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

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

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

    邊城愚人

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

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

    ?? ?接下來定義實現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實例,這個方法是在從數據庫查詢數據時用到。
    ?????
    */
    ????
    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來實現同樣的功能,感興趣的朋友可以參考文章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是一個可變類(如果想將其變為不可變類,只需要去掉屬性的set方法),因此EmailUserType中的equals要用到Email的equals(hashCode())方法,而deepCopy(Object o) 要做到是深拷貝,否則即便Email屬性內容改變,由于Hibernate緩存中的快照指向的對象不變,在update時可能不起作用(在指定了dynamic-update屬性的清況下)。
    ?? ?

    posted on 2007-08-15 10:32 kafka0102 閱讀(1526) 評論(0)  編輯  收藏 所屬分類: Framework
    主站蜘蛛池模板: 4虎1515hh永久免费| 在人线av无码免费高潮喷水| 91免费资源网站入口| 日韩亚洲国产综合久久久| 一本到卡二卡三卡免费高| 性xxxx视频免费播放直播 | 日本免费福利视频| 国产亚洲精品自在久久| 亚洲私人无码综合久久网| 中文字幕一区二区免费| 热99re久久免费视精品频软件| 亚洲不卡中文字幕无码| 精品国产亚洲第一区二区三区| 亚洲AV无码专区在线电影成人| 永久免费AV无码网站国产| 特级淫片国产免费高清视频| 水蜜桃亚洲一二三四在线| 美女露100%胸无遮挡免费观看| 最近中文字幕高清免费中文字幕mv| 免费不卡视频一卡二卡| 亚洲熟妇av一区二区三区漫画| 亚洲日韩国产二区无码| 99精品视频在线观看免费专区| 亚洲成A人片77777国产| 久久久国产亚洲精品| 无码国产精品一区二区免费3p | 亚洲国产精品综合一区在线| 久久国产精品免费| 国产精品成人无码免费| 91午夜精品亚洲一区二区三区| 青柠影视在线观看免费| 又粗又大又长又爽免费视频 | 国产亚洲中文日本不卡二区| 免费在线中文日本| 亚洲一级黄色视频| 99亚洲精品高清一二区| 亚洲第一成年网站视频| 国产成人免费在线| 亚洲一区二区成人| 中文字幕免费观看视频| 亚洲JIZZJIZZ中国少妇中文|