2013-06-28 27 views
0

有人可以解釋這種行爲嗎?通過EclipseLink多次調用實體「setter」方法

下面給出一個實體myEntity所,下面的代碼

EntityManagerFactory emf = Persistence.createEntityManagerFactory("greetingPU"); 
EntityManager em = emf.createEntityManager(); 

MyEntity e = new MyEntity(); 
e.setMessage1("hello"); e.setMessage2("world"); 
em.getTransaction().begin(); 
em.persist(e); 
System.out.println("-- Before commit --"); 
em.getTransaction().commit(); 
System.out.println("-- After commit --"); 

結果在輸出指示myEntity所由EclipseLinks的EntityManager或其聯繫人的「setter」方法的多次調用。這是行爲嗎?可能出於某些內部表現或結構原因?其他JPA實現是否顯示相同的行爲?

-- Before commit -- 
setId 
setId 
setMessage1 
setMessage2 
setId 
setMessage1 
setMessage2 
-- After commit -- 

似乎有兩種不同的重新分配。首先是Id的初始集合。其次,整個實體的兩個連續設置。 調試顯示給定「setter」的所有調用都具有與其參數相同的對象。

@Entity 
public class MyEntity { 

    private Long id; 
    private String message1; 
    private String message2; 

    @Id 
    @GeneratedValue(strategy=GenerationType.SEQUENCE) 
    public Long getId(){ return id; } 
    public void setId(Long i) { 
    System.out.println("setId"); 
    id = i; 
    } 

    public String getMessage1() { return message1; } 
    public void setMessage1(String m) { 
    message1 = m; 
    System.out.println("setMessage1"); 
    } 

    public String getMessage2() { return message2; } 
    public void setMessage2(String m) { 
    message2 = m; 
    System.out.println("setMessage2"); 
    } 
} 
+1

您應該打印堆棧軌跡以獲取有關調用的更多詳細信息。你有沒有跨過那段代碼? – SpaceTrucker

+0

謝謝。打印堆棧跟蹤很有幫助。它顯示了來電的來源,但不足以讓我理解爲什麼。克里斯答案解釋說。 – dmb

回答

1

你在使用編織嗎? http://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Advanced_JPA_Development/Performance/Weaving

EclipseLink必須調用setId一次才能在託管實體實例中設置生成的ID。它還會創建一個實例併爲共享緩存設置其值,解釋另一個setId和set值調用。如果您沒有使用編織,因爲EntityManager仍然存在,EclipseLink還將創建一個備份實例以用於比較未來的更改 - 在事務提交之後對該被管實體的任何更改仍需要跟蹤。

如果這不合乎要求,則編織允許使用屬性更改跟蹤,以便不需要備份副本來跟蹤更改。您也可以關閉共享緩存,但除非您遇到性能問題或陳舊的數據問題,否則不建議這樣做。

+0

謝謝。調試顯示確實涉及三個不同的MyEntity對象。每個人只能「設置」一次。 – dmb