0

하나의 컬렉션을 포함하는 Envers에 의해 감사되는 엔티티가 주어집니다.최대 절전 모드 Enver : @AuditJoinTable 행 누락

엔티티 A

@Audited 
    public class A{ 
    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    private int id; 
    .... 
    @OneToMany 
    @JoinColumn(name = "a_id") 
    @AuditJoinTable(name = "A_B_AUDIT" 
      ,inverseJoinColumns = @JoinColumn(name = "a")) 
    private List<B> bs; 
    .... 
} 

엔티티 B 그들의 documentation Envers으로 당

@Audited 
public class B{ 
@Id 
private int id; 
.... 
@Column(name = "a_id") 
private int aId; 

@ManyToOne 
@JoinColumn(name = "a_id", insertable = false, updatable = false) 
private A a; 
} 

이 AuditJoinTables (A_B_AUDIT)에 추가 및 삭제에 대한 감사 정보를 저장한다. 하지만 불행히도이 작업이 작동하지 않고 테이블 안의 행이 누락되었습니다.

내가 작성되는 테이블 다음 내 프로젝트를 실행하는 경우 :

A_AUDIT

B_AUDIT

A_B_AUDIT을

I는 객체와 B 오브젝트를 지속 할 수있는 별도의 컨트롤러를했습니다. A와 B를 함께 저장하려고하면 audit_table (A_B_AUDIT)이 업데이트되지 않지만 B_AUDIT이 업데이트 된 개정판이 업데이트됩니다.

누군가 내가 여기에없는 것을 알려주십시오.

감사합니다.

최대 절전 모드 Enver 버전 : 5.1.4.Final

+0

master와 5.1.4를 모두 테스트 했으므로 문제를 재현 할 수 없으므로 관계의 양쪽에 값을 설정하는 방법과 관련하여 매우 구체적이어야합니다. 엔티티를 생성하고 유지하기 전에 엔티티를 연결할 위치에 코드를 포함시킬 수 있습니까? – Naros

+0

안녕하세요 @Naros, 둘 다 컨트롤러를 분리했습니다. 그리고 매핑 (Hibernate)을 기반으로 연관을 고르고 있습니다. –

+0

'B'와'A'를 별도의 트랜잭션으로 지속하는 것처럼 들리지만, 이들 사이에 생성하는 유일한 연관은 식별자가 'A'인 'B # aId'로 설정됩니다. 이것이 사실이고'A'에서 명시 적으로'B'를 목록에 추가하지 않으면 join 테이블에 값을 넣지 않게됩니다. 이것은 지속성이 작동하는 방법이 아닙니다. 필요한 모든 속성을 함께 유지해야하는지 확인해야합니다. 그렇지 않으면 부분 상태로 끝나게되고 Envers는 감사 내역을 올바르게 채우지 않습니다. 이것이 실제 작업이 아니라면 다시 실제 코드를 게시해야합니다. – Naros

답변

1

으로는 설명했다 , 당신의 문제는 별도의 거래에서이 두 기관의 지속성을 수행하고 있지만 적절한을하지 않는 것입니다 그래서 당신은 Hibernate의 첫 번째 레벨 캐시의 상태를 오염시키고있다. 부주의로 Envers가 모든 적절한 상태를 제공하지 않아 엔티티를 제대로 감사 할 수 없게됩니다.

는 Envers 작업이 사용 사례 위해서는, 당신은 당신이 엔티티 A과의 관계에 대한 것 같다 유일한 것은 알고입니다 주어진 당신의 엔티티 B의 지속성을 처리하는 방식을 수정해야합니다. 엔티티 B의 지속성 동안

, 당신은 가능성이 작업을 수행해야합니다

이 엔티티 B의 지속성 동안 의미
if (b.getAId() != null) { 
    A a = entityManager.find(A.class, b.getAId()); 
    a.getBs().add(b); 
    a = entityManager.merge(a); 

    b.setA(a); 
    entityManager.persist(b); 
} 

, 당신이 감사에서 추가 감사 행을 받아야 예상처럼 테이블에 가입하고 상태는 Hibernate 첫 번째 레벨 캐시에서 두 엔티티 간의 모든 적절한 참조를 포함합니다.

우리가 정상 JPA 제공자의 사용에 잠시 초점 따로 Envers을 두는 경우에, 당신은 당신이 B를 유지 한 후이 작업을 수행 할 수 있어야하고 작동합니다 :

final A theA = b.getA(); 
assertNotNull(theA); 
assertTrue(!theA.getBs().isEmpty()); 
assertTrue(theA.getBs().contains(b)); 

을 분명히 당신이 설정되지 않은 경우 협회, 이러한 주장 (모두 통과해야 함)은 그렇지 않습니다.그들이 통과 할 수있는 유일한 시간은 다시 쿼리 엔터티 B이지만 반드시 필요한 것은 아닙니다.

잘하면 이해합니다.