2017-02-17 46 views
0

Я написал EntityListener, используя «DescriptorEventAdapter» eclipseLink. Я попробовал почти все варианты, которые присутствуют в сети, но сущность, которую я сохраняю от своего слушателя, не сохраняется. Я подозреваю, что что-то подозрительное происходит с транзакцией, но не получило первопричины. Вот код:Объект не сохраняется в EclipseLink 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); 
     } 
    } 
} 

Здесь все, что нужно сделать, это сохранить запись в другой таблице (ревизии), когда данные будут вставлены в одну таблицу. Мое приложение - весеннее загрузочное приложение, и я использую eclipseLink для постоянного. Я должен был вручную зарегистрировать свой сущ.-Слушатель в «PostConstruct», потому что, если он зарегистрирован с помощью аннотации @EntityListner, Spring-data-repos не получают автообучения. Вот мои вопросы:

1) Использование EntityListener для моего требования - хороший подход или я должен использовать прямые операции «сохранения»? 2) Я отлаживал код EntityListener, и метод не инициировал новую транзакцию даже после добавления Requires_new. Я вижу, что метод не называется $ proxy (spring-proxy). Я не понимаю, почему?

ответ

0

Я не уверен, что вы делаете в своем методе init() @PostConstruct ... но я подозреваю, что вы должны настроить этот дескрипторEventAdapter с помощью DescriptorCustomizer EclipseLink. Вот пример:

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; 
}