Cascade - JPA

Cascade - JPA & Hibernate Annotation häufiger Fehler

Häufig werden Entwickler die JPA- und Hibernate-Annotation gemischt verwenden. Dies führt zu einem sehr häufigen Fehler. Funktioniert die JPA-Kaskaden-Annotation im Hibernate-Modus nicht?

Während der Codeüberprüfung stelle ich fest, dass viele Java-Entwickler diesen Fehler nicht kennen und das Programm die Kaskadenoperation für die zugehörigen Entitäten nicht ausführen konnte. Ich werde dieseone-to-many hibernate example für die Demonstration nehmen.

Fehler

Im Eins-zu-Viele-Beispiel haben viele Entwickler die JPA-Kaskadenoptionen wie folgt deklariert:

...
@Entity
@Table(name = "stock", catalog = "example", uniqueConstraints = {
        @UniqueConstraint(columnNames = "STOCK_NAME"),
        @UniqueConstraint(columnNames = "STOCK_CODE") })
public class Stock implements java.io.Serializable {
    ...
    private Set stockDailyRecords =
                                              new HashSet(0);

    @OneToMany(fetch = FetchType.LAZY,
       cascade = {CascadeType.PERSIST,CascadeType.MERGE },
       mappedBy = "stock")
    public Set getStockDailyRecords() {
    return this.stockDailyRecords;
    }

    public void setStockDailyRecords(Set stockDailyRecords) {
    this.stockDailyRecords = stockDailyRecords;
    }
    ...

Speichern Sie es mit Ruhezustand.

        stockDailyRecords.setStock(stock);
        stock.getStockDailyRecords().add(stockDailyRecords);

        session.save(stock);
        session.getTransaction().commit();

Der Code, der versucht zu tun, ist, wenn Sie eine "Aktie" speichern, speichert er auch die zugehörigen stockDailyRecords. Alles sieht gut aus, aberTHIS IS NOT WORKING, die Kaskadenoptionen werden nicht ausgeführt und speichern die stockDailyRecords. Kannst du den Fehler erkennen?

Erläuterung

Schauen Sie in den Code,@OneToMany ist von JPA, es wurde eine JPA-Kaskade erwartet -javax.persistence.CascadeType. Wenn Sie es jedoch mit einer Sitzung im Ruhezustand speichern, führtorg.hibernate.engine.Cascade die folgenden Überprüfungen durch:

    if ( style.doCascade( action ) ) {
        cascadeProperty(
              persister.getPropertyValue( parent, i, entityMode ),
          types[i],
                  style,
              anything,
              false
        );
    }

Der Speichervorgang im Ruhezustand führt zu einer Aktion vonACTION_SAVE_UPDATE, aber der JPA übergibtACTION_PERSIST undACTION_MERGE. Er stimmt nicht überein und führt dazu, dass die Kaskade nicht ausgeführt werden kann.

@Siehe Quellcode

  • org.hibernate.engine.Cascade

  • org.hibernate.engine.CascadeStyle

  • org.hibernate.engine.CascadingAction

Lösung

Löschen Sie die JPA-Kaskade -javax.persistence.CascadeType und ersetzen Sie sie durch die Hibernate-Kaskade -org.hibernate.annotations.Cascade durchCascadeType.SAVE_UPDATE.

...
@Entity
@Table(name = "stock", catalog = "example", uniqueConstraints = {
        @UniqueConstraint(columnNames = "STOCK_NAME"),
        @UniqueConstraint(columnNames = "STOCK_CODE") })
public class Stock implements java.io.Serializable {
    ...
    private Set stockDailyRecords =
                                              new HashSet(0);

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "stock")
    @Cascade({CascadeType.SAVE_UPDATE})
    public Set getStockDailyRecords() {
    return this.stockDailyRecords;
    }

    public void setStockDailyRecords(Set stockDailyRecords) {
    this.stockDailyRecords = stockDailyRecords;
    }
    ...

Jetzt funktioniert es so, wie Sie es erwartet haben.

Fazit

Es sieht aus wie ein inkompatibles Problem zwischen JPA- und Hibernate-Kaskadenanmerkung. Wenn Hibernate eine JPA-Implementierung ist, was kann das Missverständnis dazwischen verursachen?