一 表與表之間關系回顧
- 一對多
- 多對多
- 一對一
二 hibernate一對多操作
1 一對多映射配置
以客戶聯系人為列:客戶是一,聯系人是多
(1)創建兩個實體類,一個客戶,一個聯系人
Customer.java
package entity;
import java.util.HashSet;
import java.util.Set;
public class Customer {
private Integer cid;
private String custName;
private String custLevel;
private String custSource;
private String custPhone;
private String custMobile;
// 在客戶類里面表示多個聯系人,一個客戶有多個聯系人
//在hibernate要求使用集合表示多的數據,使用set集合
private Set<LinkMan> setlinkMan = new HashSet<LinkMan>();
public Set<LinkMan> getSetlinkMan() {
return setlinkMan;
}
public void setSetlinkMan(Set<LinkMan> setlinkMan) {
this.setlinkMan = setlinkMan;
}
public Integer getCid() {
return cid;
}
public void setCid(Integer cid) {
this.cid = cid;
}
public String getCustName() {
return custName;
}
public void setCustName(String custName) {
this.custName = custName;
}
public String getCustLevel() {
return custLevel;
}
public void setCustLevel(String custLevel) {
this.custLevel = custLevel;
}
public String getCustSource() {
return custSource;
}
public void setCustSource(String custSource) {
this.custSource = custSource;
}
public String getCustPhone() {
return custPhone;
}
public void setCustPhone(String custPhone) {
this.custPhone = custPhone;
}
public String getCustMobile() {
return custMobile;
}
public void setCustMobile(String custMobile) {
this.custMobile = custMobile;
}
}
LinkMan.java
package entity;
public class LinkMan {
private Integer lkm_id;
private String lkm_name;
private String lkm_gender;
private String lkm_phone;
//在聯系人實體類里面表示所屬客戶,一個聯系人只能屬于一個客戶
private Customer customer;
public Customer getCustomer() {
return customer;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
public Integer getLkm_id() {
return lkm_id;
}
public void setLkm_id(Integer lkm_id) {
this.lkm_id = lkm_id;
}
public String getLkm_name() {
return lkm_name;
}
public void setLkm_name(String lkm_name) {
this.lkm_name = lkm_name;
}
public String getLkm_gender() {
return lkm_gender;
}
public void setLkm_gender(String lkm_gender) {
this.lkm_gender = lkm_gender;
}
public String getLkm_phone() {
return lkm_phone;
}
public void setLkm_phone(String lkm_phone) {
this.lkm_phone = lkm_phone;
}
}
(2)讓實體類之間互相進行表示
-
在客戶實體類里面有多個聯系人
- 一個客戶里面有多個聯系人
-
在聯系人實體類里面表示所屬客戶
- 一個聯系人只能屬于一個客戶
(3)配置映射文件
- 一般一個實體類對應一個映射文件
Customer.hb,.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="entity.Customer" table="t_customer">
<id name="cid" column="cid">
<generator class="native"></generator>
</id>
<property name="custLevel" column="custLevel"></property>
<property name="custMobile" column="custMobile"></property>
<property name="custName" column="custName"></property>
<property name="custPhone" column="custPhone"></property>
<property name="custSource" column="custSource"></property>
<!--在客戶映射文件中,表示所有聯系人
使用set標簽表示所有聯系人
set標簽里面有name屬性,屬性值寫在客戶實體類里面表示聯系人的set集合
-->
<set name="setlinkMan">
<!--一對多建表,有外鍵
hibernate機制:雙向維護外鍵,在一和多那一方配置外鍵
column屬性值:外鍵名稱-->
<key column="clid"></key>
<!--客戶所有聯系人,class里面寫聯系人實體類全路徑-->
<one-to-many class="entity.LinkMan"></one-to-many>
</set>
</class>
</hibernate-mapping>
LinkMan.hbm.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="entity.LinkMan" table="t_linkman">
<id name="lkm_id" column="lkm_id">
<generator class="native"></generator>
</id>
<property name="lkm_name" column="lkm_name"></property>
<property name="lkm_gender" column="lkm_gender"></property>
<property name="lkm_phone" column="lkm_phone"></property>
<!--表示聯系人所屬客戶
name:因為聯系人在實體類使用customer對象表示,寫customer名稱
class:customer全路徑
column:外鍵名稱
-->
<many-to-one name="customer" class="entity.Customer" column="clid"></many-to-one>
</class>
</hibernate-mapping>
- 把映射最基本配置完成
- 在映射文件中,配置一對多的關系
- 在客戶映射文件中,表示所有聯系人
<!--在客戶映射文件中,表示所有聯系人
使用set標簽表示所有聯系人
set標簽里面有name屬性,屬性值寫在客戶實體類里面表示聯系人的set集合
-->
<set name="setlinkMan">
<!--一對多建表,有外鍵
hibernate機制:雙向維護外鍵,在一和多那一方配置外鍵
column屬性值:外鍵名稱-->
<key column="clid"></key>
<!--客戶所有聯系人,class里面寫聯系人實體類全路徑-->
<one-to-many class="entity.LinkMan"></one-to-many>
</set>
- 在聯系人映射文件中,表示所屬客戶
<!--表示聯系人所屬客戶
name:因為聯系人在實體類使用customer對象表示,寫customer名稱
class:customer全路徑
column:外鍵名稱
-->
<many-to-one name="customer" class="entity.Customer" column="clid"></many-to-one>
(4)創建核心配置文件
<mapping resource="Customer.hb,.xml"></mapping>
<mapping resource="LinkMan.hbm.xml"></mapping>
測試結果
數據表創建成功
2 一對多級聯操作
(1)級聯操作
- 級聯保存
添加一個客戶,為這個客戶添加多個聯系人 - 級聯刪除
刪除某一給我客戶,這個客戶里面的所有的聯系人也刪除
(2)一對多級聯保存
目標:添加客戶,為這個客戶添加一個聯系人
方法一:
import Utils.HibernateUtils;
import entity.Customer;
import entity.LinkMan;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
public class HibernateOnetoMany {
//演示一對多級聯保存
@Test
public void testAddDemo1(){
Transaction tx = null;
try{
Session session = HibernateUtils.getSessionObject();
tx= session.beginTransaction();
//添加一個客戶,為這個客戶添加一個聯系人
//1 創建客戶和聯系人對象
Customer customer = new Customer();
customer.setCustName("歐亞學院");
customer.setCustLevel("VIP");
customer.setCustSource("軟工");
customer.setCustPhone("13692127465");
customer.setCustMobile("029864564");
LinkMan linkMan = new LinkMan();
linkMan.setLkm_name("楊某人");
linkMan.setLkm_gender("男");
linkMan.setLkm_phone("130****3381");
//2 在客戶表示聯系人,在聯系人表示客戶,建立客戶對象和聯系人對象關系
//2.1 把聯系人對象放到客戶對象的set集合里面
customer.getSetlinkMan().add(linkMan);
//2.2 把客戶對象放到聯系人里面去
linkMan.setCustomer(customer);
//3 保存到數據庫
session.save(customer);
session.save(linkMan);
tx.commit();
}catch (Exception e){
e.printStackTrace();
tx.rollback();
}
}
}
聯系人表
客戶表
方法二
一般根據客戶添加聯系人
第一步 在客戶映射文件中添加配置
- 在客戶映射文件中有set標簽進行配置
配置
第二步 創建客戶和聯系人對象,只需要把聯系人放到客戶里面就可以了,最終只需要保存客戶就可以了
public void testAddDemo2(){
Transaction tx = null;
try{
Session session= HibernateUtils.getSessionObject();
tx = session.beginTransaction();
//1 創建客戶和聯系人對象
Customer customer = new Customer();
customer.setCustName("百度");
customer.setCustLevel("普通用戶");
customer.setCustSource("網絡");
customer.setCustPhone("13612227465");
customer.setCustMobile("021864564");
LinkMan linkMan = new LinkMan();
linkMan.setLkm_name("陳某人");
linkMan.setLkm_gender("女");
linkMan.setLkm_phone("130315245456");
//2 把聯系人放到客戶里面
customer.getSetlinkMan().add(linkMan);
//3 保存
session.save(customer);
tx.commit();
}catch (Exception e){
e.printStackTrace();
tx.rollback();
}
}
聯系人表
客戶表
(3)級聯刪除
需求:刪除某個客戶,把客戶里面所有的聯系人刪除
實現:
第一步 在客戶映射文件set標簽,進行配置
配置
第二步 在代碼中直接刪除客戶(根據id查詢對象,調用session里面delete方法刪除)
public void testDelDemo3(){
Transaction tx = null;
try{
Session session= HibernateUtils.getSessionObject();
tx = session.beginTransaction();
Customer customer= session.get(Customer.class,1);
session.delete(customer);
tx.commit();
}catch (Exception e){
e.printStackTrace();
tx.rollback();
}
}
用戶表
聯系人表
執行過程:
- 根據id查詢客戶
第一步
- 根據外鍵id值查詢聯系人
第二步
- 把聯系人的外鍵設置外null
第三步
- 刪除聯系人和客戶
第四步
(4)一對多修改操作
需求:讓陳某人聯系人所屬客戶不屬于百度,而是歐亞
@Test
public void testUpdateDemo4(){
Transaction tx = null;
try {
Session session = HibernateUtils.getSessionObject();
tx = session.beginTransaction();
//1 根據id查詢陳某人,根據id查百度的客戶
Customer eurasia= session.get(Customer.class,1);
LinkMan chen = session.get(LinkMan.class,2);
//2 設置持久態對象
//把聯系人放到客戶里面
eurasia.getSetlinkMan().add(chen);
//把客戶放到聯系人里面
chen.setCustomer(eurasia);
tx.commit();
}catch (Exception e){
e.printStackTrace();
tx.rollback();
}
}
數據庫
(5)inverse屬性
- 因為hibernate雙向維護外鍵,在客戶和聯系人里面都需要維護外鍵,修改客戶時候修改一次外鍵,修改聯系人時候也修改一次外鍵,造成效率問題。
外鍵修改
- 解決方式:讓其中一方不維護外鍵(一對多里面,讓其中一方放棄外鍵維護)
- 具體實現:在放棄關系維護映射文件中,進行配置,在set標簽上使用inverse屬性
inverse
說明:inverse屬性默認值,false不放棄關系維護,true表示放棄關系維護