Hibernate之对象关系映射
一、一對多關(guān)聯(lián)關(guān)系
1.單向n-1
-
單向n-1關(guān)聯(lián)只需從n的一端可以訪問1的一端
-
Hibernate使用<many-to-one>元素來映射多對一關(guān)聯(lián)關(guān)系
-
實例:
Customer.java
public class Customer { ?private Integer customerId;private String customerName; }Order.java
public class Order {private Integer orderId;private String orderName; }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"> ? <hibernate-mapping><class name="com.yfy.hibernate.entity.n21.Customer" table="CUSTOMERS"><id name="customerId" type="java.lang.Integer"><column name="CUSTOMER_ID" /><generator class="native" /></id><property name="customerName" type="java.lang.String"><column name="CUSTOMER_NAME" /></property></class></hibernate-mapping>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"> ? <hibernate-mapping package="com.yfy.hibernate.entity.n21"> ?<class name="Order" table="ORDERS"> ?<id name="orderId" type="java.lang.Integer"><column name="ORDER_ID" /><generator class="native" /></id><property name="orderName" type="java.lang.String"><column name="ORDER_NAME" /></property><many-to-one name="customer" class="Customer" column="CUSTOMER_ID"></many-to-one> ?</class> </hibernate-mapping>HibernateTest.java
public class HibernateTest { ?private SessionFactory sessionFactory;private Session session;private Transaction transaction;@Beforepublic 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();}@Afterpublic void destroy(){transaction.commit();session.close();sessionFactory.close();} ? ?@Testpublic void testDelete(){//在不設(shè)定級聯(lián)關(guān)系的情況下, 且 1 這一端的對象有 n 的對象在引用, 不能直接刪除 1 這一端的對象Customer customer = (Customer) session.get(Customer.class, 1);session.delete(customer); }@Testpublic void testUpdate(){Order order = (Order) session.get(Order.class, 1);order.getCustomer().setCustomerName("AAA");}@Testpublic void testMany2OneGet(){//1. 若查詢多的一端的一個對象, 則默認(rèn)情況下, 只查詢了多的一端的對象. 而沒有查詢關(guān)聯(lián)的//1 的那一端的對象!Order order = (Order) session.get(Order.class, 1);System.out.println(order.getOrderName()); System.out.println(order.getCustomer().getClass().getName()); ?session.close(); ?//2. 在需要使用到關(guān)聯(lián)的對象時, 才發(fā)送對應(yīng)的 SQL 語句.Customer customer = order.getCustomer();System.out.println(customer.getCustomerName()); ?//3. 在查詢 Customer 對象時, 由多的一端導(dǎo)航到 1 的一端時,//若此時 session 已被關(guān)閉, 則默認(rèn)情況下//會發(fā)生 LazyInitializationException 異常//4. 獲取 Order 對象時, 默認(rèn)情況下, 其關(guān)聯(lián)的 Customer 對象是一個代理對象!}@Testpublic void testMany2OneSave(){Customer customer = new Customer();customer.setCustomerName("BB");Order order1 = new Order();order1.setOrderName("ORDER-3");Order order2 = new Order();order2.setOrderName("ORDER-4");//設(shè)定關(guān)聯(lián)關(guān)系order1.setCustomer(customer);order2.setCustomer(customer);//執(zhí)行 save 操作: 先插入 Customer, 再插入 Order, 3 條 INSERT//先插入 1 的一端, 再插入 n 的一端, 只有 INSERT 語句. // session.save(customer); // // session.save(order1); // session.save(order2);//先插入 Order, 再插入 Customer. 3 條 INSERT, 2 條 UPDATE//先插入 n 的一端, 再插入 1 的一端, 會多出 UPDATE 語句!//因為在插入多的一端時, 無法確定 1 的一端的外鍵值. 所以只能等 1 的一端插入后, 再額外發(fā)送 UPDATE 語句.//推薦先插入 1 的一端, 后插入 n 的一端 ?session.save(order1);session.save(order2); ?session.save(customer);} }2.雙向1-n
-
雙向1-n需要在1的一端可以訪問n的一端,反之亦然
-
Hibernate使用<set>元素來映射set類型的屬性
-
當(dāng)Session從數(shù)據(jù)庫中加載Java集合時,創(chuàng)建的是Hibernate內(nèi)置集合類的實例,因此在持久化類中定義集合屬性時必須把屬性聲明為Java接口類型
-
Hibernate的內(nèi)置集合類具有集合代理功能,支持延遲檢索策略
-
-
在定義集合屬性時,通常把它初始化為集合實現(xiàn)類的一個實例,這樣可以提高程序的健壯性,避免NullPointerException
-
實例
Customer.java
public class Customer { ?private Integer customerId;private String customerName;/** 1. 聲明集合類型時, 需使用接口類型, 因為 hibernate 在獲取* 集合類型時, 返回的是 Hibernate 內(nèi)置的集合類型, 而不是 JavaSE 一個標(biāo)準(zhǔn)的* 集合實現(xiàn). * 2. 需要把集合進(jìn)行初始化, 可以防止發(fā)生空指針異常*/private Set<Order> orders = new HashSet<>(); }Order.java
public class Order {private Integer orderId;private String orderName;private Customer customer; }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"> ? <hibernate-mapping package="com.yfy.hibernate.entity.n21"><class name="Customer" table="CUSTOMERS"><id name="customerId" type="java.lang.Integer"><column name="CUSTOMER_ID" /><generator class="native" /></id><property name="customerName" type="java.lang.String"><column name="CUSTOMER_NAME" /></property><!-- 映射 1 對多的那個集合屬性 --><!-- set: 映射 set 類型的屬性, table: set 中的元素對應(yīng)的記錄放在哪一個數(shù)據(jù)表中. 該值需要和多對一的多的那個表的名字一致 --><!-- inverse: 指定由哪一方來維護(hù)關(guān)聯(lián)關(guān)系. 通常設(shè)置為 true, 以指定由多的一端來維護(hù)關(guān)聯(lián)關(guān)系 --><!-- cascade 設(shè)定級聯(lián)操作. 開發(fā)時不建議設(shè)定該屬性. 建議使用手工的方式來處理 --><!-- order-by 在查詢時對集合中的元素進(jìn)行排序, order-by 中使用的是表的字段名, 而不是持久化類的屬性名 --><set name="orders" table="ORDERS" inverse="true" order-by="ORDER_NAME DESC"><!-- 執(zhí)行多的表中的外鍵列的名字 --><key column="CUSTOMER_ID"></key><!-- 指定映射類型 --><one-to-many class="Order"/></set></class></hibernate-mapping>其余同1對多的代碼。。。
二、多對多關(guān)聯(lián)關(guān)系
1.單向n-n
-
n-n的關(guān)聯(lián)必須使用連接表
-
與1-n類似,必須為set集合元素添加key子元素,集合中的元素使用many-to-many
Category.java
public class Category { ?private Integer id;private String name;private Set<Item> items = new HashSet<>(); }Item.java
public class Item { ?private Integer id;private String name;private Set<Category> categories = new HashSet<>(); }Category.hbm.xml
? ? ? ?<!-- table: 指定中間表 --><set name="items" table="CATEGORIES_ITEMS"><key><column name="C_ID" /></key><!-- 使用 many-to-many 指定多對多的關(guān)聯(lián)關(guān)系. column 執(zhí)行 Set 集合中的持久化類在中間表的外鍵列的名稱 --><many-to-many class="Item" column="I_ID"></many-to-many></set>2.雙向n-n
-
雙向n-n關(guān)聯(lián)需要兩端都使用集合屬性
-
雙向n-n關(guān)聯(lián)必須使用連接表
-
集合屬性增加key子元素映射外鍵列,many-to-many子元素關(guān)聯(lián)實體類
-
對于雙向n-n關(guān)聯(lián),必須把其中一端的inverse設(shè)置為true,否則兩端都維護(hù)關(guān)聯(lián)關(guān)系可能會造成主鍵沖突
Item.hbm.xml
?<set name="categories" table="CATEGORIES_ITEMS" inverse="true"><key column="I_ID"></key><many-to-many class="Category" column="C_ID"></many-to-many></set>?
總結(jié)
以上是生活随笔為你收集整理的Hibernate之对象关系映射的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Hibernate之对象关系映射文件
- 下一篇: Hibernate之检索策略