带有Eclipselink交易问题的弹簧靴



我已经在eclipselink中实现了EntityListener。我的应用是使用Spring-Boot,Spring-Data和Eclipselink构建的。当数据插入1个表中时,我需要将记录插入2个表(审核表)。我的听众中有EntityManager,一切似乎正常起作用。当我调试代码时,我可以看到要保存的实体是从DB级别维护的序列中生成的" ID"。但是,当交易订立时,我只会看到主表数据,但是审核表数据并未提交。这是示例代码:

@Entity
@Table(name="MyTable")
@EntityListeners(MyTableListener.class)
public class MyTable implements Serializable{
    private static final long serialVersionUID = -5087505622449571373L;
    private Long id;
    // Rest of the fields
    @Id
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="MASTER_SEQ")
    @SequenceGenerator(name="MASTER_SEQ",sequenceName="MASTER_SEQ",allocationSize=1)
    public Long getId() {
        return id;
    }
    // Getters/Setters
}

听众代码:

 public class MyTableListener extends DescriptorEventAdapter {
        @Override
        public void postInsert(DescriptorEvent event) {
            MyTable msg = (MyTable)((InsertObjectQuery) event.getQuery()).getObject();
            EntityManager em = BeanUtil.getBean(EntityManager.class);
            MyAudit statusAudit = new MyAudit();
            statusAudit.setNewVal("NEW");
            statusAudit.setOldval(null);
            statusAudit.setTargetColumnName(targetColumn);
            statusAudit.setTargetRecordId(msg.getId());
            em.persist(statusAudit);
        }
    }

代码似乎没有错。但是,当我在集合中看到SQL日志"最好"时,我可以看到插入查询没有被触发以供审计表触发。我已经处理了这个问题已有2天以上的时间,并且不了解到底出了什么问题。请帮助我。

您从不在EntityManager上调用flush。我怀疑以下事情正在进行:

  1. 您可能通过春季存储库将您的域实体添加到EntityManager。

  2. 某些东西触发了潮流,可能是弹簧的交易处理。

  3. 您的域实体被冲洗了。

  4. 您的事件侦听器被触发。

  5. 您将审计实体添加到EntityManager,但这些实体永远不会被冲洗。

  6. 数据库连接获取提交。保存除了您的审核之路以外的所有内容。

如果此理论正确,您应该能够通过日志和调试器验证,您可以通过在侦听器中添加flush的呼叫来修复它。

正如您在评论中所描述的那样,这会导致进一步的问题,这是因为您正在尝试做不应该做的事情。

根据本文,JPA规格不允许在回调事件中使用EntityManager。

通常,便携式应用程序的生命周期方法不应调用EntityManager或查询操作,访问其他实体实例,或在相同的持久性上下文中修改关系。生命周期回调方法可以修改调用其所在实体的非关系状态。

看起来,就像我们被困在这里一样,因此您可能应该考虑一种完全不同的方法,例如Eclipselink历史表。

最新更新