2016-08-19 52 views
0

我嘗試使用內存中的H2數據庫來測試某些實體的持久性,但是我認識到@SequenceGenerator永遠不會被調用,因爲它應該是這樣,既不是在通過構建平臺運行時,也不是在運行時使用RunAs-> JUnit test in蝕。SequenceGenerator在JUnit測試中不起作用?

我可以肯定地說,序列是在H2 DB內部生成的。當我連接到生成的H2時,我甚至可以選擇它們。所以在H2內部絕對不是問題,但是使用Hibernate。 (通常,Hibernate會在持久需要實體的時候自動分配一個ID)。

實體

@Entity 
@Table(name = "HOUSE_USERDATA") 
public class UserData { 

@Id 
@Column(name = "HU_ID") 
@GeneratedValue(generator = "SEQ_HOUSE_USERDATA", strategy = GenerationType.SEQUENCE) 
@SequenceGenerator(sequenceName = "SEQ_HOUSE_USERDATA", name = "SEQ_HOUSE_USERDATA", allocationSize = 2) 
private Long huId; 

@Column(name = "HU_DATA") 
@Size(max = 1000) 
private String m_data; 

@ManyToOne 
@JoinColumn(name = "HR_ID") 
private Registry m_registry; 

//more code [...] 
} 

在引用實體的參考...

@OneToMany(mappedBy = "registry") 
    private List<UserData> userDataList; 

持久性單元...

<persistence-unit name="test" transaction-type="RESOURCE_LOCAL"> 
    <provider>org.hibernate.ejb.HibernatePersistence</provider> 
    <class>com.foo.bar.all.entity</class> 
    <!-- all entity references --> 
    <exclude-unlisted-classes>false</exclude-unlisted-classes> 
    <properties> 
     <property name="hibernate.archive.autodetection" value="class"/> 
     <property name="hibernate.connection.username" value="sa"/> 
     <property name="hibernate.connection.password" value=""/> 
     <property name="hibernate.connection.driver_class" value="org.h2.Driver"/> 
     <property name="hibernate.connection.url" 
     value="jdbc:h2:inmemory;INIT=runscript from 'classpath:testscripts/drop_h2.sql'\;runscript from 'classpath:testscripts/create.sql'"/> 
     <property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect" /> 
     <property name="hibernate.hbm2ddl.auto" value="create-drop"/> 
     <property name="hibernate.show_sql" value="true" /> 
     <property name="hibernate.format_sql" value="true" /> 
     <property name="hibernate.use_sql_comments" value="true" /> 
    </properties> 
</persistence-unit> 

在JUnit測試調用...

Registry registry = new Registry(); 
registry.setClientId("clientId"); 
List<UserData> userDataList = new ArrayList<>(); 
UserData userData1 = new UserData(); 
userData1.setData("User defined data 1."); 
userData1.setRegistry(registry); 
UserData userData2 = new UserData(); 
userData2.setData("User defined data 2."); 
userData2.setRegistry(registry); 
userDataList.add(userData1); 
userDataList.add(userData2); 
registry.setUserDataList(userDataList); 


entityManager.persist(registry); 


Registry result = entityManager.find(Registry.class, "clientId"); 
//MUST NOT BE NULL, BUT IS NULL 
assertThat(result.getUserDataList().get(0).getId(), is(not(nullValue()))) 

其他值正確保持。只有ID沒有生成。 (我想知道爲什麼這個測試對所有其他值都起作用,因爲在生成的數據庫中將ID定義爲NOT NULL,所以應該存在持久性異常或其他內容)。 任何ides爲什麼序列發生器不會產生任何東西(我也試過GenerationType.AUTO,但沒有區別)?

+0

因爲它沒有被告知這樣做。您正在堅持'Registry',但'UserData'對象的集合沒有cascade屬性。這意味着只有最高級別的Registry纔會被保存,而不是單個的UserData對象。數據庫中沒有任何內容,從'entityManager.find'方法返回的是從數據庫中存儲在第一級緩存中的對象。如果你在'find'之前執行'entityManager.clear()',你將得到一個沒有'UserData'對象的'Registry'實例。 –

回答

2

當你正在做entityManager.persist(registry)這是它將要做的時候,存儲Registry並檢查該類的所有映射。它會遇到UserData對象的集合,但由於沒有cascade屬性匹配PERSIST它不會存儲UserData對象。

它只會存儲頂層Registry對象。如果你想改變這個,將cascade={CascadeType.ALL}或至少cascade={CascadeType.PERSIST}加到@OneToMany註釋中,爲了告訴Hibernate它還需要檢查集合中是否有新元素並保留這些元素。

或者先儲存UserData元素,然後儲存Registry

+0

謝謝,現在工作。 – Bevor