基本需求是:一个项目可以有多个开发人员,一个开发人员可以参加多个项目,因此项目和开发人员是多对多的关系。本文中的学习重点,还和前几篇文章一样,都是JavaBean类的映射文件中的配置。
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("执行结束!"); } }
序号 | 操作类型 | 是否影响 | 具体说明 |
---|---|---|---|
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("执行结束!"); } }