使用setter方法作为JPA

时间:2015-07-27 04:27:08

标签: hibernate jpa orm eclipselink jpa-2.1

反面(部门):

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方法   总是返回一个新对象,或一个副本,或设置不返回的方法   实际设定值。

     

一般情况下,如果您打算使用房产   访问,确保您的财产方法没有副作用。也许   甚至使用不同于应用程序使用的属性方法。

0 个答案:

没有答案