2012-06-04 78 views
1

在JPA2中是否存在指定合併時不會分配@Id變量的情況?然後返回實體的新實例而不發出異常?EntityManager可以不分配一個ID嗎?

說我有這個層次:

@MappedSuperclass 
abstract class Bar { 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private Long id; 

    ... 
} 

@Entity 
@Table(name = "BAR_1S") 
@Access(AccessType.PROPERTY) 
class Bar1 extends Bar { 
    ... 
} 

@Entity 
@Table(name = "BAR_2S") 
@Access(AccessType.PROPERTY) 
class Bar2 extends Bar { 
    ... 
} 

對於一個尚未被發現的原因BAR1的情況下獲得一個ID合併(後),而BAR2的情況下沒有。至少這就是它的樣子。我一直在嘗試各種方法,但沒有任何優勢。

它看起來像Hibernate(4.1.4.Final)不想分配一個id到該特定類的實例。 :-)

我有以下問題:

  • 沒有人曾經有過這樣的事情?

  • 有人可以告訴我在Hibernate的id在哪裏設置?所以我可以調試那部分代碼,找出爲什麼它跳過了這個任務。 IntelliJ似乎沒有在實體中的字段修改中斷。

編輯 - 環境配置

  • OS:LMDE AMD64
  • 數據庫:MySQL的(5.1.61-2)ConnectJ(5.1.17)
  • JVM:1.7.0_04
  • 休眠:4.1.4.Final
  • 彈簧:3.1.1

EDIT-CODE

全部實體類是(在)Bar的直接子類。只有一個地方@Id被定義。並且有幾個相同的情況Bar2 得到一個id。但具體而言,Bar2沒有。

final Bar1 bar = new Bar1();JpaTemplate.merge(bar); < - 得到一個編號

最終Bar2 bar = new Bar2();JpaTemplate.merge(bar); < - 沒有ID

該應用程序使用Spring的JpaTemplate來合併實體。對於特定類別的一切異常,它都可以運行。因此,如果我能找到Hibernate類來分配id,我可能會發現我忽略了哪些愚蠢的細節。 :-)

+0

AUTO和您的數據庫的策略是什麼?你用來合併Bar2的代碼是什麼? –

回答

0

找到了!合併發生在由@Transactional註解的重載方法中。我假設重載方法會「繼承」註釋。顯然情況並非如此。

通過使用@Transactional註解重載方法,它似乎工作。

知道這將是一件愚蠢的事情...

0

第一個注意事項:JpaTemplate已棄用,不應再使用。它只是委託給EntityManager的merge()方法,並且都返回一個實體。

這裏是JPA規範說,有關合並:

如果X是一個新的實體實例,一個新的管理實體實例X」是創建 和X的狀態被複制到新的管理實體 實例X'。

因此,如果生成一個ID,它將被分配給附屬實體,而不是傳遞給合併方法的對象。因此,您絕不應忽視合併方法的結果。取而代之的

jpaTemplate.merge(bar); 

你應該做的:

bar = jpaTemplate.merge(bar); 

此外,JPA規範還指出,

生成的ID是不能保證可用,直到 數據庫插入有後發生。

而這可能是您沒有ID的另一個原因。 AFAIK,採用MySQL的AUTO策略包括依賴數據庫中的自動增量ID列,並且只有在插入完成後才能獲得ID的值,並且Hibernate會一直等待直到完全需要刷新爲止,因此執行插入。如果你真的需要有合併後的ID正確,請執行以下操作:

bar = jpaTemplate.merge(bar); 
jpaTemplate.flush(); 
Long id = bar.getId(); 
相關問題