基本需求是:一个项目可以有多个开发人员,一个开发人员可以参加多个项目,因此项目和开发人员是多对多的关系。本文中的学习重点,还和前几篇文章一样,都是JavaBean类的映射文件中的配置。


1、多对多映射

Project.java

package com.rk.hibernate.h_many2many;

import java.util.Set;

public class Project
{
	private int prjId;
	private String prjName;
	private Set<Developer> devps;
	public int getPrjId()
	{
		return prjId;
	}
	public void setPrjId(int prjId)
	{
		this.prjId = prjId;
	}
	public String getPrjName()
	{
		return prjName;
	}
	public void setPrjName(String prjName)
	{
		this.prjName = prjName;
	}
	public Set<Developer> getDevps()
	{
		return devps;
	}
	public void setDevps(Set<Developer> devps)
	{
		this.devps = devps;
	}
}

Project.hbm.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.rk.hibernate.h_many2many" auto-import="true">
	<class name="Project" table="T_Project">
		<id name="prjId" column="id">
			<generator class="native"></generator>
		</id>
		<property name="prjName" column="name"></property>
		<set name="devps" table="R_Project_Developer" inverse="true" cascade="save-update">
			<key column="prjId"></key>
			<many-to-many column="devpId" class="Developer"></many-to-many>
		</set>
	</class>
</hibernate-mapping>

Developer.java

package com.rk.hibernate.h_many2many;

import java.util.Set;

public class Developer
{
	private int devpId;
	private String devpName;
	private Set<Project> prjs;
	public int getDevpId()
	{
		return devpId;
	}
	public void setDevpId(int devpId)
	{
		this.devpId = devpId;
	}
	public String getDevpName()
	{
		return devpName;
	}
	public void setDevpName(String devpName)
	{
		this.devpName = devpName;
	}
	public Set<Project> getPrjs()
	{
		return prjs;
	}
	public void setPrjs(Set<Project> prjs)
	{
		this.prjs = prjs;
	}
	@Override
	public String toString()
	{
		return "Developer [devpId=" + devpId + ", devpName=" + devpName + "]";
	}
	
}

Developer.hbm.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.rk.hibernate.h_many2many" auto-import="true">
	<class name="Developer" table="T_Developer">
		<id name="devpId" column="id">
			<generator class="native"></generator>
		</id>
		<property name="devpName" column="name"></property>
		<set name="prjs" table="R_Project_Developer">
			<key column="devpId"></key>
			<many-to-many column="prjId" class="Project"></many-to-many>
		</set>
	</class>
</hibernate-mapping>

App.java

 

package com.rk.hibernate.h_many2many;

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

import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.classic.Session;
import org.junit.Test;

public class App
{
	private static SessionFactory sf;
	static
	{
		sf = new Configuration()
				.configure()
				.addClass(Project.class)
				.addClass(Developer.class)
				.buildSessionFactory();
	}
	
	// 1. 多对多,保存  【只能通过一方维护另外一方,不能重复维护!】
	@Test
	public void testSave()
	{
		int i = 0;
		Session session = sf.openSession();
		session.beginTransaction();
		
		// 创建项目对象
		Project prj1 = new Project();
		prj1.setPrjName("AO项目" + i);
		
		Project prj2 = new Project();
		prj2.setPrjName("电商项目" + i);
		
		// 创建开发人员对象
		Developer devp1 = new Developer();
		devp1.setDevpName("张三" + i);
		Developer devp2 = new Developer();
		devp2.setDevpName("李四" + i);
		Developer devp3 = new Developer();
		devp3.setDevpName("王五" + i);
		
		// 关系 【项目方来维护】
		Set<Developer> set1 = new HashSet<Developer>();
		set1.add(devp1);
		set1.add(devp2);
		
		Set<Developer> set2 = new HashSet<Developer>();
		set2.add(devp2);
		set2.add(devp3);
		
		prj1.setDevps(set1);
		prj2.setDevps(set2);
		
		// 保存
		session.save(devp1);
		session.save(devp2);
		session.save(devp3);
		
		session.save(prj1);
		session.save(prj2);
		
		session.getTransaction().commit();
		session.close();
		System.out.println("执行结束!");
	}
	

}


2、inverse属性对关联关系的影响


inverse属性对操作的影响
序号操作类型是否影响具体说明
1保存数据有影响

inverse=false ,有控制权,可以维护关联关系; 保存数据的时候会把对象关系插入中间表;

inverse=true,  没有控制权, 不会往中间表插入数据。

2获取数据获取数据只是参照中间表中保存的关系,并不会对这种关系进行修改,因此获取数据不会受到影响。
3解除关联关系有影响

inverse=false ,有控制权, 解除关系就是删除中间表的数据。

inverse=true, 没有控制权,不能解除关系。

4删除数据有影响

inverse=false, 有控制权。 先删除中间表数据,再删除自身。

inverse=true, 没有控制权。 如果删除的数据有被引用,会报错! 否则,才可以删除


App_Inverse.java

package com.rk.hibernate.h_many2many;

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

import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.classic.Session;
import org.junit.Test;

public class App_Inverse
{
	private static SessionFactory sf;
	static
	{
		sf = new Configuration()
				.configure()
				.addClass(Project.class)
				.addClass(Developer.class)
				.buildSessionFactory();
	}
	
	// 多对多
	//1. 设置inverse属性,对保存数据影响?
	// 有影响。
	// inverse=false ,有控制权,可以维护关联关系; 保存数据的时候会把对象关系插入中间表;
	// inverse=true,  没有控制权, 不会往中间表插入数据。
	@Test
	public void testSave()
	{
		int i = 6;
		Session session = sf.openSession();
		session.beginTransaction();
		
		// 创建项目对象
		Project prj1 = new Project();
		prj1.setPrjName("AO项目" + i);
		
		Project prj2 = new Project();
		prj2.setPrjName("电商项目" + i);
		
		// 创建开发人员对象
		Developer devp1 = new Developer();
		devp1.setDevpName("张三" + i);
		Developer devp2 = new Developer();
		devp2.setDevpName("李四" + i);
		Developer devp3 = new Developer();
		devp3.setDevpName("王五" + i);
		
		// 关系 【项目方来维护】
		Set<Developer> set1 = new HashSet<Developer>();
		set1.add(devp1);
		set1.add(devp2);
		
		Set<Developer> set2 = new HashSet<Developer>();
		set2.add(devp2);
		set2.add(devp3);
		
		prj1.setDevps(set1);
		prj2.setDevps(set2);
		
		// 保存
//		session.save(devp1);
//		session.save(devp2);
//		session.save(devp3);
		
		session.save(prj1);		//上面的三条语句注释掉后,如果想保存成功,必须要设置级联保存 
		session.save(prj2);
		
		session.getTransaction().commit();
		session.close();
		System.out.println("执行结束!");
	}
	
	//2 .设置inverse属性, 对获取数据影响?  无
	@Test
	public void testGet()
	{
		Session session = sf.openSession();
		session.beginTransaction();
		
		Project prj = (Project) session.get(Project.class, 3);
		System.out.println(prj.getPrjName());
		System.out.println(prj.getDevps());
		
		session.getTransaction().commit();
		session.close();
		System.out.println("执行结束!");
	}

	//3. 设置inverse属性, 对解除关系影响?
	// 有影响。
	// inverse=false ,有控制权, 解除关系就是删除中间表的数据。
	// inverse=true, 没有控制权,不能解除关系。
	@Test
	public void testClearRelation()
	{
		Session session = sf.openSession();
		session.beginTransaction();
		
		Project prj = (Project) session.get(Project.class, 3);
		prj.getDevps().clear();
		
		session.getTransaction().commit();
		session.close();
		System.out.println("执行结束!");
	}
	
	//4. 设置inverse属性,对删除数据的影响?
	// inverse=false, 有控制权。 先删除中间表数据,再删除自身。
	// inverse=true, 没有控制权。 如果删除的数据有被引用,会报错! 否则,才可以删除
	@Test
	public void testDelete()
	{
		Session session = sf.openSession();
		session.beginTransaction();
		
		Project prj = (Project) session.get(Project.class, 13);
		if(prj != null)
		{
			session.delete(prj);
		}
		
		session.getTransaction().commit();
		session.close();
		System.out.println("执行结束!");
	}
}