2016-04-10 12 views
0

Ich habe Probleme beim Aktualisieren einer Entität. Hier sind meine kommentierten Modelle: (Anmerkung: es gibt viele weitere Felder, die ich denke, sind irrelevant für das Problem)Hibernate Hinzufügen von OneToMany Entity zweimal beim Aktualisieren

Mitarbeiter

@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; 
    } 
} 

Paycheck

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


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

Mein DAO Update-Methode:

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

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

Und der Service-Methode:

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; 
} 

Die bahavior Ich erhalte:

Wenn es 0 paychecks sind, und ein Gehalt hinzugefügt wird, wird der Mitarbeiter nicht dupliziert. Ich erhalte die protokollierte folgende:

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=? 

Allerdings, wenn ich ein zweites Gehalt an einen Mitarbeiter hinzufügen, wird der Mitarbeiter Einheit dupliziert. Ich lande mit zwei Mitarbeitern in der Datenbank mit den gleichen Eigenschaften, einschließlich 'ID'. Außerdem haben beide Mitarbeiter dieselben zwei Gehaltsschecks. In der folgenden protokolliert wird, nachdem die Methoden ausgeführt werden:

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=? 
+0

Das liegt daran, dass Hibernate die andere Entität in ihrem Speicher behält und wenn Sie 'update' aufrufen, wird der Ruhezustand alle Entitäten im Speicher löschen, wodurch sie auch die andere Entity aktualisiert. –

Antwort

1

Dies ist ein Symptom der N+1 problem. Ich habe dieses Problem unter Verwendung der @Fetch(FetchMode.SUBSELECT) Annotation auf meinen List Entitäten bearbeitet. Alternativ können Sie stattdessen eine Set verwenden, obwohl das andere Nebenwirkungen hat.

+1

Das hat es behoben! Ich habe keine so einfache Lösung erwartet. Vielen Dank. – Safari137