国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 編程 > Java > 正文

深入解析Java的Hibernate框架中的一對(duì)一關(guān)聯(lián)映射

2019-11-26 14:42:13
字體:
供稿:網(wǎng)友

作為一個(gè)ORM框架,hibernate肯定也需要滿足我們實(shí)現(xiàn)表與表之間進(jìn)行關(guān)聯(lián)的需要。hibernate在關(guān)聯(lián)方法的實(shí)現(xiàn)很簡(jiǎn)單。下面我們先來看看一對(duì)一的做法:
 不多說了,我們直接上代碼:
 兩個(gè)實(shí)體類,TUser和TPassport:

public class TUser implements Serializable{   private static final long serialVersionUID = 1L;  private int id;  private int age;  private String name;  private TPassport passport;   //省略Get/Set方法 } public class TPassport implements Serializable{   private static final long serialVersionUID = 1L;  private int id;  private String serial;  private int expiry;  private TUser user;   //省略Get/Set方法 } 

  下面我們看一下映射文件有什么不同:

<hibernate-mapping package="org.hibernate.tutorial.domain4">  <class name="TUser" table="USER4">   <id name="id" column="id">    <generator class="native" />   </id>   <property name="name" type="java.lang.String" column="name"/>   <property name="age" type="java.lang.Integer" column="age"/>   <one-to-one name="passport" class="TPassport"      cascade="all" outer-join="true" />  </class> </hibernate-mapping> 

  這里我們看到有一個(gè)新標(biāo)簽,one-to-one,它表明當(dāng)前類與所對(duì)應(yīng)的類是一對(duì)一的關(guān)系,cascade是級(jí)聯(lián)關(guān)系,all表明無論什么情況都進(jìn)行級(jí)聯(lián),即當(dāng)對(duì)TUser類進(jìn)行操作時(shí),TPassport也會(huì)進(jìn)行相應(yīng)的操作,outer-join是指是否使用outer join語(yǔ)句。
 我們?cè)倏戳硗庖粋€(gè)TPassport的映射文件:

<hibernate-mapping package="org.hibernate.tutorial.domain4">  <class name="TPassport" table="passport4">   <id name="id" column="id">    <generator class="foreign" >     <param name="property">user</param>    </generator>   </id>   <property name="serial" type="java.lang.String" column="serial"/>   <property name="expiry" type="java.lang.Integer" column="expiry"/>   <one-to-one name="user" class="TUser" constrained="true" />  </class> </hibernate-mapping>

  
  這里我們重點(diǎn)看到generator的class值,它為foreign表明參照外鍵,而參照哪一個(gè)是由param來進(jìn)行指定,這里表明參照User類的id。而one-to-one標(biāo)簽中多了一個(gè)constrained屬性,它是告訴hibernate當(dāng)前類存在外鍵約束,即當(dāng)前類的ID根據(jù)TUser的ID進(jìn)行生成。
 下面我們直接上測(cè)試類,這次測(cè)試類沒有用JUnit而是直接Main方法來了:

public static void main(String[] args) {      Configuration cfg = new Configuration().configure();   SessionFactory sessionFactory = cfg.buildSessionFactory();   Session session = sessionFactory.openSession();      session.beginTransaction();      TUser user = new TUser();   user.setAge(20);   user.setName("shunTest");      TPassport passport = new TPassport();   passport.setExpiry(20);   passport.setSerial("123123123");      passport.setUser(user);   user.setPassport(passport);      session.save(user);      session.getTransaction().commit();     } 

  代碼很簡(jiǎn)單,就不說了。我們主要看這里:

session.save(user); 

  這里為什么我們只調(diào)用一個(gè)save呢,原因就在我們的TUser映射文件中的cascade屬性,它被設(shè)為all,即表明當(dāng)我們對(duì)TUser進(jìn)行保存,更新,刪除等操作時(shí),TPassport也會(huì)進(jìn)行相應(yīng)的操作,所以這里我們不用寫session.save(passport)。我們看到后臺(tái):

Hibernate: insert into USER4 (name, age) values (?, ?) Hibernate: insert into passport4 (serial, expiry, id) values (?, ?, ?) 
Hibernate:   它打印出兩個(gè)語(yǔ)句,證明hibernate確定幫我們做了這個(gè)工作。
 
 
 下面我們?cè)賮硪粋€(gè)測(cè)試類,測(cè)試查詢:
public static void main(String[] args) {   Configuration cfg = new Configuration().configure();   SessionFactory sessionFactory = cfg.buildSessionFactory();   Session session = sessionFactory.openSession();      TUser user = (TUser)session.load(TUser.class,new Integer(3));   System.out.println(user.getName()+":"+user.getPassport().getSerial());     } 
  這里我們通過查詢出TUser類,取到TPassport對(duì)象。
 我們可以看到hibernate的SQL語(yǔ)句是:
復(fù)制代碼 代碼如下:

Hibernate:
select tuser0_.id as id0_1_, tuser0_.name as name0_1_, tuser0_.age as age0_1_, tpassport1_.id as id1_0_, tpassport1_.serial as serial1_0_, tpassport1_.expiry as expiry1_0_ from USER4 tuser0_ left outer join passport4 tpassport1_ on tuser0_.id=tpassport1_.id where tuser0_.id=?

  我們看到語(yǔ)句當(dāng)中有l(wèi)eft outer join,這是因?yàn)槲覀兦懊嬖趏ne-to-one當(dāng)中設(shè)了outer-join="true",我們?cè)囍阉某蒮alse,看到SQL語(yǔ)句如下:
復(fù)制代碼 代碼如下:

Hibernate:
select tuser0_.id as id0_0_, tuser0_.name as name0_0_, tuser0_.age as age0_0_ from USER4 tuser0_ where tuser0_.id=?
Hibernate:
select tpassport0_.id as id1_0_, tpassport0_.serial as serial1_0_, tpassport0_.expiry as expiry1_0_ from passport4 tpassport0_ where tpassport0_.id=?


  現(xiàn)在是分成兩條來查了,根據(jù)第一條查出的ID再到第二條查出來。
 
 也許很多人會(huì)問為什么測(cè)試的時(shí)候不用TPassport查出TUser呢,其實(shí)也可以的,因?yàn)樗鼈兪且粚?duì)一的關(guān)系,誰(shuí)查誰(shuí)都是一樣的。

外鍵關(guān)聯(lián)
現(xiàn)在我們看一下通過外鍵來進(jìn)行關(guān)聯(lián)的一對(duì)一關(guān)聯(lián)。
 還是一貫的直接上例子:我們寫了兩個(gè)實(shí)體類,TGroup和TUser

public class TGroup implements Serializable{   private static final long serialVersionUID = 1L;  private int id;  private String name;  private TUser user;   //省略Get/Set方法 } public class TUser implements Serializable{   private static final long serialVersionUID = 1L;  private int id;  private int age;  private String name;  private TGroup group;   //省略Get/Set方法   } 

  實(shí)體類完了我們就看一下映射文件:

<hibernate-mapping package="org.hibernate.tutorial.domain5">  <class name="TUser" table="USER5">   <id name="id" column="id">    <generator class="native" />   </id>   <property name="name" type="java.lang.String" column="name"/>   <property name="age" type="java.lang.Integer" column="age"/>   <many-to-one name="group" class="TGroup" column="group_id" unique="true" />  </class> </hibernate-mapping> 

  這里我們看到是用many-to-one標(biāo)簽而不是one-to-one,為什么呢?
 這里以前用的時(shí)候也沒多在注意,反正會(huì)用就行,但這次看了夏昕的書終于明白了,實(shí)際上這種通過外鍵進(jìn)行關(guān)聯(lián)方式只是多對(duì)一的一種特殊方式而已,我們通過unique="true"限定了它必須只能有一個(gè),即實(shí)現(xiàn)了一對(duì)一的關(guān)聯(lián)。
 接下來我們看一下TGroup的映射文件:

<hibernate-mapping package="org.hibernate.tutorial.domain5">  <class name="TGroup" table="group5">   <id name="id" column="id">    <generator class="native" />   </id>   <property name="name" type="java.lang.String" column="name"/>   <one-to-one name="user" class="TUser" property-ref="group" />  </class> </hibernate-mapping> 

  這里,注意,我們又用到了one-to-one,表明當(dāng)前的實(shí)體和TUser是一對(duì)一的關(guān)系,這里我們不用many-to-one,而是通過one-to-one指定了TUser實(shí)體中通過哪個(gè)屬性來關(guān)聯(lián)當(dāng)前的類TGroup。這里我們指定了TUser是通過group屬性和Tuser進(jìn)行關(guān)聯(lián)的。property-ref指定了通過哪個(gè)屬性進(jìn)行關(guān)聯(lián)。
 下面我們看測(cè)試類:

public class HibernateTest {   public static void main(String[] args) {    Configuration cfg = new Configuration().configure();   SessionFactory sessionFactory = cfg.buildSessionFactory();   Session session = sessionFactory.openSession();      session.beginTransaction();      TGroup group = new TGroup();   group.setName("testGroup");      TUser user = new TUser();   user.setAge(23);   user.setName("test");      user.setGroup(group);   group.setUser(user);      session.save(group);   session.save(user);      session.getTransaction().commit();   session.close();  }  } 

  注意,這次我們的代碼中需要進(jìn)行兩次的保存,因?yàn)樗鼈儗?duì)各自都有相應(yīng)的對(duì)應(yīng),只保存一個(gè)都不會(huì)對(duì)另外一個(gè)有什么操作。所以我們需要調(diào)用兩次保存的操作。最后進(jìn)行提交。
 hibernate打印出語(yǔ)句:

Hibernate: insert into group5 (name) values (?) Hibernate: insert into USER5 (name, age, group_id) values (?, ?, ?) 

  這說明我們正確地存入了兩個(gè)對(duì)象值。
 
 我們寫多一個(gè)測(cè)試類進(jìn)行查詢:

public static void main(String[] args) {    Configuration cfg = new Configuration().configure();   SessionFactory sessionFactory = cfg.buildSessionFactory();   Session session = sessionFactory.openSession();      TUser user = (TUser)session.load(TUser.class,new Integer(1));   System.out.println("From User get Group:"+user.getGroup().getName());         TGroup group = (TGroup)session.load(TGroup.class,new Integer(1));   System.out.println("From Group get User:" + group.getUser().getName());      session.close();     } 

  我們都可以得到正確的結(jié)果,這表明我們可以通過兩個(gè)對(duì)象拿出對(duì)方的值,達(dá)到了我們的目的。
 這個(gè)例子中用到的TGroup和TUser只是例子而已,實(shí)際上現(xiàn)實(shí)生活中的user一般都對(duì)應(yīng)多個(gè)group。

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 上饶市| 旅游| 普定县| 宣城市| 乌兰浩特市| 盱眙县| 井陉县| 桐城市| 阜南县| 潼关县| 宾阳县| 肇庆市| 象山县| 庆阳市| 安龙县| 宿松县| 咸阳市| 屏南县| 东乡族自治县| 丰台区| 龙门县| 修武县| 禄劝| 土默特左旗| 天全县| 吉木萨尔县| 奉节县| 南充市| 乐业县| 永新县| 睢宁县| 曲麻莱县| 泸西县| 阿拉善右旗| 藁城市| 灵宝市| 寿宁县| 萝北县| 福州市| 潞城市| 西乌珠穆沁旗|