hibernate 关联
1.一对多相互映射
public class Coustomer { private Long id; private String name; private Set<Order> orders; }
public class Order { private Long id; private String orderNumber; private Coustomer coustomer; }
<hibernate-mapping > <class name="com.liule.hibernate.Coustomer" table="coustomers"> <id name="id" column="id" type="long"> <generator class="increment"></generator> <!-- 主键生成方式 --> </id> <property name="name" type="string"> <column name="name" length="50"></column> </property> <set name="orders" cascade="save-update" inverse="true"> <key column="coustomer_id"></key> <one-to-many class="com.liule.hibernate.Order" /> </set> </class> </hibernate-mapping>
<set>元素的属性:
- name:设定待映射的持久化类的属性名
- cascade:当取值为“save-update”,表示级联保存和更新(表示随着改变,副关联的也跟着改变);“all”(保存、更新、删除)
- inverse:“true”,表示双向关联,这一端为镜像
- key:与所关联持久化类对应的表的外键。
- one-to-many:设定所关联的持久化类
<hibernate-mapping > <class name="com.liule.hibernate.Order" table="orders"> <id name="id" column="id" type="long"> <generator class="increment"></generator> <!-- 主键生成方式 --> </id> <property name="orderNumber" type="string"> <column name="order_Number" length="15"></column> </property> <many-to-one name="coustomer" class="com.liule.hibernate.Coustomer" column="customer_id" ></many-to-one> </class> </hibernate-mapping>
Coustomer coustomer = new Coustomer(); coustomer.setName("zhangsan"); coustomer.setOrders(new HashSet()); Order order1 = new Order(); order1.setOrderNumber("asda"); Order order2 = new Order(); order2.setOrderNumber("asdas"); Order order3 = new Order(); order3.setOrderNumber("asdasdfds"); order1.setCoustomer(coustomer); order2.setCoustomer(coustomer); order3.setCoustomer(coustomer); coustomer.getOrders().add(order1); coustomer.getOrders().add(order2); coustomer.getOrders().add(order3); tx = session.beginTransaction(); session.save(coustomer);//只保存客户,因为coustomer.hbm.xml里面的属性cascade="save-update",主对象改变,副队长也会改变 tx.commit();
一对多默认的加载模式为延迟加载(lazy loading),当我们在程序中获取到了一的一方,但不需要多的一方,那么使用延时加载就非常合适。
lazy="true";
Class Lazylnitiallzation Exception(异常) session关闭后,访问未被初始化的代理与集合。
2.一对多自身关联
public class Category { private Long id; private String name; private Category parentCategory; private Set<Category> childCategories; }
<hibernate-mapping > <class name="com.liule.hibernate.Category" table="categories"> <id name="id" column="id" type="long"> <generator class="increment"></generator> <!-- 主键生成方式 --> </id> <property name="name" type="string"> <column name="name" length="50"></column> </property> <set name="childCategories" cascade="all" inverse="true"> <key column="category_id"></key> <one-to-many class="com.liule.hibernate.Category" /> </set> <many-to-one name="parentCategory" class="com.liule.hibernate.Category" column="category_id" ></many-to-one> </class> </hibernate-mapping>
tx = session.beginTransaction(); Category category1 = new Category("liu",null,new HashSet<Category>()); Category category2 = new Category("liu",null,new HashSet<Category>()); Category category3 = new Category("liu",null,new HashSet<Category>()); Category category4 = new Category("liu",null,new HashSet<Category>()); Category category5 = new Category("liu",null,new HashSet<Category>()); Category category6 = new Category("liu",null,new HashSet<Category>()); Category category7 = new Category("liu",null,new HashSet<Category>()); category2.setParentCategory(category1); category3.setParentCategory(category1); category1.getChildCategories().add(category2); category1.getChildCategories().add(category3); category4.setParentCategory(category2); category5.setParentCategory(category2); category2.getChildCategories().add(category4); category2.getChildCategories().add(category5); category6.setParentCategory(category3); category7.setParentCategory(category3); category3.getChildCategories().add(category6); category3.getChildCategories().add(category7); session.save(category1); tx.commit();
3.域对象在持久化层的三种状态
- 临时状态(transient):刚刚用new语句创建,还没有被持久化,不处于Session的缓存中。
- 持久化状态(persistent):已经被持久化,加入到Session的缓存中
- 游离状态(detached):已经被持久化,但不再处于session的缓存中。
session的缓存:
- 当session的save方法持久化(将数据保存到数据库中)一个对象时,对象被加入到session缓存中,以后即便应用程序中的引用变量不再引用该对象,只要session的缓存还没有被清空,该对象仍然处于生命周期中。 session的load方法试图从数据库中加载一个对象时,session先判断缓存中是否存在这个对象,如果在,就不需要在数据库中检索。
- 清理缓存:按照缓存中对象状态的变化来同步更新数据库。当session清理缓存时,只需要执行update语句。
- 清理缓存的时间点:调用commit,先清理缓存,再提交事物;调用flush()时
update()方法:
- 把对象重新加入session缓存中,把他变成持久化对象
- 执行update语句。session只有在清理缓存时才会执行update语句。在程序中多次修改对象的属性,在清理缓存时只会执行一次update语句。
get()与load()区别:(查询时,现在session里查找,若无,则在数据库中寻找)
- get(),返回一个持久化实例,若无,则返回null;返回属性值本身,
- load(),返回一个持久化实例,若无,则抛出异常;返回代理,session关闭之前,若真正使用属性时,则生成SQL语句
4.一对一
(1)主键关联(主键值相同)
public class IdCard { private String id; private int number; private Student student; public String getId(); }
public class Student { private String id; private String name; private IdCard idCard; }
<hibernate-mapping > <class name="com.liule.hibernate.IdCard" table="IdCard"> <id name="id" column="id" type="string" > <generator class="foreign"> //利用student生成的id,再生成IdCard的id <param name="property">student</param> </generator> <!-- 主键生成方式 --> </id> <property name="number" type="int"> <column name="number" ></column> </property> <one-to-one name="Student" class="com.liule.hibernate.Student" ></one-to-one> </class> </hibernate-mapping>
<hibernate-mapping > <class name="com.liule.hibernate.Student" table="student"> <id name="id" column="id" type="string" > <generator class="uuid"></generator> <!-- 主键生成方式 --> </id> <property name="name" type="string"> <column name="name" length="50"></column> </property> <one-to-one name="idCard" class="com.liule.hibernate.IdCard" cascade="all"></one-to-one> </class> </hibernate-mapping>
public class SchemaExportTest { public static void main(String[] args) { SchemaExport export = new SchemaExport(new Configuration().configure()); export.create(true,true); } }
Student student1 = new Student(); student1.setName("sad"); IdCard idCard1 = new IdCard(); idCard1.setNumber(21212); student1.setIdCard(idCard1); idCard1.setStudent(student1); Session session = sf.openSession(); Transaction tx = null; try { tx = session.beginTransaction(); session.save(student1); tx.commit(); }
(2)外键关联。本质上一对多的蜕化形式。
<many-to-one name="student" class="com.liule.hibernate.Student" column="student—id" unique="true"> <!--只在某一个对象上设置-->
x.cfg.xml
<property name="max_fetch_depth">2</property> <!--最大抓取的深度,本例是最多查两张表-->
5.多对多
public class Student { private String id; private String name; private Set<Course> courses; }
public class Course { private String id; private String name; private Set<Student> students; }
<hibernate-mapping > <class name="com.liule.hibernate.Student" table="student"> <id name="id" column="id" type="string" > <generator class="uuid"></generator> <!-- 主键生成方式 --> </id> <property name="name" type="string"> <column name="name" length="50"></column> </property> <set name="courses" cascade="save-update" table="student_course" inverse="true"> <key column="student_id"></key> <many-to-many class="com.liule.hibernate.Course" column="course_id" ></many-to-many> </set> </class> </hibernate-mapping>
<hibernate-mapping > <class name="com.liule.hibernate.Course" table="course"> <id name="id" column="id" type="string" > <generator class="uuid"></generator> <!-- 主键生成方式 --> </id> <property name="name" type="string"> <column name="name" length="50"></column> </property> <set name="students" cascade="save-update" table="student_course" > <key column="course_id"></key> <many-to-many class="com.liule.hibernate.Student" column="student_id" ></many-to-many> </set> </class> </hibernate-mapping>
public static void main(String[] args) { // Student student1 = new Student(); // student1.setName("sad"); // // Course course1 = new Course(); // course1.setName("muise"); // // student1.setCourses(new HashSet<Course>()); // course1.setStudents(new HashSet<Student>()); // // student1.getCourses().add(course1); // Session session = sf.openSession(); Transaction tx = null; try { tx = session.beginTransaction(); Student student = (Student) session.get(Student.class,"402881eb513f9c8301513f9c86bb0000"); Course course = (Course) session.get(Course.class,"402881eb513f9c8301513f9c86ed0001"); student.getCourses().add(course); course.getStudents().add(student); // session.save(student1); tx.commit(); } catch(Exception ex) { if(null != tx) { tx.rollback(); } } finally { session.close(); } } }
补充:http://www.cnblogs.com/otomedaybreak/archive/2012/01/20/2327695.html
http://www.cnblogs.com/jyh317/p/3691842.html