我在Github上面写了一个例子,用于展示Hibernate中OneToOne的用法:
https://github.com/liweinan/javaee
可以签出这个代码,然后执行maven打包:
mvn package
然后部署在AS7里面。注意在部署之前要修改一下AS7的数据库配置:
jboss-as-7.1.1.Final/standalone$ vi configuration/standalone.xml
<datasources>
<datasource jndi-name="java:jboss/datasources/ExampleDS" pool-name="ExampleDS" enabled="true" use-java-context="true">
<connection-url>jdbc:h2:/usr/local/db/h2db</connection-url>
<driver>h2</driver>
<security>
<user-name>sa</user-name>
<password>sa</password>
</security>
</datasource>
这样,H2会生成数据库文件至/usr/local/db/h2db,方便调试。
核心代码是User及Address。User和Address是一对一的关系,此外,Address的主键要求与User保持一致,而User的主键由Hibernate负责生成UUID:
package net.bluedash.model.sandbox.onetoone;
import org.hibernate.annotations.GenericGenerator;
import javax.persistence.*;
import java.io.Serializable;
/**
* 11 11 2012
*
* @author [url=mailto:[email protected]]Weinan Li[/url]
*/
@Entity
@Table(name = "onetoone_user")
public class User implements Serializable {
@Id
@GeneratedValue(generator = "uuid")
@GenericGenerator(name = "uuid", strategy = "uuid2")
private String id;
@OneToOne(cascade = CascadeType.ALL, mappedBy = "user")
@PrimaryKeyJoinColumn
private Address contactAddress;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public Address getContactAddress() {
return contactAddress;
}
public void setContactAddress(Address contactAddress) {
this.contactAddress = contactAddress;
}
}
package net.bluedash.model.sandbox.onetoone;
import org.hibernate.annotations.*;
import javax.persistence.*;
import javax.persistence.Entity;
import javax.persistence.Table;
import java.io.Serializable;
/**
* 11 11 2012
*
* @author [url=mailto:[email protected]]Weinan Li[/url]
*/
@Entity
@Table(name = "onetoone_address")
public class Address implements Serializable {
@Id
@GeneratedValue(generator = "foreign")
@GenericGenerator(name = "foreign", strategy = "foreign", parameters = @org.hibernate.annotations.Parameter(name = "property", value = "user"))
private String id;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
@OneToOne
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
注意上面的Hibernate与JPA标记的混用。Hibernate的扩展功能是非常强大的,可以帮助我们生成Address的主键并与User保持一致。
在AS7里面部署项目:
部署成功的话,可以看到数据库被生成了:
进到H2的Console可以看看生成的数据库表结构:
需要注意的是SeedImporter中的代码:
{
net.bluedash.model.sandbox.onetoone.Address address
= new net.bluedash.model.sandbox.onetoone.Address();
net.bluedash.model.sandbox.onetoone.User user
= new net.bluedash.model.sandbox.onetoone.User();
user.setContactAddress(address);
address.setUser(user);
em.persist(user);
log.info("ONETOONE_USER ID: " + user.getId());
log.info("ONETOONE_ADDRESS ID: " + address.getId());
}
其中这行非常重要:
address.setUser(user);
Hibernate需要知道user的主键,才能将user的主键赋给address,从而保证@PrimaryKeyJoinColumn的约定条件,即User与Address保证主键一致。