7、hibernate中的关联关系

发布时间:2016-12-6 22:20:11 编辑:www.fx114.net 分享查询网我要评论
本篇文章主要介绍了"7、hibernate中的关联关系",主要涉及到7、hibernate中的关联关系方面的内容,对于7、hibernate中的关联关系感兴趣的同学可以参考一下。

hbm.xml文件可以完成多种映射关系的映射 - 创建具有一对多关联关系的域模型 -创建具有一对多参照关系的关系模型 -映射一对多关联关系 -通过Hibernate API级联操纵具有关联关系的域对象。(级联操纵:一的一方删除,多的一方同时删除) 1、一对多的关联关系(一对一是一对多的特殊情况) Customer和Order的一对多双向关联(双向:你中有我,我中有你),一个用户可以有多个订单,一个订单只能属于一个用户 创建两个类: import java.util.Set; public class Customer { private Long id; private String name; private Set<Order> orders; //一对多,通过该变量可以引用到对应的Order集合对象 public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Set<Order> getOrders() { return orders; } public void setOrders(Set<Order> orders) { this.orders = orders; } }   public class Order { private Long id; private String orderNumber; private Customer customer; //多对一,通过该变量可以引用到对应的customer对象 public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getOrderNumber() { return orderNumber; } public void setOrderNumber(String orderNumber) { this.orderNumber = orderNumber; } public Customer getCustomer() { return customer; } public void setCustomer(Customer customer) { this.customer = customer; } } 创建两个数据库表: CREATE TABLE `customers` ( `ID` bigint(20) NOT NULL, `NAME` varchar(50) default NULL, PRIMARY KEY (`ID`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1;   CREATE TABLE `orders` ( `ID` bigint(20) NOT NULL, `ORDER_NUMBER` varchar(15) default NULL, `CUSTOMER_ID` bigint(20) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1; 创建对应类的hbm.xml文件: Customer.hbm.xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="com.cdtax.hibernate.Customer" table="customers"> <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="customer_id"></key> <one-to-many class="com.cdtax.hibernate.Order"/> </set> </class> </hibernate-mapping> Order.hbm.xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="com.cdtax.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="customer" class="com.cdtax.hibernate.Customer" column="customer_id"> </many-to-one> </class> </hibernate-mapping> 创建测试类: import java.util.HashSet; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; public class HibernateTest { private static SessionFactory sessionFactory; static { try { sessionFactory = new Configuration().configure() .buildSessionFactory(); } catch (Exception ex) { ex.printStackTrace(); } } public static void main(String[] args) throws Exception { Session session = sessionFactory.openSession(); Transaction tx = null; try { tx = session.beginTransaction(); Customer customer = new Customer(); customer.setName("zhangsan"); customer.setOrders(new HashSet()); Order order1 = new Order(); order1.setOrderNumber("order1"); Order order2 = new Order(); order2.setOrderNumber("order2"); Order order3 = new Order(); order3.setOrderNumber("order3"); order1.setCustomer(customer); order2.setCustomer(customer); order3.setCustomer(customer); customer.getOrders().add(order1); customer.getOrders().add(order2); customer.getOrders().add(order3); session.save(customer); tx.commit(); } catch(Exception ex) { if(null != tx) { tx.rollback(); } ex.printStackTrace(); } finally { session.close(); } } } 重点要理解的是hbm.xml文件 对于Customer.hbm.xml: <hibernate-mapping>    <class name="com.cdtax.hibernate.Customer" table="customers"> : 这一句class标签表示对类整体进行映射,name指出映射的域模型,即类名,table指出类映射到的关系模型即与哪张表映射。     <id name="id" column="id" type="long">    <generator class="increment"></generator>   </id>   id标签定义关键字,name是类的OID,column是表的主键,generator指出主键的生成方式。   <property name="name" type="string">    <column name="name" length="50"></column>   </property>   property标签定义类的普通属性映射关系,name是类的属性名,column是对应表的列名   <set name="orders" cascade="save-update" inverse="true">    <key column="customer_id"></key>    <one-to-many class="com.cdtax.hibernate.Order"/>   </set>   set是一个很关键的标签,在一对多的映射中,一的一方(这里就是指Customer类)要包含多的一方(Order类),那么一的一方的属性就应该是一个集合,所以用set来表示,set的name属性是一的一方的属性名,这里就是Customer类中的orders属性,cascade是级联关系,就是指出当我对一的一方进行保存或更新时,多的一方是否同时进行操作,可以有很多值,save-update表示同时操作,none表示不级联,等等,inverse是反转的意思,默认值为false,就是说一对多的关系由一的一方维护,如果改为true,则由多的一方维护,一般一对多的一方都设为true,即反转。   one-to-many标签指出一的一方包含多的一方的属性(应该是一个集合类型)集合中对象的类型,用class来指出集合对象的类型,对于Customer的orders属性,集合中的对象类型为Order类型。可以这样理解,看源代码定义:                   private Set<Order> orders;这里使用了泛型,所以我们一看就知道orders中保存的是Order对象,如果不使用泛型,我们看不出来,机器也无从分辨,所以class就是指出泛型的具体类型。   key子标签的column属性是指出多的一方(这里就是Order)是根据多方对应的表(orders表)的哪一列来查询的,也就是多的一方对应一的一方的外键,如我查询id为1的一方(从customers表中),因为还有一个orders属性,这个属性的值就是根据相应的查询id关联到多的一方的外键,即customer_id查询出来的。   用SQL来表示,就是第一步:select * from customers where id = 1,因为这个表里没有Order信息,所以还要:select * from orders where customer_id = 1,这里的<key column="customer_id"></key>的column值就是orders表的customer_id,外键。  </class> </hibernate-mapping>   对于Order.hbm.xml,需要注意的是 <many-to-one name="customer" class="com.cdtax.hibernate.Customer" column="customer_id">   </many-to-one> 这是关系映射中的多的一方对包含的一的一方属性的映射定义,name指出多的一方(Order)的属性名,即Order类中private Customer customer;,class相当于普通属性映射property标签中的type,定义属性类型,column定义与orders表的哪一列关联。 执行测试类HibernateTest,结果: Hibernate: select max(id) from customers Hibernate: select max(id) from orders Hibernate: insert into customers (name, id) values (?, ?) Hibernate: insert into orders (order_number, customer_id, id) values (?, ?, ?) Hibernate: insert into orders (order_number, customer_id, id) values (?, ?, ?) Hibernate: insert into orders (order_number, customer_id, id) values (?, ?, ?) 可以看出,我们只是执行了save(customer),而插入表时进行级联操作,同时将关联的3个order插入了orders表。   如果我们将Customer.hbm.xml中的set进行修改,将cascade值改为none, <set name="orders" cascade="none" inverse="true">    <key column="customer_id"></key>    <one-to-many class="com.cdtax.hibernate.Order"/>   </set> 执行结果: Hibernate: select max(id) from customers Hibernate: insert into customers (name, id) values (?, ?) 只进行了customers表的插入。 2、延迟加载 对customer进行查询: 修改HibernateTest的main方法 Session session = sessionFactory.openSession(); Customer customer = null; Transaction tx = null; try { tx = session.beginTransaction(); customer = (Customer)session.get(Customer.class, new Long(1)); tx.commit(); } catch(Exception ex) { if(null != tx) { tx.rollback(); } ex.printStackTrace(); } finally { session.close(); } System.out.println(customer.getName()); } 执行结果: Hibernate: select customer0_.id as id0_0_, customer0_.name as name0_0_ from customers customer0_ where customer0_.id=? zhangsan 只执行了一次查询 继续修改: Session session = sessionFactory.openSession(); Transaction tx = null; try { tx = session.beginTransaction(); Customer customer = (Customer)session.get(Customer.class, new Long(1)); System.out.println(customer.getName()); tx.commit(); } catch(Exception ex) { if(null != tx) { tx.rollback(); } ex.printStackTrace(); } finally { session.close(); } } 执行结果: Hibernate: select customer0_.id as id0_0_, customer0_.name as name0_0_ from customers customer0_ where customer0_.id=? zhangsan 执行了一次查询 继续修改: try { tx = session.beginTransaction(); Customer customer = (Customer)session.get(Customer.class, new Long(1)); System.out.println(customer.getName()); System.out.println(customer.getOrders()); tx.commit(); } 执行结果: Hibernate: select customer0_.id as id0_0_, customer0_.name as name0_0_ from customers customer0_ where customer0_.id=? zhangsan Hibernate: select orders0_.customer_id as customer3_1_, orders0_.id as id1_, orders0_.id as id1_0_, orders0_.order_number as order2_1_0_, orders0_.customer_id as customer3_1_0_ from orders orders0_ where orders0_.customer_id=? [[email protected], [email protected], [email protected]] 修改: Session session = sessionFactory.openSession(); Transaction tx = null; try { tx = session.beginTransaction(); Customer customer = (Customer)session.get(Customer.class, new Long(1)); System.out.println(customer.getName()); Set<Order> orders = customer.getOrders(); for(Iterator iter = orders.iterator();iter.hasNext();) { Order order =(Order) iter.next(); System.out.println(order.getOrderNumber()); } tx.commit(); } catch(Exception ex) { if(null != tx) { tx.rollback(); } ex.printStackTrace(); } finally { session.close(); } 执行结果: Hibernate: select customer0_.id as id0_0_, customer0_.name as name0_0_ from customers customer0_ where customer0_.id=? zhangsan Hibernate: select orders0_.customer_id as customer3_1_, orders0_.id as id1_, orders0_.id as id1_0_, orders0_.order_number as order2_1_0_, orders0_.customer_id as customer3_1_0_ from orders orders0_ where orders0_.customer_id=? order2 order3 order1 修改: Session session = sessionFactory.openSession(); Customer customer = null; Transaction tx = null; try { tx = session.beginTransaction(); customer = (Customer)session.get(Customer.class, new Long(1)); System.out.println(customer.getName()); tx.commit(); } catch(Exception ex) { if(null != tx) { tx.rollback(); } ex.printStackTrace(); } finally { session.close(); } Set<Order> orders = customer.getOrders(); for(Iterator iter = orders.iterator();iter.hasNext();) { Order order =(Order) iter.next(); System.out.println(order.getOrderNumber()); } } 执行结果: Hibernate: select customer0_.id as id0_0_, customer0_.name as name0_0_ from customers customer0_ where customer0_.id=? zhangsan Exception in thread "main" org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.cdtax.hibernate.Customer.orders, no session or session was closed  at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:380)  at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:372)  at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:365)  at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:108)  at org.hibernate.collection.PersistentSet.iterator(PersistentSet.java:186)  at com.cdtax.hibernate.HibernateTest.main(HibernateTest.java:112) 出现异常 修改: Session session = sessionFactory.openSession(); Customer customer = null; Transaction tx = null; try { tx = session.beginTransaction(); customer = (Customer)session.get(Customer.class, new Long(1)); System.out.println(customer.getName()); Set set = customer.getOrders(); System.out.println(set); tx.commit(); } catch(Exception ex) { if(null != tx) { tx.rollback(); } ex.printStackTrace(); } finally { session.close(); } Set<Order> orders = customer.getOrders(); for(Iterator iter = orders.iterator();iter.hasNext();) { Order order =(Order) iter.next(); System.out.println(order.getOrderNumber()); } } 结果: Hibernate: select customer0_.id as id0_0_, customer0_.name as name0_0_ from customers customer0_ where customer0_.id=? zhangsan Hibernate: select orders0_.customer_id as customer3_1_, orders0_.id as id1_, orders0_.id as id1_0_, orders0_.order_number as order2_1_0_, orders0_.customer_id as customer3_1_0_ from orders orders0_ where orders0_.customer_id=? [[email protected], [email protected], [email protected]] order1 order2 order3 3、异常:LazyInitializationException延迟初始化异常 Hibernate中的延迟加载(Lazy Loading),当我们在程序中获取到了一的一方,但是不需要多的一方,那么使用延迟加载就是非常适合的。 相对应的就是立即加载 修改hbm.xml文件: <set name="orders" cascade="save-update" inverse="true" lazy="false">    <key column="customer_id"></key>    <one-to-many class="com.cdtax.hibernate.Order"/>   </set> 加上lazy=“false”就可以实现立即加载。 4、查询多的一方: Session session = sessionFactory.openSession(); Transaction tx = null; Order order = null; Customer customer = null; try { tx = session.beginTransaction(); order = (Order)session.get(Order.class, new Long(1)); System.out.println(order.getOrderNumber()); customer = order.getCustomer(); tx.commit(); } catch(Exception ex) { if(null != tx) { tx.rollback(); } ex.printStackTrace(); } finally { session.close(); } System.out.println(customer.getName()); } 结果: Hibernate: select order0_.id as id1_0_, order0_.order_number as order2_1_0_, order0_.customer_id as customer3_1_0_ from orders order0_ where order0_.id=? order1 Exception in thread "main" org.hibernate.LazyInitializationException: could not initialize proxy - no Session  at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:132)  at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:174)  at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:190)  at com.cdtax.hibernate.Customer_$$_javassist_0.getName(Customer_$$_javassist_0.java)  at com.cdtax.hibernate.HibernateTest.main(HibernateTest.java:153) 如果将Order.hbm.xml修改: <many-to-one name="customer" class="com.cdtax.hibernate.Customer" column="customer_id" lazy="false">   </many-to-one> 结果: Hibernate: select order0_.id as id1_0_, order0_.order_number as order2_1_0_, order0_.customer_id as customer3_1_0_ from orders order0_ where order0_.id=? Hibernate: select customer0_.id as id0_0_, customer0_.name as name0_0_ from customers customer0_ where customer0_.id=? Hibernate: select orders0_.customer_id as customer3_1_, orders0_.id as id1_, orders0_.id as id1_0_, orders0_.order_number as order2_1_0_, orders0_.customer_id as customer3_1_0_ from orders orders0_ where orders0_.customer_id=? order1 zhangsan cascade取值:

上一篇:基于角色的访问控制 (RBAC)- 常见问题
下一篇:JS对象之Table表格对象

相关文章

相关评论