|
最近做的一個工程要用到hibernate的一對一關聯(lián),比如論壇的一個主題對應一個作者。 hibernate的一對一關系有兩種形式,一種是共享主鍵方式,另一種是惟一外鍵方式,因為這里用到的是在主題表里與作者表之間的對應關系,所以介紹的是惟一外鍵方式的一以一關聯(lián)。 由于網(wǎng)上很多教程都說得不清楚,給出的實例不能正確運行,所以寫下這份筆記,以便以后查詢,并與大家分享,如有不對的地方請指正。 本測試使用mysql數(shù)據(jù)庫,eclipse2.1平臺,使用tanghan插件生成hbm文件。
1、新建數(shù)據(jù)庫表如下: 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建立數(shù)據(jù)庫連接,并對這兩個表生成相應的hbm文件(也可以手工編寫這些文件)。 Topic.hbm.xml文件如下: <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 2.0//EN" "http://hibernate./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./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; 找到 構造函數(shù)public Topic(java.lang.String name, int user_id),把參數(shù)int user_id改為Author author, 把函數(shù)里的this.user_id = user_id; 改為this.author = author; 找到以下兩個函數(shù) 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類。 /* * 創(chuàng)建日期 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./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類,用于測試。 /* * 創(chuàng)建日期 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,與期望相符。
圖一
圖二
|