<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    邊城愚人

    如果我不在邊城,我一定是在前往邊城的路上。

      BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
      31 隨筆 :: 0 文章 :: 96 評論 :: 0 Trackbacks
    ?? ?Hibernate提供客戶化映射類型接口,使用戶能以編程方式創(chuàng)建自定義的映射類型來將持久化類任意類型的屬性映射到數(shù)據(jù)庫中。使用客戶化映射類型,需要實現(xiàn)org.hibernate.usertype.UserType接口。這是個強大的功能,也是Hibernate的最佳實踐之一。我們經(jīng)常提到ORM中很困難的一點便是O的屬性和R的屬性不能一一映射,而Hibernate提供的UserType無疑給出了一個很好的解決方案。本文給出使用客戶化映射類型的兩個例子,算是對Hibernate初學者的拋磚。
    ?? ?第一個例子是使用UserType映射枚舉類型。假設Account表中含有一sex列,類型為tinyint(當前其0代表男,1代表女,將來可能出現(xiàn)2等代表其他性別類型);我們當然可以在對應的Account類中添加int類型的sex屬性,但這種數(shù)字化無顯示意義且類型不安全的枚舉不是很好的解決方式,這里就采用了java5的enum來作為Account類的性別屬性(如果不熟悉java5的enum,也可采用《effective java》中提到的經(jīng)典的類型安全的枚舉方案)。在Account添加enum Gender:

    public?class?Account?extends?AbstractDomain<Long>{
    ????
    ????
    public?enum?Gender{
    ????????Male(
    "male",0),
    ????????Female(
    "female",1);
    ????????
    ????????
    private?String?name;
    ????????
    private?int?value;
    ????????
    ????????
    public?String?getName()?{
    ????????????
    return?name;
    ????????}
    ????????
    public?int?getValue()?{
    ????????????
    return?value;
    ????????}
    ????????
    ????????
    private?Gender(String?name,int?value){
    ????????????
    this.name?=?name;
    ????????????
    this.value?=?value;
    ????????}
    ????????
    ????????
    public?static?Gender?getGender(int?value){
    ????????????
    if(0?==?value)return?Male;
    ????????????
    else?if(1?==?value)return?Female;
    ????????????
    else?throw?new?RuntimeException();
    ????????}
    ????????
    ????}
    ????
    ????
    private?Gender?gender;
    ????
    public?Gender?getGender()?{
    ????????
    return?gender;
    ????}
    ????
    public?void?setGender(Gender?gender)?{
    ????????
    this.gender?=?gender;
    ????}
    ???????
    //省略其他????
    }

    ?? ?接下來定義實現(xiàn)UserType接口的GenderUserType:

    public?class?GenderUserType?implements?UserType{

    ????
    public?Object?assemble(Serializable?arg0,?Object?arg1)?throws?HibernateException?{
    ????????
    return?null;
    ????}

    ????
    /*
    ?????*??這是用于Hibernate緩存生成的快照,由于Gender是不可變的,直接返回就好了。
    ?????
    */
    ????
    public?Object?deepCopy(Object?arg0)?throws?HibernateException?{
    ????????
    return?arg0;
    ????}

    ????
    public?Serializable?disassemble(Object?arg0)?throws?HibernateException?{
    ????????
    return?null;
    ????}

    ????
    /*
    ?????*?由于Gender是不可變的,因此直接==了,這個方法將在insert、update時用到。
    ?????
    */
    ????
    public?boolean?equals(Object?x,?Object?y)?throws?HibernateException?{
    ????????
    return?x?==?y;
    ????}

    ????
    public?int?hashCode(Object?o)?throws?HibernateException?{
    ????????
    return?o.hashCode();
    ????}

    ????
    /*
    ?????*?表明Gender是不是可變類(很重要的概念哦),這里的Gender由于是枚舉所以是不可變的
    ?????
    */
    ????
    public?boolean?isMutable()?{
    ????????
    return?false;
    ????}

    ????
    /*
    ?????*??從ResultSet讀取sex并返回Gender實例,這個方法是在從數(shù)據(jù)庫查詢數(shù)據(jù)時用到。
    ?????
    */
    ????
    public?Object?nullSafeGet(ResultSet?rs,?String[]?names,?Object?owner)?throws?HibernateException,?SQLException?{
    ????????
    int?value?=?rs.getInt(names[0]);
    ????????
    return?Account.Gender.getGender(value);
    ????}

    ????
    /*
    ?????*??將Gender的value設置到PreparedStatement。
    ?????
    */
    ????
    public?void?nullSafeSet(PreparedStatement?ps,?Object?value,?int?index)?throws?HibernateException,?SQLException?{
    ??????? if(value == null){
    ??? ??? ??? ps.setInt(index,Account.Gender.Male.getValue());
    ??? ??? }else{
    ??? ??? ??? ps.setInt(index,((Account.Gender)value).getValue());
    ??? ??? }

    ????}

    ????
    public?Object?replace(Object?arg0,?Object?arg1,?Object?arg2)?throws?HibernateException?{
    ????????
    return?null;
    ????}

    ????
    /*
    ?????*?設置映射的Gender類
    ?????
    */
    ????
    public?Class?returnedClass()?{
    ????????
    return?Account.Gender.class;
    ????}

    ????
    /*
    ?????*??設置Gender枚舉中的value屬性對應的Account表中的sex列的SQL類型
    ?????
    */
    ????
    public?int[]?sqlTypes()?{
    ????????
    int[]?typeList?=?{Types.TINYINT};
    ????????
    return?typeList;
    ????}
    }

    ?? ?最后在Account的配置文件中配置gender屬性就好了:
    <property name="gender" type="org.prague.domain.util.GenderUserType" column="sex"></property>
    ?? ?除了可以使用 UserType映射枚舉類型,也可以使用Hibernate的PersistentEnum來實現(xiàn)同樣的功能,感興趣的朋友可以參考文章http://www.hibernate.org/203.html。

    ?? ?
    ?? ?第二個例子是關于email的。假設Account表中email是一個varchar型的字段,而Account中的Email是如下的類:

    public?class?Email?{
    ????String?username;

    ????String?domain;

    ????
    public?Email()?{
    ????}

    ????
    public?Email(String?username,?String?domain)?{
    ????????
    this.username?=?username;
    ????????
    this.domain?=?domain;
    ????}

    ????
    public?String?getUsername()?{
    ????????
    return?username;
    ????}

    ????
    public?String?getDomain()?{
    ????????
    return?domain;
    ????}

    ????
    ????
    public?void?setDomain(String?domain)?{
    ????????
    this.domain?=?domain;
    ????}

    ????
    public?void?setUsername(String?username)?{
    ????????
    this.username?=?username;
    ????}

    ????
    public?String?toString()?{
    ????????
    return?username?+?'@'?+?domain;
    ????}

    ????
    public?static?Email?parse(String?email)?{
    ????????Email?e?
    =?new?Email();
    ????????
    int?at?=?email.indexOf('@');
    ????????
    if?(at?==?-1)?{
    ????????????
    throw?new?IllegalArgumentException("Invalid?email?address");
    ????????}

    ????????e.username?
    =?email.substring(0,?at);
    ????????e.domain?
    =?email.substring(at?+?1);

    ????????
    return?e;
    ????}

    ????@Override
    ????
    public?int?hashCode()?{
    ????????
    final?int?PRIME?=?31;
    ????????
    int?result?=?1;
    ????????result?
    =?PRIME?*?result?+?((domain?==?null)???0?:?domain.hashCode());
    ????????result?
    =?PRIME?*?result?+?((username?==?null)???0?:?username.hashCode());
    ????????
    return?result;
    ????}

    ????@Override
    ????
    public?boolean?equals(Object?obj)?{
    ????????
    if?(this?==?obj)????return?true;
    ??????
    if(null?==?obj)return?false;
    ????????
    if?(getClass()?!=?obj.getClass())
    ????????????
    return?false;
    ????????
    final?Email?other?=?(Email)?obj;
    ????????
    if?(domain?==?null)?{
    ????????????
    if?(other.domain?!=?null)
    ????????????????
    return?false;
    ????????}?
    else?if?(!domain.equals(other.domain))
    ????????????
    return?false;
    ????????
    if?(username?==?null)?{
    ????????????
    if?(other.username?!=?null)
    ????????????????
    return?false;
    ????????}?
    else?if?(!username.equals(other.username))
    ????????????
    return?false;
    ????????
    return?true;
    ????}
    }
    ????email是Account類的一個屬性:
    public?class?Account?extends?AbstractDomain<Long>{
    ????
    ????
    private?Email?email;
    ????
    public?Email?getEmail()?{
    ????????
    return?email;
    ????}
    ????
    public?void?setEmail(Email?email)?{
    ????????
    this.email?=?email;
    ????}

    ????
    //省略其他????
    }

    ?? ?這樣的情況下,需要將email的username + '@' + domain映射到Account表的email列,定義一個EmailUserType如下:
    ?
    ???public?class?EmailUserType?implements?UserType{

    ????
    public?Object?assemble(Serializable?arg0,?Object?arg1)?throws?HibernateException?{
    ????????
    return?null;
    ????}

    ????
    public?Object?deepCopy(Object?o)?throws?HibernateException?{
    ????????
    if(null?==?o)return?null;
    ????????Email?e?
    =?(Email)o;
    ????????
    return?new?Email(e.getUsername(),e.getDomain());
    ????}

    ????
    public?Serializable?disassemble(Object?arg0)?throws?HibernateException?{
    ????????
    return?null;
    ????}

    ????
    public?boolean?equals(Object?x,?Object?y)?throws?HibernateException?{
    ????????
    if(x?==?y)return?true;
    ????????
    if(x?==?null?||?y?==?null)return?false;
    ????????
    boolean??f?=?x.equals(y);
    ????????
    return?f;
    ????}

    ????
    public?int?hashCode(Object?o)?throws?HibernateException?{
    ????????
    return?o.hashCode();
    ????}

    ????
    public?boolean?isMutable()?{
    ????????
    return?true;
    ????}

    ????
    public?Object?nullSafeGet(ResultSet?rs,?String[]?names,?Object?o)?throws?HibernateException,?SQLException?{
    ????????String?email?
    =?rs.getString(names[0]);
    ????????
    if(email?==?null)return?null;
    ????????
    int?index?=?email.indexOf("@");
    ????????
    if(index?<?0)throw?new?RuntimeException();
    ????????
    return?new?Email(email.substring(0,index),email.substring(index+1));
    ????}

    ????
    public?void?nullSafeSet(PreparedStatement?ps,?Object?o,?int?index)?throws?HibernateException,?SQLException?{
    ????????
    if(o?==?null?)ps.setNull(index,?Types.VARCHAR);
    ????????
    else{
    ????????????Email?e?
    =?(Email)o;
    ????????????
    if(e.getDomain()?==?null?||?e.getUsername()?==?null)ps.setNull(index,?Types.VARCHAR);
    ????????????
    else{
    ????????????????String?email?
    =?e.getUsername()?+?"@"?+?e.getDomain();
    ????????????????ps.setString(index,?email);
    ????????????}
    ????????}
    ????????
    ????}

    ????
    public?Object?replace(Object?arg0,?Object?arg1,?Object?arg2)?throws?HibernateException?{
    ????????
    return?null;
    ????}

    ????
    public?Class?returnedClass()?{
    ????????
    return?Email.class;
    ????}

    ????
    public?int[]?sqlTypes()?{
    ????????
    int[]?typeList?=?{Types.VARCHAR};
    ????????
    return?typeList;
    ????}
    }

    ?? ?最后配置下 email 屬性:
    <property name="email" type="org.prague.domain.util.EmailUserType" column="email"></property>
    ?? ?相比于Gedner,Email是一個可變類(如果想將其變?yōu)椴豢勺冾悾恍枰サ魧傩缘膕et方法),因此EmailUserType中的equals要用到Email的equals(hashCode())方法,而deepCopy(Object o) 要做到是深拷貝,否則即便Email屬性內(nèi)容改變,由于Hibernate緩存中的快照指向的對象不變,在update時可能不起作用(在指定了dynamic-update屬性的清況下)。
    ?? ?

    posted on 2007-08-15 10:32 kafka0102 閱讀(1533) 評論(0)  編輯  收藏 所屬分類: Framework
    主站蜘蛛池模板: 色偷偷亚洲女人天堂观看欧| 亚洲人成网亚洲欧洲无码久久| 亚洲天堂电影在线观看| 永久在线观看免费视频| 亚洲精品国产精品乱码不卡| 国产亚洲视频在线观看网址| 国产一区二区三区免费看| 亚洲精品无码久久久久秋霞| 在线免费观看毛片网站| 亚洲精品乱码久久久久久V | 国产国拍亚洲精品福利 | 亚洲一区二区三区AV无码| 在线播放国产不卡免费视频| 亚洲人成无码网WWW| 九九热久久免费视频| 亚洲精品~无码抽插| 免费福利在线视频| 久久久亚洲欧洲日产国码二区| 中国xxxxx高清免费看视频| 亚洲六月丁香六月婷婷蜜芽| 精品国产麻豆免费网站| 国产亚洲情侣久久精品| 亚洲综合色视频在线观看| 黄色片免费在线观看| 亚洲国产精品成人综合久久久 | 亚洲导航深夜福利| 精品久久久久国产免费| 老司机午夜性生免费福利| 亚洲一级片内射网站在线观看| 久久中文字幕免费视频| 亚洲五月综合缴情婷婷| 一本色道久久88亚洲综合 | 日韩精品人妻系列无码专区免费 | 亚洲精品国产av成拍色拍| 日韩亚洲国产二区| 玖玖在线免费视频| 亚洲最大天堂无码精品区| 亚洲精品网站在线观看不卡无广告 | 亚洲av无码一区二区三区人妖| 亚洲?V无码乱码国产精品| 免费国产成人午夜在线观看|