国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
Hibernate標(biāo)識(shí)符屬性(主鍵)生成策略全析

Hibernate標(biāo)識(shí)符屬性(主鍵)生成策略全析

文章分類:Java編程
    數(shù)據(jù)庫中的主鍵能夠唯一識(shí)別一條記錄,它可以是一個(gè)字段也可以是多個(gè)字段的組合。主鍵的主要作用是標(biāo)識(shí)表中的一條記錄,還有和其他表中的數(shù)據(jù)進(jìn)行關(guān)聯(lián)。數(shù)據(jù)庫中的主鍵類型必須符合唯一性約束和非空約束。作為附加屬性,主鍵應(yīng)該盡可能簡潔,不要包含過多屬性。根據(jù)這個(gè)原則,主鍵可以分為自然主鍵和代理主鍵。
    自然主鍵是數(shù)據(jù)表中有邏輯含義的字段,比如身份證號(hào)來唯一確定一條個(gè)人記錄。也可以通過學(xué)號(hào)和課程號(hào)來唯一確定成績。使用自然主鍵時(shí)如果業(yè)務(wù)發(fā)生變化則對(duì)數(shù)據(jù)庫調(diào)整是極其麻煩的,所以數(shù)據(jù)庫設(shè)計(jì)使用代理主鍵是非常好的選擇。代理主鍵是一個(gè)和業(yè)務(wù)無關(guān)的流水號(hào),一般采用數(shù)據(jù)庫中自動(dòng)增長的機(jī)制自動(dòng)生成。例如Oracle數(shù)據(jù)庫使用序列,MySQL和SQL Server有自動(dòng)增長(auto increment)類型,該字段類型一般為Integer,名稱設(shè)置為ID或XXID。下面來看看Hibernate中的主鍵生成策略,實(shí)驗(yàn)都以O(shè)racle為主,MySQL為輔來說明。
    第一種是increment策略,Hibernate配置如下:
Xml代碼
  1. <id name="id" column="ID" type="java.lang.Integer" length="10">  
  2.     <generator class="increment"></generator>  
  3. </id>  

    運(yùn)行結(jié)果如下:
Sql代碼
  1. Hibernate: select max(ID) from USERS   
  2. Hibernate: insert into USERS (NAME, PHONE, DEPARTMENT, CITY, HIRE_TIME, ID) values(?, ?, ?, ?, ?, ?)  

    可以看出,Hibernate是從數(shù)據(jù)庫中先找出已經(jīng)存在的最大主鍵數(shù)值,然后加1后作為新紀(jì)錄的主鍵再執(zhí)行插入語句。這種策略不適合非獨(dú)享數(shù)據(jù)庫或者分布式的Hibernate應(yīng)用,否則就很難保證主鍵值的唯一了。
    第二種是identity策略,Hibernate中配置如下:
Xml代碼
  1. <id name="id" column="ID" type="java.lang.Integer" length="10">  
  2.     <generator class="identity"></generator>  
  3. </id>  

    這種策略在Oracle中無法使用,因?yàn)檫@種策略是針對(duì)數(shù)據(jù)庫中字段自動(dòng)增長類型。改在MySQL中測(cè)試,得到如下結(jié)果:
Sql代碼
  1. Hibernate: insert into USERS (NAME, PHONE, DEPARTMENT, CITY, HIRE_TIME) values(?, ?, ?, ?, ?)  

    多次運(yùn)行程序,在數(shù)據(jù)庫中查看,可以看到主鍵是自動(dòng)進(jìn)行遞增的。
    第三種是sequence策略,Hibernate中配置如下:
Xml代碼
  1. <generator class="sequence">  
  2.         <param name="sequence">SEQ_HIBERNATE_USERS</param>  
  3.     </generator>  

    使用序列策略是,需要現(xiàn)在數(shù)據(jù)庫中創(chuàng)建一條序列,運(yùn)行程序,得到如下結(jié)果:
Sql代碼
  1. Hibernate: select SEQ_HIBERNATE_USERS.nextval from dual   
  2. Hibernate: insert into USERS (NAME, PHONE, DEPARTMENT, CITY, HIRE_TIME, ID) values (?, ?, ?, ?, ?, ?)  

    可以看出Hibernate先從序列中得到下一個(gè)數(shù)值,然后執(zhí)行插入操作。
    第四種是hilo策略,這是Hibernate采用一種稱為“高/低位”(hi/lo)的算法產(chǎn)生標(biāo)識(shí)符屬性值,該算法采用一個(gè)高位值和一個(gè)低位值進(jìn)行運(yùn)算,結(jié)果作為標(biāo)識(shí)符屬性的值。使用該策略時(shí),需要在數(shù)據(jù)庫中建立一個(gè)表和其中一個(gè)字段,名稱可以自定。其中的字段值作為高位值的來源。在Hibernate中配置如下:
Xml代碼
  1. <generator class="hilo">  
  2.     <param name="table">HIBERNATE_KEY</param>  
  3.     <param name="column">NEXT_HIVALUE</param>  
  4. </generator>  

    可以見名知意,我使用的表名是HIBERNATE_KEY,字段名是NEXT_HIVALUE,然后給該字段設(shè)置一個(gè)值,作為高位。低位Hibernate有自己的管理機(jī)制可不用創(chuàng)建,也可以給出在配置文件中用<param name="max_lo">1</param>的形式給出即可,一般使用情況下使用1更好。該算法是每次按max_lo數(shù)值遞增。Hibernate的執(zhí)行結(jié)果還是一條語句,如下:
Sql代碼
  1. Hibernate: insert into USERS (NAME, PHONE, DEPARTMENT, CITY, HIRE_TIME, ID) values (?, ?, ?, ?, ?, ?)  

    執(zhí)行后高位自動(dòng)加1,然后到數(shù)據(jù)庫中就可以查看生成的主鍵數(shù)值。該策略與底層的數(shù)據(jù)庫無關(guān),只要保證高位降低,那么生成的主鍵值是唯一的,并且可跨數(shù)據(jù)庫使用。
    第五種是seqhilo策略,基于hilo策略,這種方式的標(biāo)識(shí)符屬性生成時(shí)指定一個(gè)序列作為高位值,那么在Hibernate中的配置如下:
Xml代碼
  1.     <generator class="seqhilo">  
  2.         <param name="sequence">SEQ_HIBERNATE_USERS</param>  
  3. </generator>  

    執(zhí)行插入后,Hibernate首先取出序列的下一個(gè)值作為高位值,然后計(jì)算一個(gè)ID出來進(jìn)行操作,得到如下結(jié)果:
Sql代碼
  1. Hibernate: select SEQ_HIBERNATE_USERS.nextval from dual   
  2. Hibernate: insert into USERS (NAME, PHONE, DEPARTMENT, CITY, HIRE_TIME, ID) values (?, ?, ?, ?, ?, ?)  

    第六種是uuid策略,這種策略是使用128位的UUID算法來生成字符串類型標(biāo)識(shí)符屬性,這種算法使用IP地址,JVM的啟動(dòng)時(shí)間(精確到1/4秒),系統(tǒng)時(shí)間和一個(gè)計(jì)數(shù)器(在當(dāng)前JVM中唯一)這些數(shù)值經(jīng)過計(jì)算得到一個(gè)標(biāo)識(shí)符屬性的值,產(chǎn)生的值是32位長度的字符串,則使用前需要將數(shù)據(jù)庫字段調(diào)整到varchar2(32),持久化類的ID屬性改為String進(jìn)行測(cè)試。Hibernate中配置如下,注意字段信息的修改:
Xml代碼
  1. <id name="id" column="ID" type="java.lang.String" length="32">  
  2.     <generator class="uuid">  
  3.     </generator>  
  4. lt;/id>  

    執(zhí)行后Hibernate的結(jié)果還是一條插入語句,這里不再復(fù)制了,我們看看數(shù)據(jù)庫中的結(jié)果吧,如下圖,就得到了32位的主鍵值了。

    在做文件下載時(shí),用這種策略生成的主鍵就可以作為下載鏈接,而不用在人為去制作鏈接,是一個(gè)不錯(cuò)的選擇。
    第七種是guid策略,Hibernate中配置如下:
Xml代碼
  1. <generator class="guid"></generator>  

    這個(gè)在Oracle中是用了sys_guid()函數(shù)生成的值,而在MySQL中使用uuid()函數(shù)生成值,這個(gè)值要設(shè)置成varchar2/varchar類型,區(qū)別在于Oracle中是32位長度,而MySQL原生是36位(有4個(gè)-隔開)。運(yùn)行程序得到如下結(jié)果:(Oracle環(huán)境下)
Sql代碼
  1. Hibernate: select rawtohex(sys_guid()) from dual   
  2. Hibernate: insert into USERS (NAME, PHONE, DEPARTMENT, CITY, HIRE_TIME, ID) values (?, ?, ?, ?, ?, ?)  

(MySQL環(huán)境下)
Sql代碼
  1. Hibernate: select uuid()   
  2. Hibernate: insert into USERS (NAME, PHONE, DEPARTMENT, CITY, HIRE_TIME, ID) values (?, ?, ?, ?, ?, ?)  

    第八種是native策略,native字面意思是“本地的”,那么對(duì)于數(shù)據(jù)庫,Hibernate該如何選擇呢?Hibernate根據(jù)所使用的數(shù)據(jù)庫支持能力從identity,sequence或者h(yuǎn)ilo策略中選擇一種,Hibernate中配置很簡單:
Xml代碼
  1. <generator class="native"></generator>  

    在Oracle下,Oracle先創(chuàng)建一個(gè)序列,使用默認(rèn)名(數(shù)據(jù)庫名_SEQUENCE),然后執(zhí)行插入操作,而在MySQL下則使用identity策略,使用了自動(dòng)增長的字段。Oracle中測(cè)試結(jié)果如下:
Sql代碼
  1. Hibernate: select hibernate_sequence.nextval from dual   
  2. Hibernate: insert into USERS (NAME, PHONE, DEPARTMENT, CITY, HIRE_TIME, ID) values (?, ?, ?, ?, ?, ?)  

    第九種是assigned策略,這種方式也是Hibernate中<generator>沒有配置標(biāo)識(shí)符屬性生成策略時(shí)默認(rèn)使用的方式。但使用這種策略時(shí)需要我們自定義標(biāo)識(shí)符屬性的值,也就是我們?nèi)藶樵O(shè)置標(biāo)識(shí)符屬性的值,這就需要在程序中顯式為標(biāo)識(shí)符屬性(ID)賦值。配置方式如下:
Xml代碼
  1. <generator class="assigned"></generator>  

    第十種是foreign策略,這種方式是通過關(guān)聯(lián)的持久化對(duì)象為當(dāng)前的持久化對(duì)象設(shè)置標(biāo)識(shí)符屬性,當(dāng)他們是一對(duì)一關(guān)聯(lián)時(shí),一個(gè)持久化類的主鍵值可以參考關(guān)聯(lián)持久化類的標(biāo)識(shí)符屬性值。我們做一個(gè)完整的實(shí)例來看。(使用Hibernate為我們自動(dòng)創(chuàng)建表)
hibernate.cfg.xml
Xml代碼
  1. <?xml version='1.0' encoding='UTF-8'?>  
  2. <!DOCTYPE hibernate-configuration PUBLIC   
  3.           "-//Hibernate/Hibernate Configuration DTD 3.0//EN"   
  4.           "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">  
  5. <hibernate-configuration>  
  6.     <session-factory>  
  7.         <property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property>  
  8.         <property name="connection.url">jdbc:oracle:thin:@localhost:1521:orcl</property>  
  9.         <property name="hibernate.connection.username">hibernate</property>  
  10.         <property name="hibernate.connection.password">hibernate</property>  
  11.         <property name="hibernate.dialect">org.hibernate.dialect.OracleDialect</property>  
  12.         <property name="current_session_context_class">thread</property>  
  13.         <property name="hbm2ddl.auto">create</property>  
  14.         <property name="show_sql">true</property>  
  15.         <property name="format_sql">false</property>  
  16.         <mapping resource="demo/domain/User.hbm.xml" />  
  17.         <mapping resource="demo/domain/Profile.hbm.xml" />  
  18.     </session-factory>  
  19. </hibernate-configuration>  

    User持久化類和映射文件:
Java代碼
  1. package demo.domain;   
  2. public class User implements java.io.Serializable {   
  3.     private Integer id;   
  4.     private String name;   
  5.     private String password;   
  6.     private Profile profile;   
  7.     public User() {   
  8.     }   
  9.     // get和set方法   
  10.     public Integer getId() {   
  11.         return id;   
  12.     }   
  13.     public void setId(Integer id) {   
  14.         this.id = id;   
  15.     }   
  16.     public String getName() {   
  17.         return name;   
  18.     }   
  19.     public void setName(String name) {   
  20.         this.name = name;   
  21.     }   
  22.     public String getPassword() {   
  23.         return password;   
  24.     }   
  25.     public void setPassword(String password) {   
  26.         this.password = password;   
  27.     }   
  28.     public Profile getProfile() {   
  29.         return profile;   
  30.     }   
  31.     public void setProfile(Profile profile) {   
  32.         this.profile = profile;   
  33.     }   
  34. }  

Xml代碼
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"   
  3. "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">  
  4. <hibernate-mapping>  
  5.     <class name="demo.domain.User" table="USERS">  
  6.         <id name="id" column="ID" type="java.lang.Integer" length="10">  
  7.             <generator class="native">  
  8.             </generator>  
  9.         </id>  
  10.         <property name="name" column="NAME" type="java.lang.String"  
  11.             length="20" not-null="true" />  
  12.         <property name="password" column="PASSWORD" type="java.lang.String"  
  13.             length="32" />  
  14.         <one-to-one name="profile" class="demo.domain.Profile"  
  15.             outer-join="true" cascade="all" />  
  16.     </class>  
  17. </hibernate-mapping>  

    Profile持久化類和映射文件如下:
Java代碼
  1. package demo.domain;   
  2.   
  3. public class Profile implements java.io.Serializable {   
  4.     private Integer id;   
  5.     private String info;   
  6.     private User user;   
  7.     public Profile() {   
  8.     }   
  9.     public Integer getId() {   
  10.         return id;   
  11.     }   
  12.     public void setId(Integer id) {   
  13.         this.id = id;   
  14.     }   
  15.     public String getInfo() {   
  16.         return info;   
  17.     }   
  18.     public void setInfo(String info) {   
  19.         this.info = info;   
  20.     }   
  21.     public User getUser() {   
  22.         return user;   
  23.     }   
  24.     public void setUser(User user) {   
  25.         this.user = user;   
  26.     }   
  27. }  

Xml代碼
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"   
  3. "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">  
  4. <hibernate-mapping>  
  5.     <class name="demo.domain.Profile" table="PROFILES">  
  6.         <id name="id" column="ID" type="java.lang.Integer" length="10">  
  7.             <generator class="foreign">  
  8.                 <param name="property">user</param>  
  9.             </generator>  
  10.         </id>  
  11.         <property name="info" column="INFO" type="java.lang.String"  
  12.             length="200" not-null="true" />  
  13.         <one-to-one name="user" class="demo.domain.User"  
  14.             constrained="true" />  
  15.     </class>  
  16. </hibernate-mapping>  

    注意二者<one-to-one>配置時(shí)的屬性是不同的,因?yàn)橹鲃?dòng)的一方是User,被動(dòng)的一方是Profile,才會(huì)要求一個(gè)配置cascade,cascade為all表示表示主動(dòng)一方無論執(zhí)行任何操作,其關(guān)聯(lián)對(duì)象執(zhí)行同樣的操作。一個(gè)配置constrained,constrained為true表示約束Profile對(duì)象的標(biāo)識(shí)符屬性必須與User對(duì)象的標(biāo)識(shí)符屬性相同。測(cè)試類如下:
Java代碼
  1. package demo;   
  2. import org.hibernate.*;   
  3. import org.hibernate.cfg.Configuration;   
  4. import demo.domain.*;   
  5. public class Test {   
  6.     public static void main(String[] args) {   
  7.         Configuration config = new Configuration();   
  8.         config.configure();   
  9.         SessionFactory sessionFactory = config.buildSessionFactory();   
  10.         Session session = sessionFactory.getCurrentSession();   
  11.         Transaction tx = session.beginTransaction();   
  12.         User user = new User();   
  13.         user.setName("Tom");   
  14.         user.setPassword("123456");   
  15.         Profile profile = new Profile();   
  16.         profile.setInfo("Information");   
  17.         //雙向關(guān)聯(lián)   
  18.         user.setProfile(profile);   
  19.         profile.setUser(user);   
  20.         session.save(user);   
  21.         tx.commit();   
  22.     }   
  23. }  

    執(zhí)行程序,我們得到如下結(jié)果:
Sql代碼
  1. Hibernate: select hibernate_sequence.nextval from dual   
  2. Hibernate: insert into USERS (NAMEPASSWORD, ID) values (?, ?, ?)   
  3. Hibernate: insert into PROFILES (INFO, ID) values (?, ?)  

    我們?yōu)閁ser對(duì)象設(shè)置的標(biāo)識(shí)符屬性生成策略是native,則在Oracle數(shù)據(jù)庫中使用序列生成。為Profie對(duì)象設(shè)置的標(biāo)識(shí)符屬性生成策略是foreign,它就按照主體對(duì)象的標(biāo)識(shí)符屬性獲取。其實(shí)這種一對(duì)一關(guān)系完全可以合并到一個(gè)表中,只是為了說明,分開來演示例子而已。而實(shí)際情況就要具體問題具體分析了,主要在業(yè)務(wù)層面考慮而不是具體的技術(shù)實(shí)現(xiàn)。
    最后來說一下標(biāo)識(shí)符屬性生成策略的選擇方式。應(yīng)用不需要分布式時(shí),在數(shù)據(jù)庫支持的sequence,identity,hilo,seqhilo和uuid中選擇比較好。而分布式數(shù)據(jù)庫應(yīng)用中uuid是最佳選擇。若是改造遺留系統(tǒng),那么使用assigned是最合適的了。
    歡迎交流,希望對(duì)使用者有用。
  • 大小: 6.7 KB
本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
一份完整的Spring Hibernate DWR extJs的生成樹及下拉comBobo...
Eclipse下Hibernate入門
SSH2框架整合(Struts2.1.6+hibernate3.3.2+spring2.5.6)(spring+hibernate+servlet的源代碼在文章底部)
Hibernate的generator屬性之意義
Eclipse快速上手Hibernate--6.關(guān)聯(lián)映射(一對(duì)一)(1)
hibernate映射關(guān)系總結(jié)
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服