多对多关联,都会引入第三张表
package org.leadfar.hibernate.model;
import java.util.HashSet;
import java.util.Set;
public class Person {
private int id;
private String name;
private Set<Role> roles;
Person(){}
//给人分配角色
public void addRole(Role role) {
if(roles==null) {
roles = new HashSet<Role>();
}
roles.add(role);
}
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;
}
public Set<Role> getRoles() {
return roles;
}
public void setRoles(Set<Role> roles) {
this.roles = roles;
}
}
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="org.hibernate.auction"> <class name="org.leadfar.hibernate.model.Person" table="t_persons" > <!-- id为数据库标识,作为主键 --> <id name="id"> <generator class="native"> </generator> </id> <property name="name"/> <!-- t_person_role为中间表,记录Person的id与Role的id --> <set name="roles" table="t_person_role"> <!-- key column="personId" 表示在t_person_role表中用personId字段来记录Person的id--> <key column="personId"></key> <!-- class指名对方是哪个类--由类即能确定表, colunm指定保存对方id的字段,通过column的id值就能到对应表中取出记录--> <many-to-many class="org.leadfar.hibernate.model.Role" column="roleId"></many-to-many> </set> </class> </hibernate-mapping>
package org.leadfar.hibernate.model;
import java.util.Set;
public class Role {
private int id;
private String name;
private Set<Person> persons;
Role(){}
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;
}
public Set<Person> getPersons() {
return persons;
}
public void setPersons(Set<Person> persons) {
this.persons = persons;
}
}
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="org.hibernate.auction"> <class name="org.leadfar.hibernate.model.Role" table="t_roles" > <!-- id为数据库标识,作为主键 --> <id name="id"> <generator class="native"/> </id> <property name="name"/> <!-- 表一致 都为t_person_role --> <set name="persons" table="t_person_role"> <!-- 用roleId记录本方Role --> <key column="roleId"></key> <!-- 用personId记录对方的id --> <!-- 注意:两张表的表名字段名都必须一致,才能将关系存储到一张表中! --> <many-to-many class="org.leadfar.hibernate.model.Person" column="personId"></many-to-many> </set> </class> </hibernate-mapping>
测试
package org.leadfar.hibernate.model;
import java.util.Set;
import junit.framework.TestCase;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class Many2ManyTest extends TestCase {
public void many2many_save() {
Configuration cfg = new Configuration().configure();
SessionFactory sf = cfg.buildSessionFactory();
Session session = sf.openSession();
try {
session.beginTransaction();
Person p1= new Person();
p1.setName("1abc");
session.save(p1);
Person p2= new Person();
p2.setName("2abc");
session.save(p2);
Person p3= new Person();
p3.setName("3abc");
session.save(p3);
Role r1 = new Role();
r1.setName("系统管理员");
session.save(r1);
Role r2 = new Role();
r2.setName("档案管理员");
session.save(r2);
Role r3 = new Role();
r3.setName("项目管理员");
session.save(r3);
p1.addRole(r3);
p1.addRole(r2);
p2.addRole(r1);
p3.addRole(r3);
p3.addRole(r2);
p3.addRole(r1);
session.getTransaction().commit();
} catch(Exception e) {
session.getTransaction().rollback();
e.printStackTrace();
} finally {
session.close();
}
}
public void many2many_load01() {
Configuration cfg = new Configuration().configure();
SessionFactory sf = cfg.buildSessionFactory();
Session session = sf.openSession();
try {
session.beginTransaction();
Person p = (Person)session.load(Person.class, 3);
Set<Role> role = p.getRoles();
for(Role r : role) {
System.out.println(p.getName()+","+r.getName());
}
session.getTransaction().commit();
} catch(Exception e) {
session.getTransaction().rollback();
e.printStackTrace();
} finally {
session.close();
}
}
public void many2many_load02() {
Configuration cfg = new Configuration().configure();
SessionFactory sf = cfg.buildSessionFactory();
Session session = sf.openSession();
try {
session.beginTransaction();
Role r = (Role)session.load(Role.class, 3);
Set<Person> persons = r.getPersons();
for(Person p : persons) {
System.out.println(r.getName()+","+p.getName());
}
session.getTransaction().commit();
} catch(Exception e) {
session.getTransaction().rollback();
e.printStackTrace();
} finally {
session.close();
}
}
}
====================================================================
拆分多对多--->2个一对多
多的一方(PersonRole),关联两个一的一端(Person,Role)
引入第三个类,不但可以保持关联关系,并可以在类中增加额外属性
而且避免了对集合的操作,在多的一端进行操作即可!
package org.leadfar.hibernate.model;
import java.util.Set;
public class Person {
private int id;
private String name;
private Set<PersonRole> personRoles;
Person(){}
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;
}
public Set<PersonRole> getPersonRoles() {
return personRoles;
}
public void setPersonRoles(Set<PersonRole> personRoles) {
this.personRoles = personRoles;
}
}
package org.leadfar.hibernate.model;
import java.util.Set;
public class Role {
private int id;
private String name;
private Set<PersonRole> rolePersons;
Role(){}
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;
}
public Set<PersonRole> getRolePersons() {
return rolePersons;
}
public void setRolePersons(Set<PersonRole> rolePersons) {
this.rolePersons = rolePersons;
}
}
package org.leadfar.hibernate.model;
import java.util.Date;
public class PersonRole {
/**
* PersonRole作为多的一方,持有Person和Role的引用
*
*/
private int id;
private Person person;
private Role role;
private Date createTime;
PersonRole(){}
public PersonRole(Person person,Role role) {
this.person = person;
this.role = role;
this.createTime = new Date();
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
public Role getRole() {
return role;
}
public void setRole(Role role) {
this.role = role;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
}
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="org.hibernate.auction"> <class name="org.leadfar.hibernate.model.Person" table="t_persons" > <!-- id为数据库标识,作为主键 --> <id name="id"> <generator class="native"> </generator> </id> <property name="name"/> <set name="personRoles" lazy="extra" inverse="true"> <key column="personId"></key> <one-to-many class="org.leadfar.hibernate.model.PersonRole"></one-to-many> </set> </class> </hibernate-mapping>
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="org.hibernate.auction"> <class name="org.leadfar.hibernate.model.Role" table="t_roles" > <!-- id为数据库标识,作为主键 --> <id name="id"> <generator class="native"/> </id> <property name="name"/> <set name="rolePersons" lazy="extra" inverse="true"> <key column="roleId"></key> <one-to-many class="org.leadfar.hibernate.model.PersonRole"></one-to-many> </set> </class> </hibernate-mapping>
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="org.hibernate.auction"> <class name="org.leadfar.hibernate.model.PersonRole" table="t_person_role" > <!-- id为数据库标识,作为主键 --> <id name="id"> <generator class="native"/> </id> <many-to-one name="person" column="personId"></many-to-one> <many-to-one name="role" column="roleId"></many-to-one> <property name="createTime" type="timestamp"></property> </class> </hibernate-mapping>
测试
package org.leadfar.hibernate.model;
import java.util.Set;
import junit.framework.TestCase;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class Many2ManyTest extends TestCase {
public void many2many_save() {
Configuration cfg = new Configuration().configure();
SessionFactory sf = cfg.buildSessionFactory();
Session session = sf.openSession();
try {
session.beginTransaction();
Person p1= new Person();
p1.setName("1abc");
session.save(p1);
Person p2= new Person();
p2.setName("2abc");
session.save(p2);
Person p3= new Person();
p3.setName("3abc");
session.save(p3);
Role r1 = new Role();
r1.setName("系统管理员");
session.save(r1);
Role r2 = new Role();
r2.setName("档案管理员");
session.save(r2);
Role r3 = new Role();
r3.setName("项目管理员");
session.save(r3);
//从多的一端维护关联关系
session.save(new PersonRole(p1,r1));
session.save(new PersonRole(p2,r2));
session.save(new PersonRole(p3,r1));
session.save(new PersonRole(p3,r2));
session.save(new PersonRole(p3,r3));
session.getTransaction().commit();
} catch(Exception e) {
session.getTransaction().rollback();
e.printStackTrace();
} finally {
session.close();
}
}
public void many2many_load01() {
Configuration cfg = new Configuration().configure();
SessionFactory sf = cfg.buildSessionFactory();
Session session = sf.openSession();
try {
session.beginTransaction();
Person p = (Person)session.load(Person.class, 3);
Set<PersonRole> prs = p.getPersonRoles();
for(PersonRole pr : prs) {
System.out.println(p.getName()+","+pr.getRole().getName());
}
session.getTransaction().commit();
} catch(Exception e) {
session.getTransaction().rollback();
e.printStackTrace();
} finally {
session.close();
}
}
public void many2many_load02() {
Configuration cfg = new Configuration().configure();
SessionFactory sf = cfg.buildSessionFactory();
Session session = sf.openSession();
try {
session.beginTransaction();
Role r = (Role)session.load(Role.class, 3);
Set<PersonRole> prs = r.getRolePersons();
for(PersonRole pr : prs) {
System.out.println(r.getName()+","+pr.getPerson().getName());
}
session.getTransaction().commit();
} catch(Exception e) {
session.getTransaction().rollback();
e.printStackTrace();
} finally {
session.close();
}
}
}
=================================================================
分析对象之间的关系:
1个用户拥有多个组,1个组只属于1个用户;
1个用户可以属于多个组(1个学生只属于1个班级),1个组可以包含多个用户;