•双向 1-n 与双向 n-1 是完全相同的两种情形
•双向 1-n 需要在1的一端可以访问n的一端,反之依然.
测试实例代码:
实体类:
package com.elgin.hibernate.nto1both; public class Order { private int orderId; private String orderName; private Customer customer; public int getOrderId() { return orderId; } public void setOrderId(int orderId) { this.orderId = orderId; } public String getOrderName() { return orderName; } public void setOrderName(String orderName) { this.orderName = orderName; } public Customer getCustomer() { return customer; } public void setCustomer(Customer customer) { this.customer = customer; } }
package com.elgin.hibernate.nto1both; import java.util.HashSet; import java.util.Set; public class Customer { private int customerId; private String customerName; /** * 1.需要把集合初始化,可以防止发生空指针异常 * 2.声明集合时,需使用接口类型,因为hibernate在获取集合类型时 * 返回的是hibernate内置的集合类型,而不是JAVASE标准的集合实现 * * */ private Set<Order> orders=new HashSet<Order>(); public int getCustomerId() { return customerId; } public void setCustomerId(int customerId) { this.customerId = customerId; } public String getCustomerName() { return customerName; } public void setCustomerName(String customerName) { this.customerName = customerName; } public Set<Order> getOrders() { return orders; } public void setOrders(Set<Order> orders) { this.orders = orders; } }
实体类对应的hbm映射文件:
Order.hbm.xml
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <!-- Generated 2015-9-21 20:58:02 by Hibernate Tools 3.4.0.CR1 --> <hibernate-mapping package="com.elgin.hibernate.nto1both"> <class name="Order" table="ORDERS"> <id name="orderId" type="int"> <column name="ORDER_ID" /> <generator class="native" /> </id> <property name="orderName" type="java.lang.String"> <column name="ORDER_NAME" /> </property> <!-- 映射多对一关联关系 使用many-to-one映射多对一关联关系 name:多这一端关联一的那一端的属性名 class:一那一端对应的类名 column:一那一端对应多的一端对应的数据表中字段的名字 --> <many-to-one name="customer" class="Customer"> <column name="CUSTOMER_ID" /> </many-to-one> </class> </hibernate-mapping>
Customer.hbm.xml
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <!-- Generated 2015-9-21 20:58:02 by Hibernate Tools 3.4.0.CR1 --> <hibernate-mapping package="com.elgin.hibernate.nto1both"> <class name="Customer" table="CUSTOMERS"> <id name="customerId" type="int"> <column name="CUSTOMER_ID" /> <generator class="native" /> </id> <property name="customerName" type="java.lang.String"> <column name="CUSTOMER_NAME" /> </property> <!-- 映射一对多的集合属性 --> <!-- Set节点:用来映射 set类型的属性 table:set中的元素对应的记录放在那一个数据表中,该值需要跟n这一端的表名一致 key:n的这一端表中关联1的一端外键列的名字 one-to-many:指定映射类型 inverse:设定由那一方来维护关联关系,通常设置为true,指定由多的一方来维护关联关系 order-by属性:查询时对集合中的元素进行排序,属性值为标的字段名 --> <set name="orders" table="ORDERS" inverse="true" order-by=""> <key column="CUSTOMER_ID"></key> <one-to-many class="Order"/> </set> </class> </hibernate-mapping>
Junit 单元测试类:
/* *双向n-1与1-n (完全相同的2种情形) */ @Test public void testMany2OneBothSave(){ Customer customer=new Customer(); customer.setCustomerName("AAaa"); Order order1=new Order(); order1.setOrderName("order-115"); order1.setCustomer(customer); Order order2=new Order(); order2.setOrderName("order-116"); order2.setCustomer(customer); customer.getOrders().add(order1); customer.getOrders().add(order2); //先插入customer,发出3条insert语句, 2条update语句 //因为1的一端和n的一端都维护关联关系,所以会多出2条update语句 //可以在1的一端set节点指定属性inverse="true"来制定让1的一端放弃维护关联关系 //建议设定inverse="true",建议先插入1的一端,再插入多的一端 session.save(customer); session.save(order1); session.save(order2); //先插入order,发出3条insert语句, 4条update语句 ,推荐先插入 customer // session.save(order1); // session.save(order2); // session.save(customer); } @Test public void testOne2ManyBothGet(){ //1、对n的一端的集合采用延迟加在 Customer customer=(Customer) session.get(Customer.class, 1); System.out.println(customer.getCustomerName()); //2、返回的n的一端的集合类型是Hibernate内置的集合类型 // 该类型具有延迟加载和存放代理对象的功能 //3、同样在需要使用集合中元素的时候初始化,如果此时session已关闭,会抛出懒加载异常 System.out.println(customer.getOrders().getClass().getName()); }