【问题标题】:Entity not getting saved in EclipseLink EntityListener实体未保存在 EclipseLink EntityListener 中
【发布时间】:2017-07-06 21:16:23
【问题描述】:

我已经使用 eclipseLink 的“DescriptorEventAdapter”编写了 EntityListener。我尝试了几乎所有在线版本的变体,但我从听众那里保存的实体没有得到保存。我怀疑交易发生了一些可疑的事情,但没有找到根本原因。这是代码:

package com.db;

import java.util.Date;
import javax.annotation.PostConstruct;
import javax.persistence.EntityManagerFactory;
import javax.transaction.Transactional;
import javax.transaction.Transactional.TxType;

import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.descriptors.DescriptorEvent;
import org.eclipse.persistence.descriptors.DescriptorEventAdapter;
import org.eclipse.persistence.jpa.JpaEntityManager;
import org.eclipse.persistence.queries.InsertObjectQuery;
import org.eclipse.persistence.queries.UpdateObjectQuery;
import org.eclipse.persistence.sessions.changesets.DirectToFieldChangeRecord;
import org.eclipse.persistence.sessions.changesets.ObjectChangeSet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class NotificationMessageListener extends DescriptorEventAdapter {

    public static Logger logger = LoggerFactory.getLogger(NotificationMessageListener.class);

    private static final String targetColumn  = "STATUS";

    //private static AuditRepository auditRepo;

    @Autowired 
    private StatusAuditRepository statusAuditRepo;

    @Autowired
    private RuleResultAuditRepository ruleResultRepo;

    @Autowired
    private EntityManagerFactory factory;

    JpaEntityManager entityManager = null;

    @PostConstruct
    public void init() {

        try {
            entityManager = (JpaEntityManager) factory.createEntityManager();
            // Use the entity manager to get a ClassDescriptor for the Entity class
            ClassDescriptor desc = 
                entityManager.getSession().getClassDescriptor(NotificationMessage.class);
            // Add this class as a listener to the class descriptor
            desc.getEventManager().addListener(this);
        } finally {
            if (entityManager != null) {
                // Cleanup the entity manager
                entityManager.close();
            }
        }
    }

    /*@Autowired
    public void setAuditRepo(AuditRepository auditRepo) {
        NotificationMessageListener.auditRepo = auditRepo;
    }*/

    @Transactional(value = TxType.REQUIRES_NEW)
    @Override
    public void postInsert(DescriptorEvent event) {
        logger.info("post insert is called ");
        //NotificationMessage notificationMsg = (NotificationMessage) ((InsertObjectQuery) event.getQuery()).getObject();
        //entityManager.getTransaction().begin();
        NotificationStatusAudit statusAudit = new NotificationStatusAudit();
        statusAudit.setInsertionTime(new Date());
        //statusAudit.setNewVal(notificationMsg.getStatus());
        statusAudit.setNewVal("abc");
        statusAudit.setOldval("asdf");
        statusAudit.setTargetColumnName("from listner");
        //statusAudit.setTargetRecordId(notificationMsg.getId());
        statusAudit.setTargetRecordId(123L);
        statusAudit = statusAuditRepo.save(statusAudit);
        //entityManager.getTransaction().commit();
        //logger.info("Number of records "+statusAuditRepo.count());
        //auditRuleResult(notificationMsg.getMessageCorrelationId() , true);
    }

    @Override
    public void postUpdate(DescriptorEvent event) {
            ObjectChangeSet objectChanges = ((UpdateObjectQuery) event.getQuery()).getObjectChangeSet();
            DirectToFieldChangeRecord statusChanges = (DirectToFieldChangeRecord) objectChanges
                    .getChangesForAttributeNamed("status");
            if (statusChanges != null && !statusChanges.getNewValue().equals(statusChanges.getOldValue())) {
                NotificationStatusAudit statusAudit = new NotificationStatusAudit();
                statusAudit.setInsertionTime(new Date());
                statusAudit.setNewVal("abc");
                statusAudit.setOldval("asdf");
                statusAudit.setTargetColumnName(targetColumn);
                statusAudit.setTargetRecordId((Long) objectChanges.getId());
                statusAudit = statusAuditRepo.save(statusAudit);
        }
    }
}

当数据被插入到一个表中时,我所要做的就是将记录保存在另一个(审计)表中。我的应用程序是 spring boot 应用程序,并且正在使用 eclipseLink 进行持久化。我必须在“PostConstruct”中手动注册我的实体侦听器,因为如果它是使用 @EntityListner 注释注册的,spring-data-repos 不会自动装配。这是我的问题:

1) 根据我的要求使用 EntityListener 是一种好方法,还是应该使用直接“保存”操作? 2)我调试了EntityListener代码,即使添加了Requires_new,方法也没有启动新的事务。我可以看到方法没有被称为 $proxy (spring-proxy)。我不明白为什么?

【问题讨论】:

    标签: spring jpa transactions eclipselink audit-logging


    【解决方案1】:

    我不确定您在 @PostConstruct init() 方法中做了什么……但我怀疑您应该使用 EclipseLink 的 DescriptorCustomizer 配置此 DescriptorEventAdapter。这是一个例子:

    public class MessageEventListener extends DescriptorEventAdapter implements DescriptorCustomizer {
    
        @Override
        public void customize(ClassDescriptor descriptor) {
            descriptor.getEventManager().addListener(this);
        }
    
        @Override
        public void postUpdate(DescriptorEvent event) {
            ObjectChangeSet objectChanges = ((UpdateObjectQuery) event.getQuery()).getObjectChangeSet();
            //More business logic...
        }
    }
    
    @Entity
    @Customizer(MessageEventListener.class)
    public class Message {
        @Id private long id;
        private String content;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-30
      • 2014-02-06
      • 1970-01-01
      • 2023-03-20
      • 2018-10-25
      • 1970-01-01
      相关资源
      最近更新 更多