反面(部门):
public class Department implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "department_id", nullable = false)
private Long departmentId;
@Column(name = "department_name", length = 255)
private String departmentName;
@OneToMany(mappedBy = "department", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
private List<Employee> employeeList = new ArrayList<Employee>(0);
private static final long serialVersionUID = 1L;
public Department() {}
public void add(Employee employee) {
List<Employee> newEmployeeList = getEmployeeList();
if (!newEmployeeList.contains(employee)) {
newEmployeeList.add(employee);
}
if (employee.getDepartment() != this) {
employee.setDepartment(this);
}
}
public void remove(Employee employee) {
List<Employee> newEmployeeList = getEmployeeList();
if (newEmployeeList.contains(employee)) {
newEmployeeList.remove(employee);
}
employee.setDepartment(null);
}
// Remaining getters + setters + hashcode() + equals() + toString().
}
拥有方(员工):
public class Employee implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "employee_id", nullable = false)
private Long employeeId;
@Column(name = "employee_name", length = 255)
private String employeeName;
@JoinColumn(name = "department_id", referencedColumnName = "department_id")
@ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH, CascadeType.DETACH})
private Department department;
private static final long serialVersionUID = 1L;
public void setDepartment(Department department) {
this.department = department;
if (department != null) {
List<Employee> employeeList = department.getEmployeeList();
if (!employeeList.contains(this)) {
employeeList.add(this);
}
}
}
// Remaining getters + setters + hashcode() + equals() + toString().
}
可以看出,setDepartment()
实体中的setter方法Employee
被赋予了应用程序代码简洁的额外责任 - 用于执行链接管理任务。它将Department
添加到反面的员工列表中。
相反,还有两种关系管理方法,即add()
和remove()
。如果为setter分配了这种链接管理任务,那么就不必明确记住将实体添加到关系的另一端。否则,必须记住在必要时在add()
中明确调用Department
方法。
►将此任务分配给setter方法是否会产生一些副作用,尤其是当访问类型设置为property(@Access(AccessType.PROPERTY)
)时?
当访问类型设置为属性时,the JPA WikiBook导致懒惰的初始化关系始终无意中初始化,这与此有点相似。
持久性可能会导致奇怪的行为。 可能导致奇怪行为的一个常见问题是使用属性访问 并在你的get或set方法中加入副作用。为此原因 通常建议在映射中使用字段访问,即 将注释放在变量上而不是get方法。
例如考虑:
public void setPhones(List<Phone> phones) { for (Phone phone : phones) { phone.setOwner(this); } this.phones = phones; }
这可能看起来很无辜,但这些副作用可能会出乎意料 后果。例如,如果这种关系是懒惰的,那就可以了 从中设置时始终实例化集合的效果 数据库。它也可能对某些JPA产生影响 导致持久化,合并和其他操作的实现 重复插入,错过更新或损坏的对象模型。
我还看到了不正确的属性方法,例如get方法 总是返回一个新对象,或一个副本,或设置不返回的方法 实际设定值。
一般情况下,如果您打算使用房产 访问,确保您的财产方法没有副作用。也许 甚至使用不同于应用程序使用的属性方法。