实体未在EclipseLink EntityListener

时间:2017-02-17 11:06:02

标签: spring jpa transactions eclipselink audit-logging

我使用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);
        }
    }
}

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

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

1 个答案:

答案 0 :(得分: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;
}