首页 > 代码库 > Hibernate双向一对多映射关系(2)
Hibernate双向一对多映射关系(2)
双向 1-n 与 双向 n-1 是完全相同的两种情形
双向 1-n 需要在 1 的一端可以访问 n 的一端, 反之依然.
域模型:从 Order 到 Customer 的多对一双向关联需要在Order 类中定义一个 Customer 属性, 而在 Customer 类中需定义存放 Order 对象的集合属性
关系数据模型:ORDERS 表中的 CUSTOMER_ID 参照 CUSTOMER 表的主键
Customer.java
private Integer customerId; private String customerName; private Set<Order> orders = new HashSet<>();
1. 声明集合类型时, 需使用接口类型, 因为 hibernate 在获取
集合类型时, 返回的是 Hibernate 内置的集合类型, 而不是 JavaSE 一个标准的
集合实现.
2. 需要把集合进行初始化, 可以防止发生空指针异常
Order.java
private Integer orderId; private String orderName; private Customer customer;
Customer.hbm.xml
<set name="orders" table="ORDERS" inverse="true" order-by="ORDER_NAME DESC">
<!-- 执行多的表中的外键列的名字 -->
<key column="CUSTOMER_ID"></key>
<!-- 指定映射类型 -->
<one-to-many class="Order"/>
</set>
<!-- 映射 一 对多的那个集合属性 -->
<!-- set: 映射 set 类型的属性, table: set 中的元素对应的记录放在哪一个数据表中. 该值需要和多对一的多的那个表的名字一致 -->
<!-- inverse: 指定由哪一方来维护关联关系. 通常设置为 true, 以指定由多的一端来维护关联关系 -->
<!-- cascade 设定级联操作. 开发时不建议设定该属性. 建议使用手工的方式来处理 -->
<!-- order-by 在查询时对集合中的元素进行排序, order-by 中使用的是表的字段名, 而不是持久化类的属性名 -->
Order.java
<many-to-one name="customer" class="Customer" column="CUSTOMER_ID"></many-to-one>
HibernateTest.java
public class HibernateTest { private SessionFactory sessionFactory; private Session session; private Transaction transaction; @Before public void init(){ Configuration configuration = new Configuration().configure(); ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()) .buildServiceRegistry(); sessionFactory = configuration.buildSessionFactory(serviceRegistry); session = sessionFactory.openSession(); transaction = session.beginTransaction(); } @After public void destroy(){ transaction.commit(); session.close(); sessionFactory.close(); } @Test public void testCascade(){ Customer customer = (Customer) session.get(Customer.class, 3); customer.getOrders().clear(); } @Test public void testDelete(){ //在不设定级联关系的情况下, 且 1 这一端的对象有 n 的对象在引用, 不能直接删除 1 这一端的对象 Customer customer = (Customer) session.get(Customer.class, 1); session.delete(customer); } @Test public void testUpdat2(){ Customer customer = (Customer) session.get(Customer.class, 1); customer.getOrders().iterator().next().setOrderName("GGG"); } @Test public void testUpdate(){ Order order = (Order) session.get(Order.class, 1); order.getCustomer().setCustomerName("AAA"); } @Test public void testOne2ManyGet(){ //1. 对 n 的一端的集合使用延迟加载 Customer customer = (Customer) session.get(Customer.class, 7); System.out.println(customer.getCustomerName()); //2. 返回的多的一端的集合时 Hibernate 内置的集合类型. //该类型具有延迟加载和存放代理对象的功能. System.out.println(customer.getOrders().getClass()); //session.close(); //3. 可能会抛出 LazyInitializationException 异常 System.out.println(customer.getOrders().size()); //4. 再需要使用集合中元素的时候进行初始化. } @Test public void testMany2OneGet(){ //1. 若查询多的一端的一个对象, 则默认情况下, 只查询了多的一端的对象. 而没有查询关联的 //1 的那一端的对象! Order order = (Order) session.get(Order.class, 1); System.out.println(order.getOrderName()); System.out.println(order.getCustomer().getClass().getName()); session.close(); //2. 在需要使用到关联的对象时, 才发送对应的 SQL 语句. Customer customer = order.getCustomer(); System.out.println(customer.getCustomerName()); //3. 在查询 Customer 对象时, 由多的一端导航到 1 的一端时, //若此时 session 已被关闭, 则默认情况下 //会发生 LazyInitializationException 异常 //4. 获取 Order 对象时, 默认情况下, 其关联的 Customer 对象是一个代理对象! } @Test public void testMany2OneSave(){ Customer customer = new Customer(); customer.setCustomerName("AA"); 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); //执行 save 操作: 先插入 Customer, 再插入 Order, 3 条 INSERT, 2 条 UPDATE //因为 1 的一端和 n 的一端都维护关联关系. 所以会多出 UPDATE //可以在 1 的一端的 set 节点指定 inverse=true, 来使 1 的一端放弃维护关联关系! //建议设定 set 的 inverse=true, 建议先插入 1 的一端, 后插入多的一端 //好处是不会多出 UPDATE 语句 session.save(customer); // session.save(order1); // session.save(order2); //先插入 Order, 再插入 Cusomer, 3 条 INSERT, 4 条 UPDATE // session.save(order1); // session.save(order2); // // session.save(customer); } }
Hibernate双向一对多映射关系(2)