[原創]hibernate 一對一實踐 by hjack

最近做的一個工程要用到hibernate的一對一關聯,比如論壇的一個主題對應一個作者。
hibernate的一對一關係有兩種形式,一種是共享主鍵方式,另一種是惟一外鍵方式,因爲這裏用到的是在主題表裏與作者表之間的對應關係,所以介紹的是惟一外鍵方式的一以一關聯。
由於網上很多教程都說得不清楚,給出的實例不能正確運行,所以寫下這份筆記,以便以後查詢,並與大家分享,如有不對的地方請指正。
本測試使用mysql數據庫,eclipse2.1平臺,使用tanghan插件生成hbm文件。

1、新建數據庫表如下:
    CREATE TABLE `author` (
      `id` int(11) NOT NULL auto_increment,
      `name` varchar(50) default NULL,
      PRIMARY KEY  (`id`)
    );
    CREATE TABLE `topic` (
      `id` int(11) NOT NULL auto_increment,
      `name` varchar(50) default NULL,
      `user_id` int(11) default NULL,
      PRIMARY KEY  (`id`)
    );

2、用tanghan建立數據庫連接,並對這兩個表生成相應的hbm文件(也可以手工編寫這些文件)。
Topic.hbm.xml文件如下:
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 2.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
    <hibernate-mapping>
    <class name="model.Topic" table="topic">
    <id column="id" length="11" name="id" type="integer">
    <generator class="native"/>
    </id>
    <property column="name" length="50" name="name" type="string"/>
    <property column="user_id" length="11" name="user_id" type="integer"/>
    </class>
    </hibernate-mapping>
   
Author.hbm.xml文件如下:
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 2.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
    <hibernate-mapping>
    <class name="model.Author" table="author">
    <id column="id" length="11" name="id" type="integer">
    <generator class="native"/>
    </id>
    <property column="name" length="50" name="name" type="string"/>
    </class>
    </hibernate-mapping>
   
Author.java文件如下:
    package model;
   
    import java.io.Serializable;
    import org.apache.commons.lang.builder.EqualsBuilder;
    import org.apache.commons.lang.builder.HashCodeBuilder;
    import org.apache.commons.lang.builder.ToStringBuilder;
   
    /** @author Hibernate CodeGenerator */
    public class Author implements Serializable {
   
        /** identifier field */
        private int id;
   
        /** nullable persistent field */
        private String name;
   
        /** full constructor */
        public Author(java.lang.String name) {
            this.name = name;
        }
   
        /** default constructor */
        public Author() {
        }
   
        public int getId() {
            return this.id;
        }
   
     public void setId(int id) {
      this.id = id;
     }
   
        public java.lang.String getName() {
            return this.name;
        }
   
     public void setName(java.lang.String name) {
      this.name = name;
     }
   
        public String toString() {
            return new ToStringBuilder(this)
                .append("id", getId())
                .toString();
        }
   
        public boolean equals(Object other) {
            if ( !(other instanceof Author) ) return false;
            Author castOther = (Author) other;
            return new EqualsBuilder()
                .append(this.getId(), castOther.getId())
                .isEquals();
        }
   
        public int hashCode() {
            return new HashCodeBuilder()
                .append(getId())
                .toHashCode();
        }
   
    }
   
Topic.java文件如下:
    package model;
   
    import java.io.Serializable;
    import org.apache.commons.lang.builder.EqualsBuilder;
    import org.apache.commons.lang.builder.HashCodeBuilder;
    import org.apache.commons.lang.builder.ToStringBuilder;
   
    /** @author Hibernate CodeGenerator */
    public class Topic implements Serializable {
   
        /** identifier field */
        private int id;
   
        /** nullable persistent field */
        private String name;
   
        /** nullable persistent field */
        private int user_id;
   
        /** full constructor */
        public Topic(java.lang.String name, int user_id) {
            this.name = name;
            this.user_id = user_id;
        }
   
        /** default constructor */
        public Topic() {
        }
   
        public int getId() {
            return this.id;
        }
   
     public void setId(int id) {
      this.id = id;
     }
   
        public java.lang.String getName() {
            return this.name;
        }
   
     public void setName(java.lang.String name) {
      this.name = name;
     }
   
        public int getUser_id() {
            return this.user_id;
        }
   
     public void setUser_id(int user_id) {
      this.user_id = user_id;
     }
   
        public String toString() {
            return new ToStringBuilder(this)
                .append("id", getId())
                .toString();
        }
   
        public boolean equals(Object other) {
            if ( !(other instanceof Topic) ) return false;
            Topic castOther = (Topic) other;
            return new EqualsBuilder()
                .append(this.getId(), castOther.getId())
                .isEquals();
        }
   
        public int hashCode() {
            return new HashCodeBuilder()
                .append(getId())
                .toHashCode();
        }
   
    }

3、修改Topic.java文件。
找到 private int user_id;
修改成private Author author;
找到 構造函數public Topic(java.lang.String name, int user_id),把參數int user_id改爲Author author, 把函數裏的this.user_id = user_id; 改爲this.author = author;
找到以下兩個函數
      public int getUser_id() {
        return this.user_id;
      }
   
     public void setUser_id(int user_id) {
      this.user_id = user_id;
     }
修改爲
     public Author getAuthor() {
      return author;
     }
   
     public void setAuthor(Author author) {
      this.author = author;
     }
然後保存。以上文件保存在model包裏。

4、修改Topic.hbm.xml文件。
刪除下面這行
<property column="user_id" length="11" name="user_id" type="integer"/>
在</class>前添回<many-to-one>項如下
<many-to-one name="author" class="model.Author" column="user_id" unique="true"/>

通過以上操作就建立了Topic表與Author表之間的單向一對一關係,因爲本工程中只需要從主題表去了解作者的信息,所以只需要單向的一對一就可以完成了。

5、建立測試用例。
1)、新建test包,在test包內建立HibernateUtil類。
    /*
     * 創建日期 2005-8-4
     *
     * TODO 要更改此生成的文件的模板,請轉至
     * 窗口 - 首選項 - Java - 代碼樣式 - 代碼模板
     */
    package test;
   
    /**
     * @author hjack<br>
     *
     * TODO 要更改此生成的類型註釋的模板,請轉至
     * 窗口 - 首選項 - Java - 代碼樣式 - 代碼模板
     */
   
   
    import net.sf.hibernate.HibernateException;
    import net.sf.hibernate.Session;
    import net.sf.hibernate.SessionFactory;
    import net.sf.hibernate.cfg.Configuration;
   
    public class HibernateUtil {
   
     private static final SessionFactory sessionFactory;
     private static Configuration cfg = null;
   
     static {
      try {
       cfg = new Configuration();
       sessionFactory =cfg.configure().buildSessionFactory();
      } catch (HibernateException ex) {
       throw new RuntimeException(
        "Exception building SessionFactory: " + ex.getMessage(),
        ex);
      }
     }
   
     public static final ThreadLocal session = new ThreadLocal();
   
     public static Session currentSession() throws HibernateException {
      Session s = (Session) session.get();
      // Open a new Session, if this Thread has none yet
      if (s == null) {
       s = sessionFactory.openSession();
       session.set(s);
      }
      return s;
     }
   
     public static void closeSession() throws HibernateException {
      Session s = (Session) session.get();
      session.set(null);
      if (s != null)
       s.close();
     }
    }
   
hibernate.cfg.xml文件內容如下:
    <!DOCTYPE hibernate-configuration PUBLIC
     "-//Hibernate/Hibernate Configuration DTD//EN"
     "http://hibernate.sourceforge.net/hibernate-configuration-2.0.dtd">
    <hibernate-configuration>
     <session-factory>
      <!--<property name="connection.datasource">java:comp/env/jdbc/mysql</property>-->
      <property name="dialect">net.sf.hibernate.dialect.MySQLDialect</property>
      <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
      <property name="connection.url">jdbc:mysql://localhost/testhibernate</property>
      <property name="connection.username">root</property>
      <property name="connection.password"></property>
      <property name="show_sql">true</property>
      <!--mapping files-->
      <mapping resource="model/Author.hbm.xml"></mapping>
      <mapping resource="model/Topic.hbm.xml"></mapping>
     </session-factory>
    </hibernate-configuration>   

2)、新建Test類,用於測試。
    /*
     * 創建日期 2005-8-10
     *
     * 更改所生成文件模板爲
     * 窗口 > 首選項 > Java > 代碼生成 > 代碼和註釋
     */
    package test;
   
    import model.Author;
    import model.Topic;
    import net.sf.hibernate.HibernateException;
    import net.sf.hibernate.Session;
    import net.sf.hibernate.Transaction;
   
    /**
     * @author hjack
    
     * 更改所生成類型註釋的模板爲
     * 窗口 > 首選項 > Java > 代碼生成 > 代碼和註釋
     */
    public class Test {
   
     Session sess;
     Transaction tx;
     
     public void insertTopic(Topic topic,int userID) throws HibernateException{
      try{
       sess = HibernateUtil.currentSession();
       tx = sess.beginTransaction();
       //新建一個author對象,並把作者id置入該對象裏。   
       Author author = new Author();
       author.setId(userID);   
       //新建一個topic對象,設置用戶名和把author對象set進去。
       topic.setAuthor(author);
       //因爲只是插入一個話題,並不必在author表中插入一條記錄,所以只需save(topic)   
       sess.save(topic);
       tx.commit();
      }catch(HibernateException e){
       System.out.println(e.toString());
      }finally{
       if(tx!=null){
        tx.rollback();
       }
       HibernateUtil.closeSession();
      }
     }
     
     public void insertAuthor(Author author) throws HibernateException{
      try{
       sess = HibernateUtil.currentSession();
       tx = sess.beginTransaction();
       sess.save(author);
       tx.commit();
      }catch(HibernateException e){
       System.out.println(e.toString());
      }finally{
       if(tx!=null){
        tx.rollback();
       }
       HibernateUtil.closeSession();
      }
     }
   
   
     public Topic query(int id) throws HibernateException{
      Topic topic = null;
      try{
       sess = HibernateUtil.currentSession();   
       topic=(Topic)sess.load(Topic.class,new Integer(id));   
      }catch(HibernateException e){
       e.printStackTrace();
      }finally{
       HibernateUtil.closeSession();
      }
      return topic;
     }
     
     public static void main(String[] args) {
      
      Test app = new Test();
      try {
       /*測試插入作者
       Author author = new Author();
       author.setName("jack");
       app.insertAuthor(author);
       */
       /*測試插入主題
       Topic topic = new Topic();
       topic.setName("helloworld.");
       app.insertTopic(topic,1);
       */
       /*測試查詢主題
       Topic topic = app.query(1);
       System.out.println(topic.getAuthor().getName());
       */
      } catch (Exception e) {
       // TODO 自動生成 catch 塊
       e.printStackTrace();
      }
      
     }
    }

測試插入作者如圖1所示,測試插入主題如圖2所示,測試查詢主題結果如下:
Hibernate: select topic0_.id as id1_, topic0_.name as name1_, topic0_.user_id as user_id1_, author1_.id as id0_, author1_.name as name0_ from topic topic0_ left outer join author author1_ on topic0_.user_id=author1_.id where topic0_.id=?
jack
生成的sql語句用到了join,查詢結果爲jack,與期望相符。

圖一

圖二

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章