hibernate多對一關聯和一對多關聯
阿新 • • 發佈:2019-01-29
1. 多對一的單向關聯
從訂單(order)到客戶(customer)的單向關聯 (多個訂單對應一個客戶)
JavaBean: Customer
public class Customer{
private Integer id;
private String name;
}
JavaBean: Orderpublic class Order{
private Integer id;
private String orderNumber;
private Double price;
private Customer customer; // 建立從訂單到客戶的多對一關聯
}
customer.hbm.xml:order.hbm.xml:<hibernate-mapping> <class name="cn.itcast.many2one.Customer" table="customers"> <id name="id" type="integer"> <column name="id"></column> <generator class="increment"></generator> </id> <property name="name" type="string" access="property"> <column name="name"></column> </property> </class> </hibernate-mapping>
2. 一對多的單向關聯<hibernate-mapping> <!-- class標籤建立javabean和表之間的對映 --> <class name="cn.itcast.many2one.Order" table="orders"> <!-- id對映表中的主鍵 --> <id name="id" type="integer"> <column name="id"></column> <!-- 配置主鍵的生成策略 --> <generator class="increment"></generator> </id> <!-- property建立javabean中的屬性和表中列的對應關係 type="string": string表示的是hibernate的型別,該型別是java型別和sql型別之間的橋樑 java中的型別: String name; sql中的型別: varchar(255); 對映一個sql的varchar型別到java的String型別 --> <!-- access屬性表示對javabean屬性的訪問策略,預設值是property --> <property name="orderNumber" type="string" access="property"> <!-- column定義表中的列 --> <column name="orderNumber"></column> </property> <property name="price" type="double"> <column name="price"></column> </property> <!— <many-to-one>: 使用該標籤來對映多對一關聯 * name: 對映的持久化類中的屬性 * class: 對映的持久化類中的屬性的型別 cascade="save-update" 級聯儲存和更新 * 就是將order物件所關聯的臨時物件Customer變成持久物件 持久物件會儲存在session的一級快取中,就能插入到資料庫中 update=”false” 指的是不能用session.update(),session.saveOrUpdate()的方式更新 但是可以用hql語句進行更新 --> <many-to-one name="customer" class="cn.itcast.many2one.Customer" cascade=”save-update”> <column name="customer_id" ></column> <!-- column表示多的一方(Role)表中的外來鍵 --> </many-to-one> </class> </hibernate-mapping>
從客戶(customer)到訂單(order)的單向關聯 (一個客戶對應多個訂單)
JavaBean: Customer
public class Customer{
private Integer id;
private String name;
private Set<Order> orders = new HashSet<Order>(0); // 開始長度為0
}
JavaBean: Order
Customer.hbm.xml:public class Order{ private Integer id; private String orderNumber; private Double price; }
<hibernate-mapping>
<class name="cn.itcast.many2one.Customer" table="customers">
<id name="id" type="integer">
<column name="id"></column>
<generator class="increment"></generator>
</id>
<property name="name" type="string" access="property">
<column name="name"></column>
</property>
<!--
配置set集合
Set: 使用set標籤配置客戶對應的訂單集合
table:訂單集合中的訂單對應的表,可以不加
cascade=”save-update”: 級聯儲存和更新,當儲存customer物件時,同時要儲存customer物件多關聯的訂單集合orders集合
“delete”: 級聯刪除,刪除客戶的同時刪除訂單
inverse=”true”: 表示多的一端(order端) 為主控方法 ---> 看成”全國人民” 全國人民可以記住國家主席 (多的一端說了算)
一的一端(customer端) 不是主控方法 ---> 看成”國家主席” 國家主席是記不住全國人的
Update的時候才有效!!! 如果不寫預設的是兩邊都維護
-->
<set name=”orders” table=”orders” inverse=”true”>
<key>
<!--對應是orders表的外來鍵,可以理解為orderes集合中的訂單物件是通過orders表的外來鍵customer_id查詢出來的-->
<column name=”customer_id”/>
</key>
<!-- one-to-many表示一對多, class表示集合中存放的物件是Order物件 -->
<one-to-many class=” cn.itcast.many2one.Order”/>
</set>
</class>
</hibernate-mapping>
Order.hbm.xml:<hibernate-mapping>
<class name="cn.itcast.many2one.Order" table="orders">
<id name="id" type="integer">
<column name="id"></column>
<generator class="increment"></generator>
</id>
<property name="orderNumber" type="string" access="property">
<column name="orderNumber"></column>
</property>
<property name="price" type="double">
<column name="price"></column>
</property>
</class>
</hibernate-mapping>
3. 一對多的雙向關聯建立從Customer到Order的一對多的雙向關聯
* 從一的一端查詢關聯到多的一端
* 從多的一端查詢關聯到一的一端
* 雙向一對多和雙向多對一是兩種完全相同的情形
JavaBean: Customer
public class Customer{
private Integer id;
private String name;
private Set<Order> orders = new HashSet<Order>(0); // 開始長度為0
}
JavaBean: Orderpublic class Order{
private Integer id;
private String orderNumber;
private Double price;
private Customer customer; // 建立從訂單到客戶的多對一關聯
}
Customer.hbm.xml:<hibernate-mapping>
<class name="cn.itcast.many2one.Customer" table="customers">
<id name="id" type="integer">
<column name="id"></column>
<generator class="increment"></generator>
</id>
<property name="name" type="string" access="property">
<column name="name"></column>
</property>
<!--
配置set集合
name: Customer類的orders屬性
table: 對應表的表名
set: 使用set標籤配置客戶對應的訂單集合
table:訂單集合中的訂單對應的表,可以不加
cascade=”save-update”: 級聯儲存和更新,當儲存customer物件是,同時要儲存customer物件所關聯的訂單集合Orders集合
不要設定成cascade=”all”,因為刪除一條,其他被關聯的也會被刪除掉
inverse:是否放棄維護表關係
lazy:是否是懶載入,如果設定為false,則即使不使用它的子元素也會執行查詢,影響效率。
-->
<set name=”orders” table=”orders” cascade=”save-update”>
<key>
<!—對應是orders表的外來鍵,可以理解為orderes集合中的訂單物件是通過orders表的外來鍵customer_id查詢出來的-->
<column name=”customer_id”/>
</key>
<!-- one-to-many表示一對多, class表示集合中存放的物件是Order物件 -->
<one-to-many class=” cn.itcast.many2one.Order”/>
</set>
</class>
</hibernate-mapping>
Order.hbm.xml:<hibernate-mapping>
<class name="cn.itcast.many2one.Order" table="orders">
<id name="id" type="integer">
<column name="id"></column>
<generator class="increment"></generator>
</id>
<property name="orderNumber" type="string" access="property">
<column name="orderNumber"></column>
</property>
<property name="price" type="double">
<column name="price"></column>
</property>
<!—
<many-to-one>: 使用該標籤來對映多對一關聯
* name: 對映的持久化類中的屬性
* class: 對映的持久化類中的屬性的型別
cascade="save-update" 級聯儲存和更新
* 就是將order物件所關聯的臨時物件Customer變成持久物件
持久物件會儲存在session的一級快取中,就能插入到資料庫中
-->
<many-to-one name="customer" class="cn.itcast.many2one.Customer" cascade=”save-update”>
<column name="customer_id" ></column>
</many-to-one>
</class>
</hibernate-mapping>
public void testDoubleRaletion(){
Session session = sf.openSession();
Transaction tx = session.beginTransaction();
Order orders1=new Order();
orders1.setOrderNumber("001");
orders1.setPrice(20);
Customer c=new Customer();
c.setName("楊逍");
//建立訂單和客戶的雙向關聯
//訂單和客戶關聯
orders1.setCustomer(c);
//客戶和訂單關聯
//c.getOrders().add(orders1);
session.save(c);
session.save(orders1);
tx.commit();
session.close();
}
4.
1個javabean對映2張表
一個人在網上有多張相片
對於子表中除了外來鍵,只有一列資料, 可以建立一個JavaBean對映兩個表
表的數量一般情況下和javabean的數量保持一致,但這不是絕對的,就比如我們這個例子
建表語句:
CREATE table persons(
pid INT,
name varchar(20)
);
CREATE table imgs(
imgid INT,
img varchar(20)
);
alter table persons
add CONSTRAINT persons_pk primary key (pid);
alter table imgs
add constraint imgs_fk foreign key imgs(imgid) references persons(pid);
JavaBean:public class Person {
private Integer id;
private String name;
private Set<String> imgs = new HashSet<String>(); // 將另一個表對映成自己的一個集合
... get和set方法
}
Person.hbm.xml<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="cn.itcast.domain2">
<class name="Person" table="persons">
<id name="id" type="integer">
<column name="pid"></column>
<generator class="increment"></generator>
</id>
<property name="name" column="name" type="string"/>
<!-- 以下通過一個Set元素對映Person類中的set集合
name是指:Person類中的成員變數名,用set對映,說明它是一個Set型別的物件
table:是指Person類中的成員變數imgs的資料來自於imgs表
-->
<set name="imgs" table="imgs">
<!-- 只要指定了另一個表,必須要指定另一個表中的外銉是哪一個欄位 -->
<key column="imgid"></key>
<!-- 因為另一個表中,即imgs表中,除了外來鍵之外只有一個欄位,所以可以使用element元素影射
element的column屬性是指items.imgs屬性的值都來自於imgs表的img欄位.
-->
<element column="imgname" type="string"></element>
</set>
</class>
</hibernate-mapping>
拓展: 查詢沒有圖片的人
方法1:
select pid,pname,imgname // 查詢兩張表
from persons p left join imgs i on p.pid=i.imgid
where i.imgname is null;
方法2:
SELECT *
FROM persons
<span style="font-family:Comic Sans MS;">WHERE NOT EXISTS (SELECT * FROM imgs WHERE persons.pid=imgs.imgid);
</span>
5. bag和set的區別Set: new HashSet() - 無序, 不能重複。
Bag: new ArrayList() 用bag來對映的List是無序的集合, 可以重複
new LinkedArrayList()
配置檔案書寫略有不同:
<set name="emps" table="emp" cascade="save-update" inverse="false" lazy="true">
<key column="edept"></key>
<one-to-many class="Emp"/>
</set>
<bag name="cars" cascade="save-update" inverse="false">
<key column="c_pid"/>
<one-to-many class="Car"/>
</bag>