[英]Not-null property references a null or transient value for persisted value
我正在嘗試使用 JPA1 和 Hibernate 實現來持久化兩個不同的實體。 代碼如下所示:
父實體類
@Entity
@Table(name = "parent")
public class Parent implements Serializable {
{...}
private Child child;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "child_id", nullable = "false")
public Child getChild() {
return child;
}
public void setChild(Child child) {
this.child = child;
}
子實體類
@Entity
@Table(name = "child")
public class Child implements Serializable {
private Integer id;
@Id
@Column(name = "child_id")
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
}
測試用例
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:META-INF/application.xml")
@Transactional
public class ParentTest extends TestCase {
@PersistenceContext
private EntityManager entityManager;
@Test
public void testSave() {
Child child = new Child();
child.setId(1);
Parent parent = new Parent();
parent.setChild(child);
entityManager.persist(parent.getChild());
entityManager.persist(parent); // throws the exception
}
}
application.xml 上的實體管理器和事務
<tx:annotation-driven transaction-manager="transactionManager" />
<jee:jndi-lookup id="dataSource" jndi-name="java:/jdbc/myds" expected-type="javax.sql.DataSource" />
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="packagesToScan" value="com.mypackage" />
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter"›
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect>org.hibernate.dialect.Oracle10gDialect</prop>
</props>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
當嘗試插入父對象時,hibernate 拋出一個 PropertyValueException,說 child 為 null 或瞬態,即使 child 在此操作之前被創建並持久化。 奇怪的是,這只在單元測試中失敗,而在實際應用程序中,使用預先插入的孩子,這正如預期的那樣工作。
PS:我很清楚我可以用級聯持續映射孩子,但這不是這里的想法。 我只想檢查這兩個是否獨立工作。
這里的問題是您使用 set 值持久化父表。 當它持久化時,它需要子表 id,它必須已經被持久化,因為它是一個外鍵,因此它是一個非空屬性引用一個空值。
@Test
public void testSave() {
Child child = new Child();
child.setId(1);
entityManager.persist(child);
Parent parent = new Parent();
parent.setChild(child);
entityManager.persist(parent);
}
嘗試先保存孩子,然后再保存父母。否則更改映射
您在 Parent 中使用 @ManyToOne 的第一件事告訴我,一個 Child 對象有多個父對象,我想情況並非如此。
根據您的類結構,我可以理解您在父實體和子實體之間有 OneToOne 映射。
關於例外,您是否有理由不使用父級和子級之間的級聯來自動處理保存、更新和刪除的映射? 如果您還沒有考慮過它,那么您可以按照此處指定的方式設置以下配置來嘗試一下: 示例父/子 - Hibernate
cascade = {CascadeType.ALL}
盡管我建議將 Child 和 Parent 之間的映射從 ManyToOne 更改為 OneToOne。
請告訴我。
除了有一個 FK 到子問題的父級之外,持久順序是導致您出現問題的原因。
您的問題與沖洗有關。 僅僅因為您指示 Hibernate 持久化一個對象,並不意味着它會自動滿足您的請求。 持久請求進入操作隊列,僅在刷新時實現。 所以你的第二個堅持只是找到沒有實際“持久化”孩子的父實體。
您可以簡單地修復您的代碼,如下所示:
Child child = new Child();
child.setId(1);
entityManager.persist(parent.getChild());
entityManager.flush();
Parent parent = new Parent();
parent.setChild(child);
entityManager.persist(parent);
entityManager.flush;
嘗試這個:
@ManyToOne(fetch = FetchType.LAZY,optional=false)
@JoinColun(name = "child_id", nullable = "false")
public Child getChild() {
return child;
}
某些字段設置為not-null="true"
您必須在保存到 db 之前為其提供值。 對於父表和子表中的所有字段,將所有非空字段設置為適當的值
嘗試為public Child getChild()
提供@ManyToOne(fetch = FetchType.LAZY,cascade=PERSIST, mappedBy="parent")
public Child getChild()
並僅保留父對象。兩者都將被保留。
我有一個類似的問題,我在測試中收到一條錯誤消息,指出“not-null 屬性引用了一個空值或瞬態值”,但在正常運行應用程序時卻沒有。
結果我只需要在hibernate.properties
文件中添加一行:
hibernate.check_nullability=false
出於某種原因,此選項在運行應用程序時默認設置為 false,但在測試時設置為 true。 將它添加到hibernate.properties
不會影響正在運行的應用程序,但修復了測試。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.