更新嵌套的 OneToMany 休眠实体
Update nested OneToMany hibernate entity
我实现了两个实体。一个 RuleEntity 和一个 RestCallEntity,如下所示:
RuleEntity
@Entity(name = "RuleEntity")
@Table(name = "Rule")
public class RuleEntity {
@Id
@Column(name = ID_COLUMN_NAME, nullable = false)
@GeneratedValue(strategy = AUTO)
private Long id;
@Column(name = "name", nullable = false)
public String name = "";
@OneToMany(targetEntity = RestCallEntity.class, fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true)
public final Set<RestCallEntity> restCalls = new HashSet<>();
}
RestCallEntity
@Entity(name = "RestCallEntity")
@Table(name = "RestCall")
public class RestCallEntity
@Id
@Column(name = ID_COLUMN_NAME, nullable = false)
@GeneratedValue(strategy = AUTO)
private Long id;
@Column(name = "name", nullable = false)
public String name = "";
}
我在 json 端点收到一条规则。然后我将收到的 json 规则转换为 RuleEntity 并调用
getEntityManager().merge(ruleEntity);
当我只更改规则名称时,更新工作正常。但是当我更改它的名称时,它看起来像 hibernate 试图创建一个新的 restcall,即使它已经有一个 ID。我得到以下异常。
Caused by: org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint ?rule_restcall_pkey?
Detail: key ?(ruleentity_id, restcalls_id)=(45, 49)? already exists.
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2675)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2365)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:355)
at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:490)
at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:408)
at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:166)
at org.postgresql.jdbc.PgPreparedStatement.executeUpdate(PgPreparedStatement.java:134)
at io.agroal.pool.wrapper.PreparedStatementWrapper.executeUpdate(PreparedStatementWrapper.java:88)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:197)
... 99 more
所以我终于想通了,可能是equals/hashcode方法的实现导致的。我将 equals 方法更改为仅检查 id,将 hashcode 方法更改为仅 return id 的哈希码。现在更新工作正常。
我实现了两个实体。一个 RuleEntity 和一个 RestCallEntity,如下所示:
RuleEntity
@Entity(name = "RuleEntity")
@Table(name = "Rule")
public class RuleEntity {
@Id
@Column(name = ID_COLUMN_NAME, nullable = false)
@GeneratedValue(strategy = AUTO)
private Long id;
@Column(name = "name", nullable = false)
public String name = "";
@OneToMany(targetEntity = RestCallEntity.class, fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true)
public final Set<RestCallEntity> restCalls = new HashSet<>();
}
RestCallEntity
@Entity(name = "RestCallEntity")
@Table(name = "RestCall")
public class RestCallEntity
@Id
@Column(name = ID_COLUMN_NAME, nullable = false)
@GeneratedValue(strategy = AUTO)
private Long id;
@Column(name = "name", nullable = false)
public String name = "";
}
我在 json 端点收到一条规则。然后我将收到的 json 规则转换为 RuleEntity 并调用
getEntityManager().merge(ruleEntity);
当我只更改规则名称时,更新工作正常。但是当我更改它的名称时,它看起来像 hibernate 试图创建一个新的 restcall,即使它已经有一个 ID。我得到以下异常。
Caused by: org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint ?rule_restcall_pkey? Detail: key ?(ruleentity_id, restcalls_id)=(45, 49)? already exists. at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2675) at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2365) at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:355) at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:490) at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:408) at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:166) at org.postgresql.jdbc.PgPreparedStatement.executeUpdate(PgPreparedStatement.java:134) at io.agroal.pool.wrapper.PreparedStatementWrapper.executeUpdate(PreparedStatementWrapper.java:88) at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:197) ... 99 more
所以我终于想通了,可能是equals/hashcode方法的实现导致的。我将 equals 方法更改为仅检查 id,将 hashcode 方法更改为仅 return id 的哈希码。现在更新工作正常。