最近做的一個(gè)工程要用到hibernate的一對(duì)一關(guān)聯(lián),比如論壇的一個(gè)主題對(duì)應(yīng)一個(gè)作者。
hibernate的一對(duì)一關(guān)系有兩種形式,一種是共享主鍵方式,另一種是惟一外鍵方式,因?yàn)檫@里用到的是在主題表里與作者表之間的對(duì)應(yīng)關(guān)系,所以介紹的是惟一外鍵方式的一以一關(guān)聯(lián)。
由于網(wǎng)上很多教程都說(shuō)得不清楚,給出的實(shí)例不能正確運(yùn)行,所以寫下這份筆記,以便以后查詢,并與大家分享,如有不對(duì)的地方請(qǐng)指正。
本測(cè)試使用mysql數(shù)據(jù)庫(kù),eclipse2.1平臺(tái),使用tanghan插件生成hbm文件。
1、新建數(shù)據(jù)庫(kù)表如下:
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ù)庫(kù)連接,并對(duì)這兩個(gè)表生成相應(yīng)的hbm文件(也可以手工編寫這些文件)。
Topic.hbm.xml文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 2.0//EN" " <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" " <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;
找到 構(gòu)造函數(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;
找到以下兩個(gè)函數(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>項(xiàng)如下
<many-to-one name="author" class="model.Author" column="user_id" unique="true"/>
通過(guò)以上操作就建立了Topic表與Author表之間的單向一對(duì)一關(guān)系,因?yàn)楸竟こ讨兄恍枰獜闹黝}表去了解作者的信息,所以只需要單向的一對(duì)一就可以完成了。
5、建立測(cè)試用例。
1)、新建test包,在test包內(nèi)建立HibernateUtil類。
/*
* 創(chuàng)建日期 2005-8-4
*
* TODO 要更改此生成的文件的模板,請(qǐng)轉(zhuǎn)至
* 窗口 - 首選項(xiàng) - Java - 代碼樣式 - 代碼模板
*/
package test;
/**
* @author hjack<br>
*
* TODO 要更改此生成的類型注釋的模板,請(qǐng)轉(zhuǎn)至
* 窗口 - 首選項(xiàng) - 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文件內(nèi)容如下:
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD//EN"
" <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類,用于測(cè)試。
/*
* 創(chuàng)建日期 2005-8-10
*
* 更改所生成文件模板為
* 窗口 > 首選項(xiàng) > 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
* 更改所生成類型注釋的模板為
* 窗口 > 首選項(xiàng) > Java > 代碼生成 > 代碼和注釋
*/
public class Test {
Session sess;
Transaction tx;
public void insertTopic(Topic topic,int userID) throws HibernateException{
try{
sess = HibernateUtil.currentSession();
tx = sess.beginTransaction();
//新建一個(gè)author對(duì)象,并把作者id置入該對(duì)象里。
Author author = new Author();
author.setId(userID);
//新建一個(gè)topic對(duì)象,設(shè)置用戶名和把a(bǔ)uthor對(duì)象set進(jìn)去。
topic.setAuthor(author);
//因?yàn)橹皇遣迦胍粋€(gè)話題,并不必在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 {
/*測(cè)試插入作者
Author author = new Author();
author.setName("jack");
app.insertAuthor(author);
*/
/*測(cè)試插入主題
Topic topic = new Topic();
topic.setName("helloworld.");
app.insertTopic(topic,1);
*/
/*測(cè)試查詢主題
Topic topic = app.query(1);
System.out.println(topic.getAuthor().getName());
*/
} catch (Exception e) {
// TODO 自動(dòng)生成 catch 塊
e.printStackTrace();
}
}
}
測(cè)試插入作者如圖1所示,測(cè)試插入主題如圖2所示,測(cè)試查詢主題結(jié)果如下:
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語(yǔ)句用到了join,查詢結(jié)果為jack,與期望相符。
圖一
圖二
聯(lián)系客服