通常,开发人员将JPA和Hibernate批注混用在一起,会引起一个非常普遍的错误-JPA级联类型批注在Hibernate中不起作用?
在代码审查部分中,我发现许多Java开发人员都不知道此错误,并导致程序无法对相关实体执行级联操作。 我将以这个一对多的休眠示例进行演示。
错误
在一对多示例中,许多开发人员声明了JPA级联选项,如下所示:
...
@Entity
@Table(name = "stock", catalog = "mkyong", uniqueConstraints = {
@UniqueConstraint(columnNames = "STOCK_NAME"),
@UniqueConstraint(columnNames = "STOCK_CODE") })
public class Stock implements java.io.Serializable {
...
private Set<StockDailyRecord> stockDailyRecords =
new HashSet<StockDailyRecord>(0);
@OneToMany(fetch = FetchType.LAZY,
cascade = {CascadeType.PERSIST,CascadeType.MERGE },
mappedBy = "stock")
public Set<StockDailyRecord> getStockDailyRecords() {
return this.stockDailyRecords;
}
public void setStockDailyRecords(Set<StockDailyRecord> stockDailyRecords) {
this.stockDailyRecords = stockDailyRecords;
}
...
使用Hibernate会话保存它。
stockDailyRecords.setStock(stock);
stock.getStockDailyRecords().add(stockDailyRecords);
session.save(stock);
session.getTransaction().commit();
该代码尝试执行的操作是在保存“库存”时,还将保存关联的stockDailyRecords。 一切看起来都很好,但是这不起作用,级联选项将不会执行并保存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
);
}
Hibernate保存过程将导致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 = "mkyong", uniqueConstraints = {
@UniqueConstraint(columnNames = "STOCK_NAME"),
@UniqueConstraint(columnNames = "STOCK_CODE") })
public class Stock implements java.io.Serializable {
...
private Set<StockDailyRecord> stockDailyRecords =
new HashSet<StockDailyRecord>(0);
@OneToMany(fetch = FetchType.LAZY, mappedBy = "stock")
@Cascade({CascadeType.SAVE_UPDATE})
public Set<StockDailyRecord> getStockDailyRecords() {
return this.stockDailyRecords;
}
public void setStockDailyRecords(Set<StockDailyRecord> stockDailyRecords) {
this.stockDailyRecords = stockDailyRecords;
}
...
现在,它可以按预期工作。
结论
看起来JPA和Hibernate级联批注之间存在不兼容的问题,如果Hibernate是JPA实现,则可能是什么原因导致两者之间的误解?
翻译自: https://mkyong.com/hibernate/cascade-jpa-hibernate-annotation-common-mistake/