2017-09-27 40 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被設置爲零。我看到來自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() 

注意歷史記錄表插入後的「SELECT LAST_INSERT_ID()」。歷史記錄表沒有生成的標識,因此此查詢返回零,並且此值將被覆蓋到對象的標識字段中。原始ID丟失,這對應用程序有問題。

有沒有人知道如何克服與Eclipselink與MySQL的這種短缺?

+0

這是[EclipseLink中的已知錯誤](https://bugs.eclipse.org/bugs/show_bug.cgi?id=323023)。在2010年報道! 7年過去了,我想我有2次得到這個固定的機會[Buckley's和Nunn](https://en.wikipedia.org/wiki/Buckley_%26_Nunn)。 – 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的內部行爲,因此可能無法在將來的更新。幸運的是,在2.6.6版本中,在插入歷史記錄之後調用PostUpdate回調函數,所以這很有用。