Cascade - распространенная ошибка аннотации JPA и Hibernate

Каскад - JPA & Hibernate аннотация распространенная ошибка

Часто разработчики смешивают использование аннотаций JPA и Hibernate вместе, это может привести к очень распространенной ошибке - аннотации каскадного типа JPA не работают в Hibernate?

В разделе обзора кода я обнаружил, что многие Java-разработчики не знают об этой ошибке и из-за того, что программе не удалось выполнить каскадную операцию для связанных объектов. Я возьму этотone-to-many hibernate example для демонстрации.

ошибка

В примере «один ко многим» многие разработчики объявили следующие параметры каскада JPA:

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

Сохраните его с помощью Hibernate.

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

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

Код, который пытается сделать, это когда вы сохраняете «сток», он также сохраняет и связанный с ним stockDailyRecords. Все выглядит нормально, ноTHIS IS NOT WORKING, параметры каскада не будут выполняться и сохранять stockDailyRecords. Вы можете заметить ошибку?

объяснение

Посмотрите код,@OneToMany из JPA, он ожидал каскад JPA -javax.persistence.CascadeType. Однако, когда вы сохраните его в сеансе Hibernate,org.hibernate.engine.Cascade выполнит следующую проверку ...

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

Процесс сохранения гибернации вызовет действиеACTION_SAVE_UPDATE, но JPA передастACTION_PERSIST иACTION_MERGE, это не будет соответствовать и приведет к сбою выполнения каскада.

@ смотри исходный код

  • org.hibernate.engine.Cascade

  • org.hibernate.engine.CascadeStyle

  • org.hibernate.engine.CascadingAction

Решение

Удалите каскад JPA -javax.persistence.CascadeType, замените его каскадом Hibernate -org.hibernate.annotations.Cascade, наCascadeType.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;
    }
    ...

Теперь это работает так, как вы ожидали.

Заключение

Это похоже на несовместимую проблему между JPA и каскадной аннотацией Hibernate, если Hibernate является реализацией JPA, что может вызвать неправильное понимание между ними?

Related