首页 > 学院 > 开发设计 > 正文

Hibernate4-5 映射一对多关联关系

2019-11-08 00:59:30
字体:
来源:转载
供稿:网友

  在领域模型中,类与类之间最普遍的关系是关联关系,而在UML中关联是有方向的。以Customer类和Order类为例,从Order到Customer的关联是多对一关联,而从Customer到Order的关联则是一对多关联,两者均属于单向关联。


1. 单向n-1关联

  概念:单向n-1关联只需从n的一端可以访问1的一端即可。 这里写图片描述

1.1 对象关系映射

  显然,无法直接使用PRoperty元素来映射Order类的customer属性,Hibernate提供many-to-one元素来映射多对一关联关系。示例如下:

<!-- 映射单向n-1映射关系:CUSTOMER_ID为ORDERS表中的外键 实现:使用<many-to-one>元素来映射关联关系,其具体属性说明如下: name: 设定待映射的持久化类的属性的名字 class:设定待映射的持久化类的属性的类型 column: 设定和持久化类的属性对应的表的外键 --><many-to-one name="customer" class="Customer" column="CUSTOMER_ID" not-null="true"></many-to-one>

1.2 数据库操作

public class HibernateTest { private sessionFactory sessionFactory; // 单实例的 private Session session; // 项目中不能声明为成员变量,可能会有并发问题 private Transaction transaction; // 项目中不能声明为成员变量,可能会有并发问题 @Before public void init() { // 创建Session对象并开启事务 Configuration configuration = new Configuration().configure(); ServiceRegistry serviceRegistry = new ServiceRegistryBuilder() .applySettings(configuration.getProperties()) .buildServiceRegistry(); sessionFactory = configuration.buildSessionFactory(serviceRegistry); session = sessionFactory.openSession(); transaction = session.beginTransaction(); } @Test public void testManyToOneSave() { Customer customer = new Customer(); customer.setCustomerName("qiaobc"); Order order1 = new Order(); order1.setOrderName("Order-1"); Order order2 = new Order(); order2.setOrderName("Order-2"); // 设定关联关系 order1.setCustomer(customer); order2.setCustomer(customer); // 1. 先1后n:只有3条INSERT语句;// session.save(customer);// session.save(order1);// session.save(order2); // 2. 先n后1:3条INSERT语句后有2条更新语句; session.save(order1); session.save(order2); session.save(customer); } @Test public void testManyToOneGet() { // 1. 查询n的一端的对象时,默认不会查询与其关联的1的一端的对象 Order order = (Order) session.get(Order.class, 1); System.out.println(order.getOrderName()); // 4. 仅获取n的一端的对象时,默认情况下其关联的1的一端的对象是一个代理对象 // com.qiaobc.hibernate.entities.n21.Customer_$$_javassist_3 System.out.println(order.getCustomer().getClass().getName()); // 不会查询关联对象 // 3. 在查询关联对象时,若session关闭,则默认情况下会抛出org.hibernate.LazyInitializationException异常 // session.close(); // 2. 若需要使用关联对象时,才发送SELECT语句 System.out.println(order); } @Test public void testManyToOneUpdate() { // 2条SELECT语句,1条UPDATE语句 Order order = (Order) session.get(Order.class, 1); order.getCustomer().setCustomerName("qiaob"); } @Test public void testManyToOneDelete() { // 在未设定级联关系的情况下,1的一端的对象有n的一端对象在引用,故其不能删除 Customer customer = (Customer) session.get(Customer.class, 1); session.delete(customer); } @After public void destory() { transaction.commit(); session.close(); sessionFactory.close(); }}

2. 双向1-n关联

  概念:双向1-n与双向 n-1是完全相同的两种情形,即需要在1的一端可以访问n的一端,反之依然。 这里写图片描述

2.1 对象关系映射

  在双向1-n关联关系中,既需要在1的一端配置一对多映射关系(set元素),又需要在n的一端配置多对一映射关系(many-to-one元素)。示例如下:

<!-- 1. 在Order.hbm.xml中:配置n-1映射关系 --><many-to-one name="customer" class="Customer" column="CUSTOMER_ID"></many-to-one><!-- 2. 在Customer.hbm.xml中:配置1-n映射关系 --><set name="orders" table="ORDERS"> <key column="CUSTOMER_ID"></key> <one-to-many class="Order"/></set>

2.2 1-n集合声明

这里写图片描述

2.3 数据库操作 

public class HibernateTest { private SessionFactory sessionFactory; // 单实例的 private Session session; // 项目中不能声明为成员变量,可能会有并发问题 private Transaction transaction; // 项目中不能声明为成员变量,可能会有并发问题 @Before public void init() { // 创建Session对象并开启事务 Configuration configuration = new Configuration().configure(); ServiceRegistry serviceRegistry = new ServiceRegistryBuilder() .applySettings(configuration.getProperties()) .buildServiceRegistry(); sessionFactory = configuration.buildSessionFactory(serviceRegistry); session = sessionFactory.openSession(); transaction = session.beginTransaction(); } @Test public void testManyToOneSave() { Customer customer = new Customer(); customer.setCustomerName("qiaobc"); Order order1 = new Order(); order1.setOrderName("Order-1"); Order order2 = new Order(); order2.setOrderName("Order-2"); // 设定关联关系 order1.setCustomer(customer); order2.setCustomer(customer); customer.getOrders().add(order1); // 需要在持久化类中对集合属性进行初始化 customer.getOrders().add(order2); // 1. 先1后n:3条INSERT语句,2条UPDATE语句,因为均需要维护关联关系 // 注意:可以设置1的一端的set属性inverse="true",使其放弃维护关联关系// session.save(customer);// session.save(order1);// session.save(order2); // 2. 先n后1:3条INSERT语句,4条UPDATE语句,因为均需要维护关联关系 session.save(order1); session.save(order2); session.save(customer); } @Test public void testManyToOneGet() { // 1. 查询n的一端的对象时,默认不会查询与其关联的1的一端的对象 Order order = (Order) session.get(Order.class, 1); System.out.println(order.getOrderName()); // 4. 仅获取n的一端的对象时,默认情况下其关联的1的一端的对象是一个代理对象 // com.qiaobc.hibernate.entities.n21.Customer_$$_javassist_3 System.out.println(order.getCustomer().getClass().getName()); // 不会查询关联对象 // 3. 在查询关联对象时,若session关闭,则默认情况下会抛出org.hibernate.LazyInitializationException异常 // session.close(); // 2. 若需要使用关联对象时,才发送SELECT语句 System.out.println(order); } @Test public void testOneToManyGet() { // 1. 对n的一端的集合延迟加载 Customer customer = (Customer) session.get(Customer.class, 1); System.out.println(customer.getCustomerName()); // 2. 需要在持久化类中定义集合类型为Java接口类型 // org.hibernate.collection.internal.PersistentSet: // Hibernate内置的集合类型,具有延迟加载和存放代理对象的功能 System.out.println(customer.getOrders().getClass().getName()); // 3. 可能会抛出org.hibernate.LazyInitializationException异常// session.close();// System.out.println(customer.getOrders().size()); // 4. 在需要使用集合中元素的时候才进行初始化。 } @Test public void testManyToOneUpdate() { // 2条SELECT语句,1条UPDATE语句 Order order = (Order) session.get(Order.class, 1); order.getCustomer().setCustomerName("qiaob"); } @Test public void testManyToOneUpdate2() { Customer customer = (Customer) session.get(Customer.class, 1); customer.getOrders().iterator().next().setOrderName("qiaobei"); } @Test public void testManyToOneDelete() { // 在未设定级联关系的情况下,1的一端的对象有n的一端对象在引用,故其不能删除 Customer customer = (Customer) session.get(Customer.class, 1); session.delete(customer); } @After public void destory() { transaction.commit(); session.close(); sessionFactory.close(); }}

3. set元素

这里写图片描述

3.1 inverse属性

  Hibernate中通过inverse属性来决定是由双向关联的哪一方来维护表与表之间的级联关系,默认情况下父子双方均会维护父子关系(保存操作时会多出UPDATE语句)。   实现:通过设置inverse=true使当前方为被动方,即不维护级联关系。   注意:在双向1-n关系中,将n的一方设置为主动方将有助于性能改善。

3.2 cascade属性

  了解:在对象关系映射文件中,用于映射持久化类之间关联关系的元素都有cascade属性,用于指定如何操纵与当前对象关联的其他对象.。 这里写图片描述

3.3 在数据库中对集合排序

  order-by属性可使Hibernate在检索集合对象时,利用order by子句对集合进行排序,该属性中还可以加入SQL函数。 这里写图片描述


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表