日期:2014-05-16  浏览次数:20496 次

hibernate中双向关联在级联情况下save对象讨论

一般在双向关联的情况下,都要在一方设置mappedBy(name="xxx"),由对方主导映射关系。在多对一的情况下,一般在多的一方设置主导映射的关系(为了方便叙述,就这么叫它了,呵呵)。所谓主导这种映射关系,如group,user,就是由多的一方(user)里面产生一个外键参考一的一方(group)的主键,这时候user就是主导的一方,写mappedBy是被主导的一方。在多对多的情况下,随便由那方主导,在数据库表的结构上都是一样的,都会产生一个中间表,中间表有两个字段的联合主键,分别作为外键参考两个多的一方。

在一对多和多对多的双向关联的情况下,并且在cascade=CascadeType.ALL情况下,save不同方面(如主导关系一方或被主导的一方)在级联的具体表现上是不同的。分别来讨论一下。

先看一对多的双向关联关系,这里就拿group和user举例。

Group类如下:

package com.chen.hibernate.ormapping;

import java.util.HashSet;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;

@Entity
@Table(name = "t_group")
public class Group {
	private int id;
	private String name;
	private Set<User> users = new HashSet<User>();

	@Id
	@GeneratedValue
	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	// 设置mappedBy是被主导的一方 
	@OneToMany(mappedBy = "group", cascade = { CascadeType.ALL }, fetch = FetchType.LAZY)
	public Set<User> getUsers() {
		return users;
	}

	public void setUsers(Set<User> users) {
		this.users = users;
	}
}

User类如下:

package com.chen.hibernate.ormapping;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

@Entity
@Table(name = "t_user")
public class User {
	private int id;
	private String name;
	private Group group;

	@Id
	@GeneratedValue
	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	//设置fetch为lazy,多的一方默认问eager
	@ManyToOne(cascade = { CascadeType.ALL }, fetch = FetchType.EAGER)
	@JoinColumn(name = "groupId")
	public Group getGroup() {
		return group;
	}

	public void setGroup(Group group) {
		this.group = group;
	}
}

junit测试类

package com.chen.hibernate.ormapping;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.tool.hbm2ddl.SchemaExport;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;

public class CRUDTest {
	private static SessionFactory sessionFactory = null;

	@BeforeClass
	public static void beforeClass() {
		new SchemaExport(new AnnotationConfiguration().configure()).create(
				false, true);
		sessionFactory = new AnnotationConfiguration().configure()
				.buildSessionFactory();
	}

	@Test
	public void testSaveUser() {
		User user = new User();
		user.setName("u1");
		Group group = new Group();
		group.setName("g1");

		// 这里仅仅把group加到user中,而不需要group.getUsers().add(user);把当前的对象加入到group的set里
		user.setGroup(group);

		Session session = sessionFactory.getCurrentSession();
		session.beginTransaction();
		session.save(user);
		session.getTransaction().commit();
	}

	// 再看看save被主导的一方会如何。
	@Test
	public void testSaveGroup() {
		// 先new两个user,一个group,然后把user加到group中
		User user = new User();
		user.setName("u1");

		User user2 = new User();
		user2.setName("u2");
		Group group = new Group();
		group.setName("g1");
		group.getUsers().add(user);
		group.getUsers().add(user2);

		// 注意,虽然两边都是级联的方式,但這裡的user也要把group设一下,不然,save(group)的时候,user表中的
		// groupId字段仍是null
		user.setGroup(group);
		user2.setGroup(group);

		Sess