我在數據庫中出現了一個奇怪的雙重插入錯誤。我有以下類別:Hibernate錯誤在@PostPersist方法中持續存在實體
- TestEntity - 具有@PrePersist和@PostPersist方法的實體。
- 禮堂 - 審計實體
- 數據集 - DatasetBean的接口
- DatasetBean - 無狀態Bean上實現數據集
- DatasetFactory - 例如數據集(查找)的EJB
我把這個問題在junit測試(我正在使用嵌入式Glassfish):
@Test
public void test() throws NamingException {
Dataset<TestEntity> dataset = this.lookupBy(DatasetBean.class);
Assert.assertNotNull(dataset);
TestEntity t = new TestEntity();
t.setName(UUID.randomUUID().toString());
dataset.insert(t);
System.out.println("end");
}
測試流程如下:
剛開DataSet對象後,我嘗試插入TestEntity對象
@Stateless @EJB(name = 「...」,beanInterface = Dataset.class) 公共類DatasetBean實現數據集{
@PersistenceContext(type = PersistenceContextType.TRANSACTION) private EntityManager entityManager; @Override public void insert(T entidade) { LOG.info("Inserting: " + entidade); entityManager.persist(entidade); } //...
}
使用DatasetFactory,我嘗試在@PostPer插入一個審計實體在TestEntity的SIST方法
公共類DatasetFactory { 公共靜態數據集createDataset(){ 嘗試{ 回報率(數據集)新的InitialContext()查詢( 「...」)。 (ex){ } catch(Exception ex){ throw new RuntimeException(ex); }} }
@Entity 公共類TestEntity實現myEntity所{ @Id 私人整數ID; 私人字符串名稱; //設置和獲取
@PrePersist public void fillId() { if (getId() == null || getId() == 0) { Dataset d = DatasetFactory.createDataset(); Integer i = (Integer) d.fetchJPQLFirstResult("SELECT MAX(te.id) FROM TestEntity te"); if (i == null || i < 100) { setId(100); } else { setId(i + 1); } } } @PostPersist public void audit() { Dataset<Auditing> dataset = DatasetFactory.createDataset(); // dataset.getEntityManager().clear(); Auditing auditing = new Auditing(); auditing.setIdEntidade(String.valueOf(this.getId())); dataset.insert(auditing); }
}
@Entity 公共類禮堂實現myEntity所{ @Id @GeneratedValue(策略= GenerationType.IDENTITY) 私人整數ID; private String idEntity; //設置並獲取 }
public interface MyEntity extends Serializable {整數getId();} }
登錄:
信息:已嵌入了成功部署於47.154毫秒。 PlainTextActionReporterSUCCESSDescription:部署名爲embedded的AdminCommandApplication。
2012-01-06 02:56:54826 [主要] INFO com.joaosavio.model.db.DatasetBean(DatasetBean.java:30) - 插入:TestEntity {ID = NULL,姓名= ea5c2af4-0ca7-48a2 -a82a-dbf582c570a9}
休眠:選擇最大(testentity0_.id)從TestEntity col_0_0_ testentity0_
休眠:(?)插入TestEntity(姓名,身份證)值
2012 -01-06 02:56:56,344 [main] INFO com.joaosavio.model.db.DatasetBean(DatasetBean.java:30) - 插入:Auditoria {id = null,idEntidade = 100}
休眠:插入TestEntity(姓名,ID)值
2012-01-06 02(?,?):56:56350 [主要] WARN org.hibernate.engine.jdbc.spi。 SqlExceptionHelper(SqlExceptionHelper.java:143) - SQL錯誤:2627,SQLSTATE:23000
2012-01-06 02:56:56352 [主要] ERROR org.hibernate.engine.jdbc.spi.SqlExceptionHelper(SqlExceptionHelper.java :144) - 違反PRIMARY KEY約束'PK_ TestEntity_76818E95'。無法在對象'dbo.TestEntity'中插入重複鍵。
06/01/2012 2點56分56秒com.sun.ejb.containers.BaseContainer postInvoke
警告:在EJB DatasetBean方法public void com.joaosavio.model.db調用期間發生系統異常.DatasetBean.insert(java.lang.Object中) javax.ejb.TransactionRolledbackLocalException:異常來自豆 拋出...
造成的:javax.persistence.PersistenceException:org.hibernate.exception.ConstraintViolationException:初級違規KEY約束'PK_ TestEntity _76818E95'。無法在對象'dbo.TestEntity'中插入重複鍵。 ...
造成的:org.hibernate.exception.ConstraintViolationException:PRIMARY KEY約束違反 'PK_ TestEntity _76818E95'。無法在對象'dbo.TestEntity'中插入重複鍵。
注意事項:
依託,一切工作正常,如果我的審計實體(在TestEntity @PostPersist方法comented碼)的插入之前清除實體管理的事實,我相信TestEntity是陷入交易中。
我在做什麼錯?
+1,文檔中說「執行實體管理器持久操作後實際執行或級聯。執行數據庫INSERT後調用此調用。」並且它還說「回調方法可能會引發RuntimeException。必須回滾當前事務(如果有)。」然後在提交事務之前它必須等待回調方法完成。 – Reddy 2012-08-21 12:39:36