joa*_*vio 3 java lifecycle entity hibernate jpa
我在DB中有双重插入的奇怪错误.我有以下课程:
我把问题放在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");
}
Run Code Online (Sandbox Code Playgroud)
测试流程如下:
在获取数据集对象后,我尝试插入TestEntity对象
@Stateless @EJB(name ="...",beanInterface = Dataset.class)公共类DatasetBean实现Dataset {
@PersistenceContext(type = PersistenceContextType.TRANSACTION)
private EntityManager entityManager;
@Override
public void insert(T entidade) {
LOG.info("Inserting: " + entidade);
entityManager.persist(entidade);
}
//...
Run Code Online (Sandbox Code Playgroud)
}
使用DatasetFactory,我尝试在TestEntity的@PostPersist方法中插入审计实体
公共类DatasetFactory {公共静态数据集createDataset(){尝试{回报率(数据集)新的InitialContext()查询( "...").} catch(Exception ex){throw new RuntimeException(ex); }}}
@Entity公共类TestEntity实现MyEntity {@Id private Integer 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);
}
Run Code Online (Sandbox Code Playgroud)
}
@Entity公共类Auditoria实现MyEntity {@Id @GeneratedValue(strategy = GenerationType.IDENTITY)私有整数id; private String idEntity; //设置并获取}
public interface MyEntity扩展Serializable {Integer getId(); }
日志:
信息:嵌入式已成功部署47.154毫秒.PlainTextActionReporterSUCCESSDescription:部署名为embedded的AdminCommandApplication.
2012-01-06 02:56:5426 [main] INFO com.joaosavio.model.db.DatasetBean(DatasetBean.java:30) - 插入:TestEntity {id = null,name = ea5c2af4-0ca7-48a2-a82a-dbf582c570a9 }
Hibernate:从TestEntity testentity0_选择max(testentity0_.id)为col_0_0_
Hibernate:插入TestEntity(name,id)值(?,?)
2012-01-06 02:56:55,844 [main] INFO com.joaosavio.model.db.DatasetBean(DatasetBean.java:30) - 插入:Auditoria {id = null,idEntidade = 100}
Hibernate:插入TestEntity(name,id)值(?,?)
2012-01-06 02:56:55,850 [main] WARN org.hibernate.engine.jdbc.spi.SqlExceptionHelper(SqlExceptionHelper.java:143) - SQL错误:2627,SQLState:23000
2012-01-06 02:56:55,852 [main] ERROR org.hibernate.engine.jdbc.spi.SqlExceptionHelper(SqlExceptionHelper.java:144) - 违反PRIMARY KEY约束'PK_ TestEntity _76818E95'.无法在对象'dbo.TestEntity'中插入重复键.
06/01/2012 02:56:56 com.sun.ejb.containers.BaseContainer postInvoke
警告:在EJB DatasetBean方法调用期间发生系统异常public void com.joaosavio.model.db.DatasetBean.insert(java.lang.Object)javax.ejb.TransactionRolledbackLocalException:从bean抛出的异常...
引起:javax.persistence.PersistenceException:org.hibernate.exception.ConstraintViolationException:违反PRIMARY KEY约束'PK_ TestEntity _76818E95'.无法在对象'dbo.TestEntity'中插入重复键....
引起:org.hibernate.exception.ConstraintViolationException:违反PRIMARY KEY约束'PK_ TestEntity _76818E95'.无法在对象'dbo.TestEntity'中插入重复键.
注意事项:
如果我在插入审核实体(TestEntity中的@PostPersist方法中的代码)之前清除实体管理器,依赖于一切正常的事实,我相信TestEntity会陷入事务中.
我究竟做错了什么???
jay*_*100 10
我曾经看过一个非常类似的问题....你应该---
@PostPersist要非常小心!hibernate bean持久化或保存动作与数据库插入不同!
问题很可能是你假设在插入数据后调用@PostPersist方法....但是,情况并非总是如此!PostPersist方法是回调,但它们不是来自数据库的回调!如您所知 - hibernate可能没有提交您的事务并完全刷新它.如果您尝试使用PostPersist来协调数据库事务之间的障碍,那么您就犯了一个错误.
解决方案是在一个正确规划和管理的事务中完成所有插入操作,并使用密钥和级联设置,以便hibernate能够以正确的方式为您组织插入 - 或者只是硬编码存储过程来执行为你工作.
我想你可能在这里合并有状态和无状态的事务逻辑.
归档时间: |
|
查看次数: |
2789 次 |
最近记录: |