2017-09-27 1 views
0

작동하지 나는 간단한 엔티티 객체와 역사 정책은 EclipseLink 역사 정책은 MySQL의 생성 된 ID의

@Entity 
@Customizer(MyHistoryPolicy.class) 
@Table(name = "employee") 
public class Employee { 
    @Id 
    @Column(name = "id") 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    private Long id; 

    @Column(name = "name") 
    private String name; 

    ... accessor methods 
} 


public class MyHistoryPolicy implements DescriptorCustomizer { 

    public void customize(ClassDescriptor descriptor) { 
     String historyTableName = descriptor.getTableName() + "_history"; 
     HistoryPolicy policy = new HistoryPolicy(); 
     policy.addHistoryTableName(historyTableName); 
     policy.addStartFieldName("start_date"); 
     policy.addEndFieldName("end_date"); 
     descriptor.setHistoryPolicy(policy); 
    } 
} 

새로운 객체가 잘 작동 삽입이있다. 객체를 업데이트하면 id가 0으로 설정됩니다. 난은 EclipseLink에서

UPDATE employee SET name = ? WHERE (id = ?) 
    bind => [test name, 2] 
UPDATE employee_history SET end_date = ? WHERE ((end_date IS NULL) AND (id = ?)) 
    bind => [2017-09-27 17:45:25.316, 2] 
INSERT INTO employee_history (id, name, start_date) VALUES (?, ?, ?) 
    bind => [2, test name, 2017-09-27 17:45:25.316] 
SELECT LAST_INSERT_ID() 

참고 "LAST_INSERT_ID()를 선택"후 기록 테이블 삽입을 다음 디버그 로그를 참조하십시오. 히스토리 테이블에는 생성 된 ID가 없으므로이 쿼리는 0을 반환하며이 값은 객체의 id 필드로 덮어 쓰여집니다. 응용 프로그램에 문제가있는 원본 ID가 유실되었습니다.

MySQL을 사용하여 Eclipselink에서이 부족분을 극복하는 방법을 아는 사람이 있습니까?

+0

[EclipseLink의 알려진 버그] (https://bugs.eclipse.org/bugs/show_bug.cgi?id=323023)입니다. 2010 년에보고되었습니다! 7 년 동안, 나는이 고정 된 [Buckley 's and Nunn] (https://en.wikipedia.org/wiki/Buckley_%26_Nunn)을 얻을 수있는 기회가 2 번 있다고 생각합니다. – bludginozzie

답변

0

누군가가이 질문에 비틀 거린 경우를 대비해 저에게 효과가있는 해결 방법을 개발했습니다. JPA 리스너를 사용하여 손실 된 ID를 저장하고 복원한다는 점에서 간단합니다. 다음은 내 코드입니다.

@MappedSuperclass 
public abstract class EclipseLinkHistoryFix { 

    @Transient 
    private Long savedId; 

    @Id 
    @Column(name = "id") 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    private Long id; 

    @PreUpdate 
    public void saveId() { 
     savedId = getId(); 
    } 

    @PostUpdate 
    public void restoreId() { 
     if (savedId != null) { 
      if (id == null || id.longValue() != savedId.longValue()) { 
       setId(savedId); 
      } 
      savedId = null; 
     } 
    } 

    public final Long getId() { 
     return id; 
    } 

    public final void setId(Long id) { 
     this.id = id; 
    } 
} 

이 해킹은 EclipseLink의 내부 동작에 따라 다르므로 향후 업데이트에서 작동하지 않을 수 있습니다. 운좋게도 v2.6.4에서 PostUpdate 콜백은 히스토리가 삽입 된 후에 호출되어 위대한 기능을합니다.