Hibernate 在更新时两次添加 OneToMany 实体

Hibernate adding OneToMany Entity twice when updating

我在更新实体时遇到问题。下面是我标注的模型:(注意:还有很多字段我觉得和问题无关)

员工

@Entity
public class Employee {
   @Id
   @GeneratedValue(strategy = GenerationType.AUTO)
   private int id;

   @OneToMany(cascade = CascadeType.ALL, mappedBy = "employee", fetch = FetchType.EAGER)
   private List<Paycheck> paychecks;

   // Note: this method does not ever seem to be called
   @Override
   public boolean equals(Object o) {
       System.out.printf("\n\n\nEquals requested!\n\n\n");

       if (o == null || !(o instanceof Employee)) {
           System.out.printf("\n\n\nNot equal! 1\n\n\n");
           return false;
       }

       Employee other = (Employee) o;

       if (id == other.getId()) {
          System.out.printf("\n\n\nEqual! id = id\n\n\n");
          return true;
       }

       // equivalence by id
       return id == other.getId();
   }

   @Override
   public int hashCode() {
       final int prime = 31;
       int result = 1;
       result = prime * result + (id ^ (id >>> 32));
       return result;
   }
}

薪水

@Entity
public class Paycheck {
   @Id
   @GeneratedValue(strategy = GenerationType.AUTO)
   private int id;


   @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
   private Employee employee;
}

我的 DAO 更新方法:

@Override
public void update(T item) {
    Session session = sessionFactory.getCurrentSession();

    session.beginTransaction();
    session.saveOrUpdate(item);
    session.getTransaction().commit();
}

以及服务方式:

 public List<Paycheck> executePayroll(List<Employee> employees) {
    List<Paycheck> paychecks = new ArrayList<>();

    for(Employee employee : employees) {
        Paycheck paycheck = engine.processPay(employee, employee.getCurrentHours());
        paycheck.setEmployeeId(employee.getId());
        paycheck.setEmployee(employee);
        paycheck.setDate(today);
        paychecks.add(paycheck);
        employee.setCurrentHours(0);

        employee.getPaychecks().add(paycheck);

        employeeRepository.update(employee);
    }

    return paychecks;
}

我得到的行为:

当薪水为0时,添加薪水时,员工不会重复。我得到以下记录:

Hibernate: call next value for hibernate_sequence

Hibernate: insert into Paycheck (date, employee_id, employeeId, employerFederalUnemploymentTax, employerMedicareTax, employerSocialSecurityTax, employerStateUnemploymentTax, federalWithholdingTax, grossAmount, medicareWithholdingTax, netAmount, socialSecurityWithholdingTax, stateWithholdingTax, id) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)

Hibernate: update Employee set address=?, city=?, currentHours=?, dateOfBirth=?, email=?, federalExemptions=?, firstName=?, isMarried=?, lastName=?, payRate=?, phoneNumber=?, socialSecurityNumber=?, state=?, stateExemptions=?, zipcode=? where id=?

但是,当我向员工添加第二份薪水时,员工实体重复了。我最终在数据库中找到了两名具有所有相同属性的员工,包括 'id'。此外,两名员工都有相同的两份薪水。在方法 运行:

之后记录以下内容
Hibernate: call next value for hibernate_sequence

Hibernate: insert into Paycheck (date, employee_id, employeeId, employerFederalUnemploymentTax, employerMedicareTax, employerSocialSecurityTax, employerStateUnemploymentTax, federalWithholdingTax, grossAmount, medicareWithholdingTax, netAmount, socialSecurityWithholdingTax, stateWithholdingTax, id) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)

Hibernate: update Employee set address=?, city=?, currentHours=?, dateOfBirth=?, email=?, federalExemptions=?, firstName=?, isMarried=?, lastName=?, payRate=?, phoneNumber=?, socialSecurityNumber=?, state=?, stateExemptions=?, zipcode=? where id=?

Hibernate: update Paycheck set date=?, employee_id=?, employeeId=?, employerFederalUnemploymentTax=?, employerMedicareTax=?, employerSocialSecurityTax=?, employerStateUnemploymentTax=?, federalWithholdingTax=?, grossAmount=?, medicareWithholdingTax=?, netAmount=?, socialSecurityWithholdingTax=?, stateWithholdingTax=? where id=?

这是N+1 problem的症状。我通过在我的 List 实体上使用 @Fetch(FetchMode.SUBSELECT) 注释解决了这个问题。或者,您可以改用 Set,尽管这有其他副作用。