HibernateException:实例的标识符已从 Alert@62794582 更改为 Alert@c82ad22
HibernateException: identifier of an instance was altered from Alert@62794582 to Alert@c82ad22
我正在使用 Hibernate JPA 实现持久性 API。
我正在使用 PostgreSQL 10.4 并将数据存储为 JSONB。
我正在分享我对 Hibernate 和 Entity 的实现,请指出为什么我会遇到异常。
我关注这篇精彩的文章来实现自定义 UserType,因为 Hibernate 不支持 PostgreSQL JSONB 数据类型:
https://www.thoughts-on-java.org/persist-postgresqls-jsonb-data-type-hibernate/
我能够创建实体映射并执行简单的 Select 查询并打印分配给映射的值。
问题是当我对事务执行提交操作时,出现以下异常:
22:42:35.218 [main] DEBUG
org.hibernate.engine.transaction.internal.TransactionImpl - rollback()
called on an inactive transaction Exception in thread "main"
javax.persistence.RollbackException: Error while committing the
transaction at
org.hibernate.jpa.internal.TransactionImpl.commit(TransactionImpl.java:86)
at com.postgres.main.TestMain.main(TestMain.java:41) Caused by:
javax.persistence.PersistenceException:
org.hibernate.HibernateException: identifier of an instance of
com.postgres.model.Alert was altered from
com.postgres.model.Alert@62794582 to com.postgres.model.Alert@c82ad22
at
org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1692)
at
org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1602)
at
org.hibernate.jpa.internal.TransactionImpl.commit(TransactionImpl.java:67)
... 1 more Caused by: org.hibernate.HibernateException: identifier of
an instance of com.postgres.model.Alert was altered from
com.postgres.model.Alert@62794582 to com.postgres.model.Alert@c82ad22
at
org.hibernate.event.internal.DefaultFlushEntityEventListener.checkId(DefaultFlushEntityEventListener.java:64)
at
org.hibernate.event.internal.DefaultFlushEntityEventListener.getValues(DefaultFlushEntityEventListener.java:175)
at
org.hibernate.event.internal.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:135)
at
org.hibernate.event.internal.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:216)
at
org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:85)
at
org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:38)
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1295)
at
org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:468)
at
org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:3135)
at
org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2352)
at
org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:485)
at
org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:147)
at
org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access0(JdbcResourceLocalTransactionCoordinatorImpl.java:38)
at
org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:231)
at
org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:65)
at
org.hibernate.jpa.internal.TransactionImpl.commit(TransactionImpl.java:61)
... 1 more
我也关注了 post 那里的人们分享了他们如何解决这个问题,但这对我没有帮助:
Hibernate: How to fix "identifier of an instance altered from X to Y"?
这是警报实体:
@Entity
@IdClass(Alert.class)
@Table(name = "alert")
public class Alert implements Serializable
{
private static final long serialVersionUID = 1L;
@Id
@Column(name = "historyid")
private Character historyId;
@Id
@Column(name = "tenantname")
private Character tenantName;
@Column(name = "data")
@Type(type = "AlertJsonUserType")
private AlertJson alertJson;
public Character getHistoryId() {
return historyId;
}
public void setHistoryId(Character historyId) {
this.historyId = historyId;
}
public Character getTenantName() {
return tenantName;
}
public void setTenantName(Character tenantName) {
this.tenantName = tenantName;
}
public AlertJson getAlertJson() {
return alertJson;
}
public void setAlertJson(AlertJson alertJson) {
this.alertJson = alertJson;
}
}
这是警报实体中 JSONB 元素的实体
public class AlertJson implements Serializable
{
private static final long serialVersionUID = 1L;
@JsonProperty("DeviceId")
private String deviceId;
@JsonProperty("TenantName")
private String tenantName;
@JsonProperty("FocusPointId")
private List<FocusPointId> focusPointId;
public String getDeviceId() {
return deviceId;
}
public void setDeviceId(String deviceId) {
this.deviceId = deviceId;
}
public String getTenantName() {
return tenantName;
}
public void setTenantName(String tenantName) {
this.tenantName = tenantName;
}
public List<FocusPointId> getFocusPointId() {
return focusPointId;
}
public void setFocusPointId(List<FocusPointId> focusPointId) {
this.focusPointId = focusPointId;
}
}
class FocusPointId
{
@JsonProperty("PartNumber")
private String partNumber;
@JsonProperty("SerialNumber")
private String serialNumber;
public String getPartNumber() {
return partNumber;
}
public void setPartNumber(String partNumber) {
this.partNumber = partNumber;
}
public String getSerialNumber() {
return serialNumber;
}
public void setSerialNumber(String serialNumber) {
this.serialNumber = serialNumber;
}
}
下面是 main() 的片段,我在其中创建 EntityManager 实例并发出查询
public static void main(String[] args)
{
EntityManagerFactory emf = Persistence.createEntityManagerFactory("my-persistence-unit");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
Query alertQuery = em.createNativeQuery("SELECT * FROM \"A.01\".\"Alert\" where tenantname = 'TestUser-152'", Alert.class);
List<Alert> alertList = alertQuery.getResultList();
for(Alert jsonElement : alertList)
{
System.out.println("======> "+"Device: " + jsonElement.getAlertJson().getDeviceId() + " TenantName: " +jsonElement.getAlertJson().getTenantName());
}
em.getTransaction().commit();
emf.close();
}
下面是描述 table 和约束。
PK既是historyid又是tenantname。
我认为你有这个问题是因为你错误地使用了 IdClass
注释,你应该创建一个单独的 class AlertId
例如,它必须包含来自你的组合 PK 的字段,并且此 class 应用作 IdClass
注释
的参数
我正在使用 Hibernate JPA 实现持久性 API。
我正在使用 PostgreSQL 10.4 并将数据存储为 JSONB。
我正在分享我对 Hibernate 和 Entity 的实现,请指出为什么我会遇到异常。
我关注这篇精彩的文章来实现自定义 UserType,因为 Hibernate 不支持 PostgreSQL JSONB 数据类型:
https://www.thoughts-on-java.org/persist-postgresqls-jsonb-data-type-hibernate/
我能够创建实体映射并执行简单的 Select 查询并打印分配给映射的值。
问题是当我对事务执行提交操作时,出现以下异常:
22:42:35.218 [main] DEBUG org.hibernate.engine.transaction.internal.TransactionImpl - rollback() called on an inactive transaction Exception in thread "main" javax.persistence.RollbackException: Error while committing the transaction at org.hibernate.jpa.internal.TransactionImpl.commit(TransactionImpl.java:86) at com.postgres.main.TestMain.main(TestMain.java:41) Caused by: javax.persistence.PersistenceException: org.hibernate.HibernateException: identifier of an instance of com.postgres.model.Alert was altered from com.postgres.model.Alert@62794582 to com.postgres.model.Alert@c82ad22 at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1692) at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1602) at org.hibernate.jpa.internal.TransactionImpl.commit(TransactionImpl.java:67) ... 1 more Caused by: org.hibernate.HibernateException: identifier of an instance of com.postgres.model.Alert was altered from com.postgres.model.Alert@62794582 to com.postgres.model.Alert@c82ad22 at org.hibernate.event.internal.DefaultFlushEntityEventListener.checkId(DefaultFlushEntityEventListener.java:64) at org.hibernate.event.internal.DefaultFlushEntityEventListener.getValues(DefaultFlushEntityEventListener.java:175) at org.hibernate.event.internal.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:135) at org.hibernate.event.internal.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:216) at org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:85) at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:38) at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1295) at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:468) at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:3135) at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2352) at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:485) at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:147) at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access0(JdbcResourceLocalTransactionCoordinatorImpl.java:38) at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:231) at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:65) at org.hibernate.jpa.internal.TransactionImpl.commit(TransactionImpl.java:61) ... 1 more
我也关注了 post 那里的人们分享了他们如何解决这个问题,但这对我没有帮助:
Hibernate: How to fix "identifier of an instance altered from X to Y"?
这是警报实体:
@Entity
@IdClass(Alert.class)
@Table(name = "alert")
public class Alert implements Serializable
{
private static final long serialVersionUID = 1L;
@Id
@Column(name = "historyid")
private Character historyId;
@Id
@Column(name = "tenantname")
private Character tenantName;
@Column(name = "data")
@Type(type = "AlertJsonUserType")
private AlertJson alertJson;
public Character getHistoryId() {
return historyId;
}
public void setHistoryId(Character historyId) {
this.historyId = historyId;
}
public Character getTenantName() {
return tenantName;
}
public void setTenantName(Character tenantName) {
this.tenantName = tenantName;
}
public AlertJson getAlertJson() {
return alertJson;
}
public void setAlertJson(AlertJson alertJson) {
this.alertJson = alertJson;
}
}
这是警报实体中 JSONB 元素的实体
public class AlertJson implements Serializable
{
private static final long serialVersionUID = 1L;
@JsonProperty("DeviceId")
private String deviceId;
@JsonProperty("TenantName")
private String tenantName;
@JsonProperty("FocusPointId")
private List<FocusPointId> focusPointId;
public String getDeviceId() {
return deviceId;
}
public void setDeviceId(String deviceId) {
this.deviceId = deviceId;
}
public String getTenantName() {
return tenantName;
}
public void setTenantName(String tenantName) {
this.tenantName = tenantName;
}
public List<FocusPointId> getFocusPointId() {
return focusPointId;
}
public void setFocusPointId(List<FocusPointId> focusPointId) {
this.focusPointId = focusPointId;
}
}
class FocusPointId
{
@JsonProperty("PartNumber")
private String partNumber;
@JsonProperty("SerialNumber")
private String serialNumber;
public String getPartNumber() {
return partNumber;
}
public void setPartNumber(String partNumber) {
this.partNumber = partNumber;
}
public String getSerialNumber() {
return serialNumber;
}
public void setSerialNumber(String serialNumber) {
this.serialNumber = serialNumber;
}
}
下面是 main() 的片段,我在其中创建 EntityManager 实例并发出查询
public static void main(String[] args)
{
EntityManagerFactory emf = Persistence.createEntityManagerFactory("my-persistence-unit");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
Query alertQuery = em.createNativeQuery("SELECT * FROM \"A.01\".\"Alert\" where tenantname = 'TestUser-152'", Alert.class);
List<Alert> alertList = alertQuery.getResultList();
for(Alert jsonElement : alertList)
{
System.out.println("======> "+"Device: " + jsonElement.getAlertJson().getDeviceId() + " TenantName: " +jsonElement.getAlertJson().getTenantName());
}
em.getTransaction().commit();
emf.close();
}
下面是描述 table 和约束。 PK既是historyid又是tenantname。
我认为你有这个问题是因为你错误地使用了 IdClass
注释,你应该创建一个单独的 class AlertId
例如,它必须包含来自你的组合 PK 的字段,并且此 class 应用作 IdClass
注释