在第一篇中写了多表映射之多对多的常规配置,即关联表中只有以其它表主键做外键的字段。第一篇链接
这一篇是讲述多对多映射时,关联表如何配置非主键字段。依然以Employee与Role为例
与常规配置相比需要多编写一个实体类,例EmployeeAndRole.java,该实体类应包含Employee类和Role类对象,并提供getter、setter方法。如下:
public class EmployeeAndRole implements Serializable {
private static final long serialVersionUID = 1L;
private Employee employee;
private Role role;
public Employee getEmployee() {
return employee;
}
public void setEmployee(Employee employee) {
this.employee = employee;
}
public Role getRole() {
return role;
}
public void setRole(Role role) {
this.role = role;
}
}
编写此实体类之后,原来的Employee.java、Role.java也需要做相应修改,如下:
//Employee.java
public class Employee implements Serializable {
private static final long serialVersionUID = 1L;
private Integer id;
private String name;
private Integer age;
// 注意!!!
// 集合应该为EmployeeAndRole实体类的集合
private Set<EmployeeAndRole> employeeAndRoles = new HashSet<>();
public Employee(Integer id, String name, Integer age) {
super();
this.id = id;
this.name = name;
this.age= age;
}
public Employee() {
super();
}
public Set<EmployeeAndRole> getEmployeeAndRoles() {
return employeeAndRoles;
}
public void setEmployeeAndRoles(Set<EmployeeAndRole> employeeAndRoles) {
this.employeeAndRoles = employeeAndRoles;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
//Role.java
public class Role implements Serializable {
private static final long serialVersionUID = 1L;
private Integer id;
private String name;
// 注意!!!
// 集合应该为EmployeeAndRole实体类的集合
private Set<EmployeeAndRole> employeeAndRoles = new HashSet<>();
public Role(Integer id, String name) {
super();
this.id = id;
this.name = name;
}
public Role() {
super();
}
public Set<EmployeeAndRole> getEmployeeAndRoles() {
return employeeAndRoles;
}
public void setEmployeeAndRoles(Set<EmployeeAndRole> employeeAndRoles) {
this.employeeAndRoles = employeeAndRoles;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
映射配置文件同时也需要进行修改,这里会用到<composite-element>等标签,拭目以待。
<!-- Employee.hbm.xml -->
<hibernate-mapping package="com.aha.hibernate.entity">
<class name="Employee" table="employee">
<id name="id" column="ID">
<generator class="native"></generator>
</id>
<property name="name" column="NAME"></property>
<property name="age" column="AGE"></property>
<!-- 此处set的name属性值应为EmployeeAndRole的集合 -->
<set name="employeeAndRoles" table="role_user_table">
<!-- 当前实体类在关联表做外键的主键名 -->
<key column="employee_id"></key>
<!-- 使用组件标签,class属性值为组件类名 -->
<composite-element class="EmployeeAndRole">
<!-- 当前实体类在组件类中对应的对象名 -->
<parent name="employee"/>
<!-- 另一端在组件类中对应的对象名、另一端完整类名、另一端在组件类中做外键的主键名 -->
<many-to-one name="role" class="Role" column="role_id"></many-to-one>
<!-- 此处就是配置主键外其它字段的配置。name属性为字段所属的实体类对应的对象,class属性为字段所属的实体类完整类名 -->
<nested-composite-element name="employee" class="Employee">
<!-- 字段属性 -->
<property name="name" column="NAME"></property>
</nested-composite-element>
<!-- nested-composite-element标签可以并行写多个 -->
</composite-element>
</set>
</class>
</hibernate-mapping>
<!-- Role.hbm.xml -->
<hibernate-mapping package="com.aha.hibernate.entity">
<class name="Role" table="role">
<id name="id" column="ID">
<generator class="native"></generator>
</id>
<property name="name" column="NAME"></property>
<set name="employeeAndRoles" table="role_user_table" inverse="true">
<key column="role_id"></key>
<composite-element class="EmployeeAndRole">
<parent name="role"/>
<many-to-one name="employee" class="Employee" column="user_id"></many-to-one>
</composite-element>
</set>
</class>
</hibernate-mapping>
解释已在代码注释中标注,另外补充:添加字段时只在维护映射关系的一端添加配置即可,放弃维护的一端不需要配置。