Hibernate 一對一關聯查詢


版權聲明:本文為博主原創文章,如需轉載請標注轉載地址。

博客地址:http://www.cnblogs.com/caoyc/p/5602418.html 

一對一關聯,可以分為兩種。一種是基於外鍵的關聯,另一種是基於主鍵的關聯。如圖

 

一、基於外鍵的方式

  

  User.java

 1 package com.proc.one2one;
 2 
 3 public class User {
 4 
 5     private Integer id;
 6     private String name;
 7     private IdCard card;
 8     public User() {
 9     }
10     public User(String name) {
11         this.name = name;
12     }
13     public Integer getId() {
14         return id;
15     }
16     public void setId(Integer id) {
17         this.id = id;
18     }
19     public String getName() {
20         return name;
21     }
22     public void setName(String name) {
23         this.name = name;
24     }
25     public IdCard getCard() {
26         return card;
27     }
28     public void setCard(IdCard card) {
29         this.card = card;
30     }
31     @Override
32     public String toString() {
33         return "User [id=" + id + ", name=" + name + "]";
34     }
35 }

 

  IdCard.java

 1 package com.proc.one2one;
 2 
 3 public class IdCard {
 4 
 5     private Integer id;
 6     private String cardNo;
 7     private User user;
 8     public IdCard(String cardNo) {
 9         this.cardNo = cardNo;
10     }
11     public IdCard() {
12     }
13     public Integer getId() {
14         return id;
15     }
16     public void setId(Integer id) {
17         this.id = id;
18     }
19     public String getCardNo() {
20         return cardNo;
21     }
22     public void setCardNo(String cardNo) {
23         this.cardNo = cardNo;
24     }
25     public User getUser() {
26         return user;
27     }
28     public void setUser(User user) {
29         this.user = user;
30     }
31     @Override
32     public String toString() {
33         return "IdCard [id=" + id + ", cardNo=" + cardNo + "]";
34     }
35     
36 }

  

  User.hbm.xml

 1 <?xml version="1.0" encoding="UTF-8" ?>
 2 <!DOCTYPE hibernate-mapping PUBLIC 
 3     "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
 4     "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
 5 <hibernate-mapping package="com.proc.one2one">
 6     <class name="User" table="t_user">
 7         <id name="id" type="int" column="id" >
 8             <generator class="native"></generator>
 9         </id>
10         <property name="name" length="20" not-null="true"></property>
11         <one-to-one name="card" class="IdCard"></one-to-one>
12     </class>
13 </hibernate-mapping>

  

  IdCard.hbm.xml

 1 <?xml version="1.0" encoding="UTF-8" ?>
 2 <!DOCTYPE hibernate-mapping PUBLIC 
 3     "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
 4     "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
 5 <hibernate-mapping package="com.proc.one2one">
 6     <class name="IdCard" table="t_idcard">
 7         <id name="id" type="int" column="id" >
 8             <generator class="native"></generator>
 9         </id>
10         <property name="cardNo" type="string" column="cardNo" length="20" not-null="true"></property>
11         <many-to-one name="user" column="userid" class="User" unique="true"></many-to-one>
12     </class>
13 </hibernate-mapping>

 

  我們可以看到一個是one-to-one一個是many-to-one的unique。

  分清楚這兩個很重要,many-to-one用在保存外鍵的表,也就是說t_idcard表,one-to-one用在沒有保存外鍵的表,也就是user表.

 

測試代碼:

1、添加關聯關系

測試:1:

 1 public class App {
 2 
 3     private static SessionFactory factory=new Configuration()
 4                     .configure()
 5                     .addClass(User.class)
 6                     .addClass(IdCard.class)
 7                     .buildSessionFactory();
 8     
 9     @Test
10     public void test(){
11         
12         Session session=factory.openSession();
13         Transaction tx=session.beginTransaction();
14         
15         User user=new User("caoyc");
16         IdCard card=new IdCard("510123588413x");
17         
18         card.setUser(user);
19         session.save(user);
20         session.save(card);
21         tx.commit();
22         session.close();
23         
24     }
25 }

  上面我們通過IdCard來維護關聯關系,結果正確

  

測試2:

  下面我們來試一試通過User來維護關聯關系,看結果會怎么樣?

 1     @Test
 2     public void test(){
 3         
 4         Session session=factory.openSession();
 5         Transaction tx=session.beginTransaction();
 6         
 7         User user=new User("caoyc");
 8         IdCard card=new IdCard("510123588413x");
 9         
10         user.setCard(card);
11         
12         session.save(user);
13         session.save(card);
14         tx.commit();
15         session.close();
16         
17     }

  在數據庫中我們可以看到,數據庫中表的結構完全一致,而且在t_user中也插入了數據,在t_idcard表中也同樣有數據,只不過,t_idcard表中的userid列為null,也就是說,通過user無法維護關聯關系

  【總結】:在有外鍵的一方,可以維護關聯關系,而在沒有外鍵的一方無法維護關聯關系

 

測試3:

  我們交換user對象和card對象的保存順序

1 session.save(card);
2 session.save(user);

  結果數據也能夠正常插入到數據庫中,結果和測試1相同。那么交換保存順序是否有其他影響呢?答案是肯定的,雖然數據同樣插入進去了,但是在具體插入過程卻有不同。

  在測試1中:我們先保存的user,通過insert into語句我們將數據正確插入,然后我們在保存card,而此時的user對象由於已經在數據庫中存在,那么必然有主鍵ID存在,我們在插入到IdCard表中,數據全部完全插入。具體sql語句

1 Hibernate: insert into t_user (name) values (?)
2 Hibernate: insert into t_idcard (cardNo, userid) values (?, ?)

  在測試3中:我們先將card的數據保存到idcard表中,而此時的user的id值為null,所有在插入到idcard中是,userid會是nul

  l

  然后在插入user到t_user表中,那么此時user的主鍵值已經生成。為了維護關聯關系

  系統會有執行一條語句

  update t_idcard set cardNo=?, userid=? where id=?

  所有在測試3中,我們會看到

1 Hibernate: insert into t_idcard (cardNo, userid) values (?, ?)
2 Hibernate: insert into t_user (name) values (?)
3 Hibernate: update t_idcard set cardNo=?, userid=? where id=?

  【總結】:在保存數據時,我們先保存沒有外鍵的一方,然后在保存有外鍵的一方,這樣執行效率更高

 

2、解除關聯關系

測試1:通過User來解除關聯關系

 

 1     @Test
 2     public void test(){
 3         
 4         Session session=factory.openSession();
 5         Transaction tx=session.beginTransaction();
 6         
 7         User user=session.get(User.class, 1);
 8         user.setCard(null);
 9 
10         tx.commit();
11         session.close();
12         
13     }

 

  執行的SQL語句

Hibernate: select user0_.id as id1_1_0_, user0_.name as name2_1_0_, idcard1_.id as id1_0_1_, idcard1_.cardNo as cardNo2_0_1_, idcard1_.userid as userid3_0_1_ from t_user user0_ left outer join t_idcard idcard1_ on user0_.id=idcard1_.id where user0_.id=?

  可以看到,此時通過user無法來解除關聯關系

 

測試2:通過idcard來解除關聯關系

 1     @Test
 2     public void test(){
 3         
 4         Session session=factory.openSession();
 5         Transaction tx=session.beginTransaction();
 6         
 7         IdCard card=session.get(IdCard.class, 1);
 8         card.setUser(null);
 9 
10         tx.commit();
11         session.close();
12         
13     }

  執行的SQL語句

1 Hibernate: select idcard0_.id as id1_0_0_, idcard0_.cardNo as cardNo2_0_0_, idcard0_.userid as userid3_0_0_ from t_idcard idcard0_ where idcard0_.id=?
2 Hibernate: update t_idcard set cardNo=?, userid=? where id=?

  在數據庫中也可看到通過idcard的確能夠解除關聯關系

 

3、刪除操作

測試1:刪除user

 

 1     @Test
 2     public void test(){
 3         
 4         Session session=factory.openSession();
 5         Transaction tx=session.beginTransaction();
 6         
 7         User user=session.get(User.class, 1);
 8         session.delete(user);
 9 
10         tx.commit();
11         session.close();
12         
13     }

 

  如果此時將要刪除的user數據在t_idcard表中沒有對應相應的數據,那么可以刪除成功,否則將會拋出異常,意思說有外鍵約束,該數據無法刪除

 

測試2:刪除idcard

1     public void test(){
2         
3         Session session=factory.openSession();
4         Transaction tx=session.beginTransaction();
5         IdCard card=session.get(IdCard.class, 1);
6         session.delete(card);
7         tx.commit();
8         session.close();
9     }

  結果:刪除成功 

 

Question:在上面測試2中,我們刪除了t_idcard中的數據,如果我需要當刪除了t_idcard中的數據后,同樣刪除t_user中對應的屬性,我們該怎么辦呢?

Answer: 那么我們需要設置cascade屬性為delete,我們在IdCard.hbm.xml

<many-to-one name="user" column="userid" class="User" unique="true" cascade="delete"></many-to-one>

也就是說,我們在刪除對象idCard是,同樣對其屬性user也做刪除動作

 

 

外鍵方式總結:

  1、在有外鍵的一方,可以維護關聯關系,可以建立關聯關系,同樣也可以解除關聯關系,可以任意刪除本對象,如果在hbm.xml中設置了cascade="delete",也可以刪除關聯對象

  2、在沒有外鍵的一方,不可以維護關聯關系,所有無法建立關聯關系,也無法解除關聯關系。在刪除過程中,如有沒有外鍵值對應本條數據,可以成功刪除,否則會拋出異常

 

 

  

二、基於主鍵的關聯方式

  基於外鍵方式:一個many-to-one(有外鍵方)和一個one-to-one(無外鍵方法)

  基於主鍵方式:兩個都是one-to-one

  還是上面的例子,其它我們都不需要改變,我們只需要改變IdCard.hbm.xml就可以,具體代碼如下

 1 <?xml version="1.0" encoding="UTF-8" ?>
 2 <!DOCTYPE hibernate-mapping PUBLIC 
 3     "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
 4     "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
 5 <hibernate-mapping package="com.proc.one2one">
 6     <class name="IdCard" table="t_idcard">
 7         <id name="id" type="int" column="id" >
 8             <generator class="foreign">
 9                 <param name="property">user</param>
10             </generator>
11         </id>
12         <property name="cardNo" type="string" column="cardNo" length="20" not-null="true"></property>
13         <one-to-one name="user" class="User" constrained="true"></one-to-one>
14     </class>
15 </hibernate-mapping>

 

  代碼說明:

    1、由於是基於主鍵方式,所有對應t_idcard表的主鍵id也是來自於t_user表,所有對應IdCard主鍵生成策略我們選用foregin,其中還必須指定一個從參數property,表示該主鍵生成策略基於對象的那個屬性,我們這里的屬性是user

    2、constrained="true":表示給t_idcard添加一個外鍵約束,默認為false,不添加外鍵約束

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM