2017-02-17 13 views
0

eclipseLink의 "DescriptorEventAdapter"를 사용하여 EntityListener를 작성했습니다. 현재 온라인 상태에서도 거의 모든 유사 콘텐츠를 시도했지만 청취자가 저장 한 개체는 저장되지 않습니다. 나는 비린내가 거래로 진행되고 있지만 근본 원인을 찾지 못했던 것으로 의심합니다. 여기엔티티가 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를 사용하고 있습니다. @EntityListner annotation을 사용하여 등록 된 경우 spring-data-repos가 autowired되지 않기 때문에 수동으로 Entity-Listener를 "PostConstruct"에 등록해야했습니다. 내 질문은 다음과 같습니다

1) 내 요구 사항에 대한 EntityListener 사용은 좋은 접근 방식입니까? 직접 "저장"작업을 사용해야합니까? 2) Requires_new를 추가 한 후에도 EntityListener 코드를 디버깅하고 메소드가 새 트랜잭션을 시작하지 않았습니다. 메서드가 $ proxy (spring-proxy)로 호출되지 않는 것을 볼 수 있습니다. 왜 그런지 모르겠다 고요?

답변

0

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