Hibernate Annotation 共享主键一对一双向联系关系
写了这么几篇都是单向的关联,干脆后面的都写双向关联吧,今晚天就把Hibernate Annotation的问题都结了。
使用@OneToOne 注解可以建立实体bean之间的一对一的关联. 一对一关联有三种情况: 一是关联的实体都共享同样的主键, 二是其中一个实体通过外键关联到另一个实体的主键 (注意要模拟一对一关联必须在外键列上添加唯一约束). 三是通过关联表来保存两个实体之间的连接关系 (注意要模拟一对一关联必须在每一个外键上添加唯一约束).(摘自Hibernate Annotation Reference)
本篇是基于共享主键的方式来写的,顾名思义,共享主键即两个表使用一个主键。
数据库脚本:(见附件)
//User.java
package com.zyp.examples; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.OneToOne; import javax.persistence.PrimaryKeyJoinColumn; import javax.persistence.Table; import org.hibernate.annotations.GenericGenerator; /** * User entity. @author MyEclipse Persistence Tools */ @Entity @Table(name="user") public class User implements java.io.Serializable { // Fields private static final long serialVersionUID = 6210252824713630770L; @Id @Column(name="id") @GeneratedValue(generator="incrementGenerator", strategy=GenerationType.IDENTITY) @GenericGenerator(name="incrementGenerator", strategy="increment") private Integer id; @Column(name="name") private String name; @Column(name="password") private String password; @OneToOne(targetEntity=Profile.class, cascade={CascadeType.ALL}) //这里用的是PrimaryKeyJoinColumn,不是JoinColumn @PrimaryKeyJoinColumn private Profile profile; // Constructors /** default constructor */ public User() { } /** full constructor */ public User(String name, String password) { this.name = name; this.password = password; } // Property accessors public Integer getId() { return this.id; } public void setId(Integer id) { this.id = id; } public String getName() { return this.name; } public void setName(String name) { this.name = name; } public String getPassword() { return this.password; } public void setPassword(String password) { this.password = password; } public Profile getProfile() { return profile; } public void setProfile(Profile profile) { this.profile = profile; } }
//Profile.java
package com.zyp.examples; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.OneToOne; import javax.persistence.PrimaryKeyJoinColumn; import javax.persistence.Table; import org.hibernate.annotations.GenericGenerator; import org.hibernate.annotations.Parameter; /** * Profile entity. @author MyEclipse Persistence Tools */ @Entity @Table(name="profile") public class Profile implements java.io.Serializable { // Fields private static final long serialVersionUID = -6436265401783499807L; @Id @Column(name="pid") @GenericGenerator(name="foreignKey", strategy="foreign", parameters=@Parameter(name="property", value="user")) @GeneratedValue(generator="foreignKey", strategy=GenerationType.IDENTITY) private Integer pid; @Column(name="email") private String email; @Column(name="address") private String address; @OneToOne(targetEntity=User.class, cascade={CascadeType.ALL}, mappedBy="profile") @PrimaryKeyJoinColumn(name="id", referencedColumnName="id") private User user; // Constructors /** default constructor */ public Profile() { } /** full constructor */ public Profile(Integer pid, String email, String address) { this.pid = pid; this.email = email; this.address = address; } // Property accessors public Integer getPid() { return this.pid; } public void setPid(Integer pid) { this.pid = pid; } public String getEmail() { return this.email; } public void setEmail(String email) { this.email = email; } public String getAddress() { return this.address; } public void setAddress(String address) { this.address = address; } public User getUser() { return user; } public void setUser(User user) { this.user = user; } }
//HibernateTest.java
package com.zyp.examples; import org.hibernate.Session; public class HibernateTest { public static void main(String[] args) { // addProfileByUser(); // addUserByProfile(); deleteFromUser(); } public static void deleteFromUser() { Session session = HibernateUtil.getSessionFactory().openSession(); session.getTransaction().begin(); session.delete(session.load(User.class, new Integer(1))); session.getTransaction().commit(); } public static void addProfileByUser() { Profile p = new Profile(); p.setAddress("yunnan"); p.setEmail("sdfds@1236.com"); User user = new User(); user.setName("zyp"); user.setPassword("123"); //注意这里是双向关系 user.setProfile(p); p.setUser(user); Session session = HibernateUtil.getSessionFactory().openSession(); session.getTransaction().begin(); session.save(user); session.getTransaction().commit(); } public static void addUserByProfile() { Profile p = new Profile(); p.setAddress("yunnan"); p.setEmail("sdfds@1236.com"); User user = new User(); user.setName("zyp"); user.setPassword("123"); //注意这里是双向关系 user.setProfile(p); p.setUser(user); Session session = HibernateUtil.getSessionFactory().openSession(); session.getTransaction().begin(); //保存profile session.save(p); session.getTransaction().commit(); } }
写这个文章的时候遇到了不少的麻烦,也差了一些资料,下面把一些错误罗列出来,希望大家把参考的URL好好看一下消化下,老实说,Annotation里面的参数还是挺麻烦的,有的时候只能凭感觉和经验。
参考文章
JPA Annotation常用指南
http://blog.sina.com.cn/s/blog_3da1cce1010009dj.html
经典错误:attempted to assign id from null one-to-one
http://hi.baidu.com/88feiquan/item/856bf3dec2b23e15e0f46fe0
Hibernate Mapping One-to-One using Annotations Tutorial
http://www.dzone.com/tutorials/java/hibernate/hibernate-example/hibernate-mapping-one-to-one-using-annotations-1.html
http://stackoverflow.com/questions/787698/jpa-hibernate-one-to-one-relationship