gpt4 book ai didi

hibernate 故障 : INSERT instead of UPDATE when using Inheritance:SINGLE_TABLE and SecondaryTables

转载 作者:行者123 更新时间:2023-12-02 03:50:12 27 4
gpt4 key购买 nike

我已经使用 SINGLE_TABLE with SecondaryTables 实现了继承层次结构.

这可以正常工作,但是当我的辅助表的字段为空(= Oracle 中的 null)时,对实体的下一次更新失败,因为 Hibernate 认为它应该在应该更新时插入到表中。例子:

CREATE TABLE TASK 
(
ID NUMBER(10) NOT NULL
, TYPE NUMBER(1) NOT NULL
, STATUS NUMBER(1) NOT NULL
, CONSTRAINT TASK_PK PRIMARY KEY (ID) ENABLE);

CREATE TABLE SUB_TASK
(
ID NUMBER(10) NOT NULL
, TEXT VARCHAR2(4000 CHAR)
, CONSTRAINT SUB_TASK_PK PRIMARY KEY
(ID) ENABLE);

ALTER TABLE SUB_TASK
ADD CONSTRAINT SUB_TASK_FK1 FOREIGN KEY
(ID)REFERENCES TASK(ID)ENABLE;

任务.java:
@Entity
@Table(name="TASK")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="TYPE",discriminatorType=DiscriminatorType.INTEGER)
public abstract class Task implements Serializable, Comparable<Task> {

@Id
@Column(nullable = false)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "TASK_GEN")
@SequenceGenerator(name = "TASK_GEN", sequenceName = "SEQ_TASK", allocationSize = 1)
private Long id;

@Column(name = "TYPE", nullable = false, insertable=false, updatable=false)
private int typeCode;

子任务.java
@Entity
@DiscriminatorValue("7")
@SecondaryTable(name = "SUB_TASK", pkJoinColumns = {@PrimaryKeyJoinColumn(name = "id", referencedColumnName = "id")})
public class SubTask extends Task implements Serializable {

@Column(name="TEXT", length = 4000, table="SUB_TASK")
@Size(max = 4000)
private String text;

public String getText() {
return text;
}

public void setText(String text) {
this.text = text;
}

}

保存以前为空 SubTask.text 的实体时出现异常:

引起:org.hibernate.exception.ConstraintViolationException: ORA-00001: yksikäsitteistä rajoitetta (SUB_TASK_PK) loukattu
at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:128)
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:49)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:125)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:110)
at org.hibernate.engine.jdbc.internal.proxy.AbstractStatementProxyHandler.continueInvocation(AbstractStatementProxyHandler.java:129)
at org.hibernate.engine.jdbc.internal.proxy.AbstractProxyHandler.invoke(AbstractProxyHandler.java:81)
at $Proxy75.executeUpdate(Unknown Source)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2965)
at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:3028)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3350)
at org.hibernate.action.internal.EntityUpdateAction.execute(EntityUpdateAction.java:140)

我调试了相关的 Hibernate 代码,AbstractEntityPersister.java:
    if ( !isInverseTable( j ) ) {

final boolean isRowToUpdate;
if ( isNullableTable( j ) && oldFields != null && isAllNull( oldFields, j ) ) {
//don't bother trying to update, we know there is no row there yet
isRowToUpdate = false;
}
else if ( isNullableTable( j ) && isAllNull( fields, j ) ) {
//if all fields are null, we might need to delete existing row
isRowToUpdate = true;
delete( id, oldVersion, j, object, getSQLDeleteStrings()[j], session, null );
}
else {
//there is probably a row there, so try to update
//if no rows were updated, we will find out
isRowToUpdate = update( id, fields, oldFields, rowId, includeProperty, j, oldVersion, object, sql, session );
}

if ( !isRowToUpdate && !isAllNull( fields, j ) ) {
// assume that the row was not there since it previously had only null
// values, so do an INSERT instead
//TODO: does not respect dynamic-insert
insert( id, fields, getPropertyInsertability(), j, getSQLInsertStrings()[j], object, session );
}

}

看起来第一个 if(“不要打扰尝试更新”)已经完成并且 isRowToUpdate = false,最后一个 if(if (!isRowToUpdate && !isAllNull(fields, j))也完成了,所以插入被执行。

我想我可以通过向表 SUB_TASK 添加一个虚拟的非空字段来解决这个问题,但这是我唯一的选择吗?

使用 Hibernate 4.17.final

编辑:希望清楚我在做什么:
SubTask s = taskRepository.findOne(42l);
s.setText("dasdsa");
taskRepository.save(s); // OK
s.setText(null);
taskRepository.save(s); // OK
s.setText("update after null value");
taskRepository.save(s); // exception

我使用 Spring Data 进行持久化,但看起来问题与它无关(并且我假设在使用 vanilla JPA 时会发生同样的事情)

最佳答案

我有一个有点类似的问题,一个 @ManyToOne在辅助表中定义的关系。当辅助表有一行引用主表中的实体,关系列为空并尝试设置值时,Hibernate 尝试插入新行而不是更新现有行,从而引发约束冲突异常。

解决方案是使用注释 @org.hibernate.annotations.Table(appliesTo="secondary_table", optional=false) ,这使 Hibernate 更新行。

我不确定辅助表中的行不存在时的行为,但也许它可以解决您的问题。

关于 hibernate 故障 : INSERT instead of UPDATE when using Inheritance:SINGLE_TABLE and SecondaryTables,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14683592/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com