2016-06-14 4 views
3

RESTful 웹 앱입니다. 나는 Hibernate Envers를 사용하여 히스토리 데이터를 저장하고있다. 개정 번호 및 타임 스탬프와 함께 다른 세부 정보 (예 : IP 주소 및 인증 된 사용자)도 저장해야합니다. Envers은 여러 가지 방법으로 멋진 수정 기능을 제공합니다. 수정 엔터티에 사용자 지정 데이터를 설정하는 데 문제가 있습니다.() 메서드를 추가 인수를 허용하지 않습니다 newRevision 때문에 Hibernate Envers에서 Custom RevisionEntity에 추가 데이터를 전달하는 방법은 무엇입니까?

@RevisionEntity(MyCustomRevisionListener.class) 
public class MyCustomRevisionEntity extends DefaultRevisionEntity { 
    private String userName; 

    private String ip; 

    //Accessors 
} 

public class MyCustomRevisionListener implements RevisionListener { 
    public void newRevision(Object revisionEntity) { 
     MyCustomRevisionEntity customRevisionEntity = (MyCustomRevisionEntity) revisionEntity; 
     //Here I need userName and Ip address passed as arguments somehow, so that I can set them on the revision entity. 
    } 
} 

, 나는 그것 (사용자 이름 및 IP 등) 내 사용자 정의 데이터를 전달할 수 없습니다. 어떻게해야합니까?

대신 getCurrentRevision 호출되는 org.hibernate.envers.RevisionListener를 사용하는 또 다른 방법 (클래스 revisionEntityClass를 부울 지속)을 org.hibernate의 방법

는 Envers은 또한 또 다른 방법을 제공한다. envers.AuditReader 인터페이스는 현재 개정판을 가져 와서 원하는 정보로 채 웁니다.

public void persist(SomeEntity entity) { 
    ... 
    entityManager.persist(entity); 
    ... 
} 

public void persist(SomeEntity entity, String userName, String ip) { 
    ... 
    //Do the intended work 
    entityManager.persist(entity); 
    //Do the additional work 
    AuditReader reader = AuditReaderFactory.get(entityManager) 
    MyCustomRevisionEntity revision = reader.getCurrentRevision(MyCustomRevisionEntity, false); 
    revision.setUserName(userName); 
    revision.setIp(ip); 

} 

I 돈

에 :

같이 내 현재 DAO 방법을 변경

:

그래서 위의 방법을 사용하여, 나는 이런 식으로 뭔가를해야 할 것이다 감사 데이터를 유지하는 것이 나에게 커다란 우려가되는 것 같아서이 접근 방식에 매우 만족스럽지 않습니다. 그리고 HTTP 요청 객체를 통해 userName과 Ip 및 다른 데이터를 얻습니다. 따라서 모든 데이터는 응용 프로그램 (컨트롤러)의 시작 지점에서 가장 낮은 레이어 (DAO 레이어)로 바로 내려와야합니다.

내가이 목표를 달성 할 수있는 다른 방법이 있습니까? 나는 봄을 사용하고있다.

특정 메소드 호출이 속한 '스택'에 대한 정보를 유지하는 스프링과 같은 것을 상상하고 있습니다. 그래서 newRevision()이 호출 될 때 엔트리 포인트에서 어떤 특정 호출이이 호출로 연결되는지 알 수 있습니다. 또한, 어떻게 든 호출 스택의 첫 번째 메서드에 전달 된 인수를 얻을 수 있습니다.

답변

5

이것을 수행하는 좋은 방법은 ThreadLocal 변수를 이용하는 것입니다. 예를 들어

는 봄 보안 SecurityContextHolder에 저장된 스레드 로컬 변수를 초기화하는 필터를 가지고 있으며, 당신은 단순히 같은 수행하여 특정 스레드에서이 데이터에 액세스 할 수 있도록 추가 상상

SecurityContext ctx = SecurityContextHolder.getSecurityContext(); 
Authorization authorization = ctx.getAuthorization(); 

을 인터셉터는 스프링 보안을 사용하는 경우 사용자 정의 사용자 세부 정보 객체에 스프링 보안 컨텍스트에 추가 정보를 추가하거나 리스너가 필요로하는 정보를 보유하기 위해 자신의 홀더 & 컨텍스트 객체를 만드는 웹 프레임 워크 호출을 호출합니다.

public class MyRevisionEntityListener implements RevisionListener { 
    @Override 
    public void newRevision(Object revisionEntity) { 
    // If you use spring security, you could use SpringSecurityContextHolder. 
    final UserContext userContext = UserContextHolder.getUserContext(); 
    MyRevisionEntity mre = MyRevisionEntity.class.cast(revisionEntity); 
    mre.setIpAddress(userContext.getIpAddress()); 
    mre.setUserName(userContext.getUserName()); 
    } 
} 

이 나에게 가장 깨끗한 방법 같은 느낌 :

는 그 다음 간단한된다.

다른 API getCurrentRevision(Session,boolean)은 Hibernate 5.2에서 더 이상 사용되지 않으며 6.0에서 제거 될 예정입니다. 다른 방법을 도입 할 수도 있지만이 유형의 논리를 수행하는 의도 된 방법은 RevisionListener을 사용하는 것입니다.

+0

감사합니다. 구현하고 업데이트를 게시 해 보겠습니다. –

+0

@AnmolGupta 안녕하세요, 이것에 대한 업데이트가 있습니까? –

+0

ThreadLocal은 이러한 상황을 처리하는 좋은 방법입니다. 즉, 일반적으로 사용합니다. –