Hibernate(七)__多對一 、一對多、 一對一、多對多

来源:http://www.cnblogs.com/xiangkejin/archive/2016/10/27/6002467.html
-Advertisement-
Play Games

1.many-to-one 以學生和部門之間的關係為例: Department.hbm.xml student.hbm.xml 應用: Student stu1=new Student(); stu.setName("宋江"); Student stu2=new Student();stu.setN ...


1.many-to-one

以學生和部門之間的關係為例:

Department.hbm.xml

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.xidian.domain">
<class name="Department" lazy="false">
<!-- 配置主鍵屬性 -->
<id name="id" type="java.lang.Integer">
<!-- 生成策略 -->
<generator class="identity">
</generator>
</id>
<property name="name" type="java.lang.String">
<column name="name" length="64" not-null="true"/>
</property>
</class>
</hibernate-mapping>

student.hbm.xml

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.xidian.domain">
<class name="Student">
<id name="id" type="java.lang.Integer"> 
<generator class="identity">
</generator>
</id>
<property name="name" type="java.lang.String">
<column name="name" length="64"/>
</property>
<!-- 對於private Department dept;就不能使用property 
  column="dept_id" 表示將來自動生成的表的外鍵名-->
<many-to-one name="dept" column="dept_id"/>
</class>
</hibernate-mapping>

應用:

Student stu1=new Student();
stu.setName("宋江");

Student stu2=new Student();
stu.setName("宋江");

Department d=new Department();
d.setName("財務部");

stu1.setDept(d);//指定該學生是哪個部門

stu2.setDept(d);

s.save(d);
s.save(stu1);
s.save(stu2);
如果先保存學生再保存部門,也是可以的。在保存學生的時候部門還不存在,外鍵會設置為空,然後再保存部門,當commit提交事務的

時候發現它們具有映射關係,就會再來設置學生的外鍵引用(這種情況下hibernate會多一條update語句)。

 

在應用多對一的情況時會發現,只做了many到one單方向的映射,只是能將多個學生通過外鍵關係添加到一個部門中

問題:反過來如果需要通過一個部門號(1),來獲取該部門的所有學生?如果用上面的many to one形式需要hql語句進行查詢

String hql=”from Student where dept.id=1”

這時就需要one-to-many的反方向查詢

 

在這裡引入懶載入的概念:

簡述: 多表查詢時,當我們查詢一個對象的時候,在預設情況下,返回的只是該對象的普通屬性,當用戶去使用對象屬性時,

才會向資料庫發出再一次的查詢.這種現象我們稱為 lazy現象.

student=(Student) s.get(Student.class, 3);

System.out.println(student1.getName()+" 所在部門="
      +student1.getDept().getName());//當session還在,依然可以向資料庫發sql語句。可是假若我們只是獲取到student對象,

                   //沒有對對象屬性進行查詢,當session關閉後就不可以再向資料庫發sql語句,無法查詢。

解決方法

1.顯示初始化代理對象 Hibernate.initized( student.getdept()) 

2.修改對象關係文件 class屬性 lazy  改寫 lazy=false

3.通過過濾器(web項目) openSessionInView     (從上面的例子可以看出,當session關閉後,就不能向資料庫發sql語句,那麼就擴大session的範圍

                    這個後面會詳細介紹)

 

2.one-to-many

在one那一方配置<set ></set>

在many一方必須要一個外鍵指向one這方的屬性,所以配置<many-to-one>是必須的。

one這方是否配置<one-to-many>看是否需要指定一個集合屬性指向回many一方,這樣從主表一方獲取從表的屬性是非常方便的。

在這裡再看通過獲取到部門查看學生信息

Department department1=(Department) s.get(Department.class, 3);
//取出該部門的學生
Set<Student> stus= department1.getStus();
for(Student ss: stus){
System.out.println(ss.getName());

}

 

添加學生
Department department=new Department();
department.setName("業務部門");

Student stu1=new Student();
stu1.setName("順平");
Student stu2=new Student();
stu2.setName("小明");

Set<Student> sets=new HashSet<Student>();
sets.add(stu1);
sets.add(stu2);
department.setStus(sets);

s.save(department);              //這裡涉及到級聯操作,需要在Department.hbml.xml中配置

               //<set name="stus" cascade="save-update">這樣將在保存department的時候將

               //部門中的學生一併保存。

 

3.one-to-one

一對一有有兩種方式  區別是基於主鍵的情況是會在主鍵之間形成映射關係

(從表的某一屬性既是自身表的主鍵也是引用到其他表的外鍵,主鍵充當外鍵),基於外鍵是以非主鍵的外鍵形成映射關係。

(1) 基於主鍵的一對一

一定要設置constrained=true 才能形成外鍵約束關係

一對一關係中典型的問題是人與身份證的關係。

Person p1=new Person();
p1.setId(1224);
p1.setName("xkj");

IdCard idCard=new IdCard();
idCard.setValidateDte(new Date());

idCard.setPerson(p1);//表示idCard對象是屬於p1這個對象.
           //p1.setIdCard(idCard);錯誤方式
s.save(p1);     //先保存人
s.save(idCard);

資料庫中結果:

idCard表

person表

這裡有兩個註意問題

1.如果我使用p1.setIdCard(idCard)來指定person和idCard之間的關係會出錯:

只能使用idCard.setPerson(p1)方式。關係應該是在idCard上有一個外鍵指向person,而不是相反。報錯行在

說明在保存idCard的時候,外鍵person屬性是空而導致錯誤。

2.如果調換保存順序:

s.save(idCard); //先保存卡

s.save(p1);  

報出錯誤:

 java.sql.SQLException: [Microsoft][SQLServer 2000 Driver for JDBC][SQLServer]

INSERT 語句與 FOREIGN KEY 約束"FKB8CDF6CB2A59F864"衝突。該衝突發生於資料庫"test",表"dbo.person", column 'id'。  
解析理論:外鍵約束,比如B表存在一個欄位b,有外鍵約束,引用於A表的主鍵a,那麼在向B表插入數據時,

欄位b必須為A表中a已經存在的值,如過向b中存放一個a中沒有的值,則會報違反外鍵約束。

可是如果回頭看one-to-many那個例子中卻發現學生表中有外鍵指向部門的主鍵,先保存學生再保存部門也是可以的,

只是會多一個update語句,這是hibernate的優化機制。可是放在這個地方卻不可以,why?

希望大家指點填坑!

 

(二)基於外鍵的一對一

只改動上面的IdCard.hbm.xml映射文件

<id name=”id” type=”java.lang.Integer”>

<generator class=”assigned” />  

</id>

<property ame=”VaidateDate” type=”java.util.Date”>

<column name=”validateDate” />

</property>

<many-to-one  name=”person”  unique=”true” />   //person是外鍵 在idCard表中會生成這個外鍵,它指向的是主表的主id

在idCard這邊,可看成是many-to-one的一個特例,加unique保證唯一。

Person p1=new Person();
p1.setId(122);
p1.setName("xkj");

IdCard idCard=new IdCard();
idCard.setId(1905);
idCard.setValidateDte(new Date());

idCard.setPerson(p1);//表示idCard對象是屬於p1這個對象.

s.save(p1); //先保存人
s.save(idCard);

資料庫結果:

在這裡我依然測試了前面出現的兩個問題:

第一個問題沒有報錯,只是idCard的person外鍵為空。

第二個問題hibernate又給解決了,同樣是多一句update語句。

 

4.many-to-many

學生和課程是經典的多對多的案例。

在實際開發中,如果出現了many-to-many關係,我們應該將其轉換成兩個one-to-many 或者 many-to-on, 這個程式好控制,同時不會有冗餘。

在stucourse中有兩個外鍵分別指向student和course

//添加一個學生,一門課程,選課
Student stu1=new Student();
stu1.setName("小明");

Course course=new Course();
course.setName("java");

StuCourse sc=new StuCourse();

sc.setCourse(course);
sc.setStudent(stu1);

//順序保存.
s.save(stu1);
s.save(course);
s.save(sc);

資料庫結果:


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 如果對什麼是線程、什麼是進程仍存有疑惑,請先Google之,因為這兩個概念不在本文的範圍之內。 用多線程只有一個目的,那就是更好的利用cpu的資源,因為所有的多線程代碼都可以用單線程來實現。說這個話其實只有一半對,因為反應“多角色”的程式代碼,最起碼每個角色要給他一個線程吧,否則連實際場景都無法模擬 ...
  • Java類庫里有四個表示流的抽象類:InputStream、OutputStream、Reader、Writer。 其中 InputStream 和 OutputStream 是對位元組進行操作的輸入流和輸出流;Reader 和 Writer 是對字元操作的輸入輸出流。 它們是抽象類,在用它們的時候必 ...
  • 英文文檔: format(value[, format_spec]) Convert a value to a “formatted” representation, as controlled by format_spec. The interpretation of format_spec wi ...
  • ArrayDeque 數組迴圈隊列,這個數據結構設計的挺有意思的。 據說此類很可能在用作堆棧時快於 Stack,在用作隊列時快於 LinkedList。 一、容量 1.1預設容量是8=2^3 1.2指定初始化容容量 此方法是給數組分配初始容量,初始容量並不是numElements,而是大於指定長度的 ...
  • `EditFileEntryAction.java` 文件路徑在資料庫中的dlfileentry中存儲,與bundle/data/document_library的對應關係如下: | Table Column | companyid | folderid | treepath | name | | ...
  • 瞭解面向對象思想的同學們,都知道“封裝”這一基本特征,如何正確運用訪問修飾符,恰恰能體現出封裝的好壞。 java訪問修飾符有四個: 1)public:訪問許可權最高,其修飾的類、類變數、方法所有類都可見。 2)protected:其修飾的類、類變數、方法在同包中(包括同類)可見,不同包的子類可見。 3 ...
  • 最大子段和: 最長遞增子序列: 最長迴文串: ...
  • 兩個函數作用都是合併數組。參數可以是1到n個數組。(呃,不明白參數是1個數組的時候啥用的。誰知道告訴我。) 輸出結果: 第3行: Array( [0] => 1 [1] => 2 [2] => 3 [3] => 4 [color] => blue //這一行有區別註意哦 [4] => a [5] = ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...