Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/381.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Hibernate错误将@PostPersist方法中的实体持久化_Java_Hibernate_Jpa_Entity_Lifecycle - Fatal编程技术网

Java Hibernate错误将@PostPersist方法中的实体持久化

Java Hibernate错误将@PostPersist方法中的实体持久化,java,hibernate,jpa,entity,lifecycle,Java,Hibernate,Jpa,Entity,Lifecycle,我在数据库中有一个奇怪的双重插入错误。我有以下课程: TestEntity—具有@PrePersist和@PostPersist方法的实体 审计机构-审计实体 Dataset—DatasetBean的接口 DatasetBean-实现Dataset的无状态bean DatasetFactory-实例Dataset的EJB(查找) 我将问题放在junit测试中(我使用的是嵌入式Glassfish): } 使用DatasetFactory,我尝试在TestEntity的@PostPersist方

我在数据库中有一个奇怪的双重插入错误。我有以下课程:

  • TestEntity—具有@PrePersist和@PostPersist方法的实体
  • 审计机构-审计实体
  • Dataset—DatasetBean的接口
  • DatasetBean-实现Dataset的无状态bean
  • DatasetFactory-实例Dataset的EJB(查找)
我将问题放在junit测试中(我使用的是嵌入式Glassfish):

}

  • 使用DatasetFactory,我尝试在TestEntity的@PostPersist方法中插入审计实体

    公共类数据集工厂{ 公共静态数据集createDataset(){ 试一试{ 返回(数据集)新的InitialContext().lookup(“…”); }捕获(例外情况除外){ 抛出新的运行时异常(ex); } } }

    @实体 公共类TestEntity实现MyEntity{ @身份证 私有整数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);
    }
    
    @PrePersist
    公共void fillId(){
    如果(getId()==null | | getId()==0){
    Dataset d=DatasetFactory.createDataset();
    整数i=(整数)d.fetchJPQLFirstResult(“从TestEntity te中选择MAX(te.id));
    如果(i==null | | i<100){
    setId(100);
    }否则{
    setId(i+1);
    }
    }
    }  
    @后复印机
    公共审计(){
    Dataset Dataset=DatasetFactory.createDataset();
    //dataset.getEntityManager().clear();
    审核=新审核();
    auditing.setIdEntidade(String.valueOf(this.getId());
    数据集.插入(审计);
    }
    
    }

    @实体 公共类礼堂实现MyEntity{ @身份证 @GeneratedValue(策略=GenerationType.IDENTITY) 私有整数id; 私有字符串标识; //设置和获取 }

    公共接口MyEntity扩展了可序列化{ 整数getId(); }

  • 日志:

    信息:embedded在47.154毫秒内成功部署。 PlainTextActionReporterSUCCESSDescription:部署名为embedded的AdminCommandApplication部署

    2012-01-06 02:56:54826[main]INFO com.joaosavio.model.db.DatasetBean(DatasetBean.java:30)-插入:TestEntity{id=null,name=ea5c2af4-0ca7-48a2-a82a-dbf582c570a9}

    休眠:从TestEntityTestEntity0中选择max(testentity0.id)作为列0_

    Hibernate:插入测试实体(名称、id)值(?,)

    2012-01-06 02:56:56344[main]INFO com.joaosavio.model.db.DatasetBean(DatasetBean.java:30)-插入:Auditoria{id=null,idEntidade=100}

    Hibernate:插入测试实体(名称、id)值(?,)

    2012-01-06 02:56:56350[main]WARN org.hibernate.engine.jdbc.spi.SqlExceptionHelper(SqlExceptionHelper.java:143)-SQL错误:2627,SQLState:23000

    2012-01-06 02:56:56352[main]错误org.hibernate.engine.jdbc.spi.SqlExceptionHelper(SqlExceptionHelper.java:144)-违反主键约束“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:违反主键约束“PK_TestEntity_76818E95”。无法在对象“dbo.TestEntity”中插入重复键。

    原因:org.hibernate.exception.ConstraintViolationException:违反主键约束“PK_TestEntity_76818E95”。无法在对象“dbo.TestEntity”中插入重复键

    注意事项:

    如果我在插入审计实体(TestEntity中@PostPersist方法中的代码)之前清除实体管理器,那么一切都会正常工作,我相信TestEntity正在事务中卡住


    我做错了什么?

    我曾经看到过一个非常类似的问题。。。。你应该--

    小心@PostPersist!HibernateBean持久化或保存操作与数据库插入不同

    问题可能是您假设@PostPersist方法在插入数据后被调用。。。。然而,情况并非总是如此!PostPersist方法是回调,但它们不是来自数据库的回调!!!正如您所知-hibernate可能没有提交您的事务并完全刷新它。如果您试图使用PostPersist来协调数据库事务之间的障碍,您就犯了错误。

    解决方案是在一个适当规划和管理的事务中完成所有插入,并计算出键和级联,以便hibernate能够以正确的方式为您组织插入,或者只是硬编码一个存储过程来为您完成这项工作

    我认为您可能正在这里合并有状态和无状态事务逻辑。

    +1,文档中说“在实体管理器持久化操作实际执行或级联后执行。此调用在数据库插入执行后调用。”它还说“回调方法可能引发RuntimeException。当前事务(如果有的话)必须回滚。”然后它必须在提交事务之前等待回调方法完成。
    @PersistenceContext(type = PersistenceContextType.TRANSACTION)
    private EntityManager entityManager;
    
    @Override
    public void insert(T entidade) {
        LOG.info("Inserting: " + entidade);
        entityManager.persist(entidade);
    }
    //...
    
    @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);
    }