Hibernate Annotation 共享主键一对一双向联系关系

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