JPA初探06---多对多的双向关联

多对多的关系,在项目中一定会遇到,而我们在项目中一定会遇到的权限控制。
在权限控制中: 角色和权限的关系就是多对多的关系

下面我们来看看是怎么样进行JPA的配置的

【Java类设计】

package ManyToMany;

import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

/**
 * 权限类
 * @author 青山
 * @date 2014年10月19日
 * @file name: RightBean.java
 * 
 * 	create table t_right(
		rightid int primary key auto_increment,
		rightname varchar(45)
	);
 */
@Entity
@Table(name="t_right")
public class RightBean {
	@Id
	@Column(name="rightid")
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	private int id;
	
	@Column(name="rightname")
	private String rname;
	
	//many端默认的就是延迟加载
	@ManyToMany(cascade={CascadeType.REFRESH},mappedBy="rightSet",fetch=FetchType.LAZY)//这里RightBean被选为关系的被维护端,用mappedBy表示,填写的值是维护关系的属性的名称
	private Set<RoleBean> roleSet;
	
	
	public Set<RoleBean> getRoleSet() {
		return roleSet;
	}
	public void setRoleSet(Set<RoleBean> roleSet) {
		this.roleSet = roleSet;
	}
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getRname() {
		return rname;
	}
	public void setRname(String rname) {
		this.rname = rname;
	}
	
	
}


package ManyToMany;

import java.util.Set;

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.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

/**
 * 角色类
 * @author 青山
 * @date 2014年10月19日
 * @file name: RoleBean.java
 * 
 * 	create table t_role(
		roleid int primary key auto_increment,
		rolename varchar(45)
	);
	
	双向关系:是对等关系,关系维护端是自由选择的,当然一旦选定,以后只能由已选择的里维护
	在这里:角色被选为关系维护端
	
	中间表:
		create table t_role_right(
			role_id int,
			right_id int
		);

 * 
 */
@Entity
@Table(name="t_role")
public class RoleBean {
	@Id
	@Column(name="roleid")
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	private int id;
	
	@Column(name="rolename")
	private String rname;
	
	@ManyToMany(cascade=CascadeType.REFRESH)
	//多对多关系处理使用中间表使用注解JoinTable
	//inverseJoinColumns: (inverse表示被维护端) ,针对被维护端的外键的定义
	//joinColumns: 关系维护端的定义
	@JoinTable(name="t_role_right",
			inverseJoinColumns=@JoinColumn(name="right_id"),
			joinColumns=@JoinColumn(name="role_id")) 
	private Set<RightBean> rightSet;

	
	public int getId() {
		return id;
	}


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


	public String getRname() {
		return rname;
	}


	public void setRname(String rname) {
		this.rname = rname;
	}


	public Set<RightBean> getRightSet() {
		return rightSet;
	}


	public void setRightSet(Set<RightBean> rightSet) {
		this.rightSet = rightSet;
	}
	
	
}
【测试】

package ManyToMany;

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

import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;

import util.JPAManagerFactory;

/**
 * 
 * @author 青山
 * @date 2014年10月19日
 * @file name: ManyTest.java
 */
public class ManyTest {
	public static void main(String[] args) {
		EntityManager manager = JPAManagerFactory.getMFInstance().getManager();
		EntityTransaction t = manager.getTransaction();
		t.begin();
		
//		add(manager);
//		query(manager);
		
//		remove(manager);
		
		
		remove2(manager);
		
		
		t.commit();
		manager.close();
	}

	static void remove2(EntityManager manager) {
//		RightBean right = manager.find(RightBean.class, 1);
//		manager.remove(right);
		/**
		 * result: error com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: 
		 * 		   Cannot delete or update a parent row: a foreign key constraint fails 
		 * 		   (`world`.`t_role_right`, CONSTRAINT `fk_right_id` FOREIGN KEY (`right_id`) 
		 * 			REFERENCES `t_right` (`rightid`) ON DELETE NO ACTION ON UPDATE NO ACTION)
		 * 原因:删除的权限记录是关系的被维护端,它是没有权利去维护关系的,也就是说没有权利去删除中间表
		 * 解决方案:首先需要断开联系,再来进行删除;或者是先删除中间表的记录,再来删除权限表的记录
		 */
		
		
		RightBean right = manager.find(RightBean.class, 1);
		//由于RightBean没有关系的操作权限,而RoleBean又权限,所以只需要在所有和需要删除的权限有关系的RoleBean中的权限列表的权限移除就可以了
		Set<RoleBean> set = right.getRoleSet();
		for(RoleBean role : set){
			role.getRightSet().remove(right);
		}
		
		manager.remove(right);
	}

	static void remove(EntityManager manager) {
		/**
		 * 因为RoleBean是关系的维护端,所有能够JPA先删除了中间表的记录,然后再删除角色记录
		 */
		RoleBean role = manager.find(RoleBean.class, 1);
		manager.remove(role);
		/**
		 * result:
		 *  Hibernate: select rolebean0_.roleid as roleid1_7_0_, rolebean0_.rolename as rolename2_7_0_ from t_role rolebean0_ where rolebean0_.roleid=?
			Hibernate: delete from t_role_right where role_id=?
			Hibernate: delete from t_role where roleid=?
		 */
	}

	static void query(EntityManager manager) {
		 RoleBean role = manager.find(RoleBean.class, 1);
		System.out.println(role.getRname());
		Set<RightBean> set = role.getRightSet();
		for(RightBean right : set){
			System.out.println(right.getRname());
		}
		/**
		 * result:
		 * Hibernate: select rolebean0_.roleid as roleid1_7_0_, rolebean0_.rolename as rolename2_7_0_ from t_role rolebean0_ where rolebean0_.roleid=?
			二级管理员
			Hibernate: select rightset0_.role_id as role_id1_7_0_, rightset0_.right_id as right_id2_8_0_, rightbean1_.rightid as rightid1_6_1_, rightbean1_.rightname as rightnam2_6_1_ from t_role_right rightset0_ inner join t_right rightbean1_ on rightset0_.right_id=rightbean1_.rightid where rightset0_.role_id=?
			普通权限
		 */
	}

	static void add(EntityManager manager) {
		 RoleBean r1 = new RoleBean();
			RoleBean r2 = new RoleBean();
			
			r1.setRname("一级管理员");
			r2.setRname("二级管理员");
			
			RightBean r11 = new RightBean();
			RightBean r12 = new RightBean();
			
			r11.setRname("超级权限");
			r12.setRname("普通权限");
			
			Set<RightBean> s1 = new HashSet<RightBean>();
			Set<RightBean> s2 = new HashSet<RightBean>();
			
			Set<RoleBean> s11 = new HashSet<RoleBean>();
			Set<RoleBean> s22 = new HashSet<RoleBean>();
			
			s1.add(r12);
			s1.add(r11);
			
			s2.add(r12);
			
			s11.add(r1);
			s11.add(r2);
			
			s22.add(r1);
			
			r1.setRightSet(s1);
			r2.setRightSet(s2);
			
			r11.setRoleSet(s11);
			r12.setRoleSet(s22);
			
			manager.persist(r12);
			manager.persist(r11);
			manager.persist(r2);
			manager.persist(r1);
			
			
	}
	
	 
}

 

你可能感兴趣的:(jpa)