一 表與表之間關(guān)系回顧
- 一對多
- 多對多
- 一對一
二 hibernate一對多操作
1 一對多映射配置
以客戶聯(lián)系人為列:客戶是一,聯(lián)系人是多
(1)創(chuàng)建兩個實體類,一個客戶,一個聯(lián)系人
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;
// 在客戶類里面表示多個聯(lián)系人,一個客戶有多個聯(lián)系人
//在hibernate要求使用集合表示多的數(shù)據(jù),使用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;
//在聯(lián)系人實體類里面表示所屬客戶,一個聯(lián)系人只能屬于一個客戶
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)讓實體類之間互相進行表示
-
在客戶實體類里面有多個聯(lián)系人
- 一個客戶里面有多個聯(lián)系人
-
在聯(lián)系人實體類里面表示所屬客戶
- 一個聯(lián)系人只能屬于一個客戶
(3)配置映射文件
- 一般一個實體類對應(yīng)一個映射文件
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>
<!--在客戶映射文件中,表示所有聯(lián)系人
使用set標(biāo)簽表示所有聯(lián)系人
set標(biāo)簽里面有name屬性,屬性值寫在客戶實體類里面表示聯(lián)系人的set集合
-->
<set name="setlinkMan">
<!--一對多建表,有外鍵
hibernate機制:雙向維護外鍵,在一和多那一方配置外鍵
column屬性值:外鍵名稱-->
<key column="clid"></key>
<!--客戶所有聯(lián)系人,class里面寫聯(lián)系人實體類全路徑-->
<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>
<!--表示聯(lián)系人所屬客戶
name:因為聯(lián)系人在實體類使用customer對象表示,寫customer名稱
class:customer全路徑
column:外鍵名稱
-->
<many-to-one name="customer" class="entity.Customer" column="clid"></many-to-one>
</class>
</hibernate-mapping>
- 把映射最基本配置完成
- 在映射文件中,配置一對多的關(guān)系
- 在客戶映射文件中,表示所有聯(lián)系人
<!--在客戶映射文件中,表示所有聯(lián)系人
使用set標(biāo)簽表示所有聯(lián)系人
set標(biāo)簽里面有name屬性,屬性值寫在客戶實體類里面表示聯(lián)系人的set集合
-->
<set name="setlinkMan">
<!--一對多建表,有外鍵
hibernate機制:雙向維護外鍵,在一和多那一方配置外鍵
column屬性值:外鍵名稱-->
<key column="clid"></key>
<!--客戶所有聯(lián)系人,class里面寫聯(lián)系人實體類全路徑-->
<one-to-many class="entity.LinkMan"></one-to-many>
</set>
- 在聯(lián)系人映射文件中,表示所屬客戶
<!--表示聯(lián)系人所屬客戶
name:因為聯(lián)系人在實體類使用customer對象表示,寫customer名稱
class:customer全路徑
column:外鍵名稱
-->
<many-to-one name="customer" class="entity.Customer" column="clid"></many-to-one>
(4)創(chuàng)建核心配置文件
<mapping resource="Customer.hb,.xml"></mapping>
<mapping resource="LinkMan.hbm.xml"></mapping>

測試結(jié)果

數(shù)據(jù)表創(chuàng)建成功
2 一對多級聯(lián)操作
(1)級聯(lián)操作
- 級聯(lián)保存
添加一個客戶,為這個客戶添加多個聯(lián)系人 - 級聯(lián)刪除
刪除某一給我客戶,這個客戶里面的所有的聯(lián)系人也刪除
(2)一對多級聯(lián)保存
目標(biāo):添加客戶,為這個客戶添加一個聯(lián)系人
方法一:
import Utils.HibernateUtils;
import entity.Customer;
import entity.LinkMan;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
public class HibernateOnetoMany {
//演示一對多級聯(lián)保存
@Test
public void testAddDemo1(){
Transaction tx = null;
try{
Session session = HibernateUtils.getSessionObject();
tx= session.beginTransaction();
//添加一個客戶,為這個客戶添加一個聯(lián)系人
//1 創(chuàng)建客戶和聯(lián)系人對象
Customer customer = new Customer();
customer.setCustName("歐亞學(xué)院");
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 在客戶表示聯(lián)系人,在聯(lián)系人表示客戶,建立客戶對象和聯(lián)系人對象關(guān)系
//2.1 把聯(lián)系人對象放到客戶對象的set集合里面
customer.getSetlinkMan().add(linkMan);
//2.2 把客戶對象放到聯(lián)系人里面去
linkMan.setCustomer(customer);
//3 保存到數(shù)據(jù)庫
session.save(customer);
session.save(linkMan);
tx.commit();
}catch (Exception e){
e.printStackTrace();
tx.rollback();
}
}
}

聯(lián)系人表

客戶表
方法二
一般根據(jù)客戶添加聯(lián)系人
第一步 在客戶映射文件中添加配置
- 在客戶映射文件中有set標(biāo)簽進行配置

配置
第二步 創(chuàng)建客戶和聯(lián)系人對象,只需要把聯(lián)系人放到客戶里面就可以了,最終只需要保存客戶就可以了
public void testAddDemo2(){
Transaction tx = null;
try{
Session session= HibernateUtils.getSessionObject();
tx = session.beginTransaction();
//1 創(chuàng)建客戶和聯(lián)系人對象
Customer customer = new Customer();
customer.setCustName("百度");
customer.setCustLevel("普通用戶");
customer.setCustSource("網(wǎng)絡(luò)");
customer.setCustPhone("13612227465");
customer.setCustMobile("021864564");
LinkMan linkMan = new LinkMan();
linkMan.setLkm_name("陳某人");
linkMan.setLkm_gender("女");
linkMan.setLkm_phone("130315245456");
//2 把聯(lián)系人放到客戶里面
customer.getSetlinkMan().add(linkMan);
//3 保存
session.save(customer);
tx.commit();
}catch (Exception e){
e.printStackTrace();
tx.rollback();
}
}

聯(lián)系人表

客戶表
(3)級聯(lián)刪除
需求:刪除某個客戶,把客戶里面所有的聯(lián)系人刪除
實現(xiàn):
第一步 在客戶映射文件set標(biāo)簽,進行配置

配置
第二步 在代碼中直接刪除客戶(根據(jù)id查詢對象,調(diào)用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();
}
}

用戶表

聯(lián)系人表
執(zhí)行過程:
- 根據(jù)id查詢客戶

第一步
- 根據(jù)外鍵id值查詢聯(lián)系人

第二步
- 把聯(lián)系人的外鍵設(shè)置外null

第三步
- 刪除聯(lián)系人和客戶

第四步
(4)一對多修改操作
需求:讓陳某人聯(lián)系人所屬客戶不屬于百度,而是歐亞
@Test
public void testUpdateDemo4(){
Transaction tx = null;
try {
Session session = HibernateUtils.getSessionObject();
tx = session.beginTransaction();
//1 根據(jù)id查詢陳某人,根據(jù)id查百度的客戶
Customer eurasia= session.get(Customer.class,1);
LinkMan chen = session.get(LinkMan.class,2);
//2 設(shè)置持久態(tài)對象
//把聯(lián)系人放到客戶里面
eurasia.getSetlinkMan().add(chen);
//把客戶放到聯(lián)系人里面
chen.setCustomer(eurasia);
tx.commit();
}catch (Exception e){
e.printStackTrace();
tx.rollback();
}
}

數(shù)據(jù)庫
(5)inverse屬性
- 因為hibernate雙向維護外鍵,在客戶和聯(lián)系人里面都需要維護外鍵,修改客戶時候修改一次外鍵,修改聯(lián)系人時候也修改一次外鍵,造成效率問題。

外鍵修改
- 解決方式:讓其中一方不維護外鍵(一對多里面,讓其中一方放棄外鍵維護)
- 具體實現(xiàn):在放棄關(guān)系維護映射文件中,進行配置,在set標(biāo)簽上使用inverse屬性

inverse
說明:inverse屬性默認(rèn)值,false不放棄關(guān)系維護,true表示放棄關(guān)系維護