Java 非空属性引用了持久值的空值或瞬态值
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/27112784/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Not-null property references a null or transient value for persisted value
提问by renke
I'm trying to persist two different entities using JPA1, with the Hibernate implementation. The code for this is as shown below:
我正在尝试使用 JPA1 和 Hibernate 实现来持久化两个不同的实体。代码如下所示:
Parent entity class
父实体类
@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;
}
Child entity class
子实体类
@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;
}
}
Test case
测试用例
@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
}
}
Entity manager and transaction on application.xml
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>
When trying to insert the parent object, hibernate throws a PropertyValueException, saying child is null or transient, even though child was created and persisted before this operation. The odd thing is this only fails on the unit test, and in the real application, with a pre-inserted child, this works just as expected.
当尝试插入父对象时,hibernate 抛出一个 PropertyValueException,说 child 为 null 或瞬态,即使 child 在此操作之前被创建和持久化。奇怪的是,这仅在单元测试中失败,而在实际应用程序中,使用预先插入的孩子,这正如预期的那样工作。
PS: I'm pretty aware I could map child with cascade persist, but that's not the idea here. I just want to check if these two work independently.
PS:我很清楚我可以用级联持续映射孩子,但这不是这里的想法。我只想检查这两个是否独立工作。
回答by Vlad Mihalcea
Aside from having a Parent with a FK to a Child issue, the persist order is what causes your issue.
除了有一个 FK 到子问题的父级之外,持久顺序是导致您出现问题的原因。
Your problem is related to flushing. Just because you instructed Hibernate to persist an object, it doesn't mean it automatically serves your request. The persist request goes to an action queue only to be materialized at flush time. So your second persist simply find the Parent entity without an actual "persisted" Child.
您的问题与冲洗有关。仅仅因为您指示 Hibernate 持久化一个对象,并不意味着它会自动满足您的请求。持久请求进入操作队列,仅在刷新时实现。所以你的第二个坚持只是找到没有实际“持久化”孩子的父实体。
You can simply fix your code as follows:
您可以简单地修复您的代码,如下所示:
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;
回答by muthukumar
The problem here is you are persisting the parent table with the values set . When it goes to persist it needs the child table id which has to be persisted already as it was a foreign key and hence it was a not null property references a null value.
这里的问题是您正在使用 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);
}
Try this to save the child first and then parent .Else changing the mapping
尝试先保存孩子,然后再保存父母。否则更改映射
回答by xrcwrn
Some field is set with not-null="true"
you have to provide value for that before saveing to db.
For all fields in parent table and for child table set all not null fields with appropriate value
某些字段设置为not-null="true"
您必须在保存到数据库之前为其提供值。对于父表和子表中的所有字段,将所有非空字段设置为适当的值
回答by DS Stack
Try giving @ManyToOne(fetch = FetchType.LAZY,cascade=PERSIST, mappedBy="parent")
for public Child getChild()
and persist only the parent object.Both will be persisted.
尝试只@ManyToOne(fetch = FetchType.LAZY,cascade=PERSIST, mappedBy="parent")
为public Child getChild()
和保留父对象。两者都将被保留。
回答by Tkachuk_Evgen
Try this:
尝试这个:
@ManyToOne(fetch = FetchType.LAZY,optional=false)
@JoinColun(name = "child_id", nullable = "false")
public Child getChild() {
return child;
}
回答by Sariq Shaikh
First thing you are using @ManyToOne in Parent which tells me that you are having more than one parent for one Child object, I guess that is not the case.
您在 Parent 中使用 @ManyToOne 的第一件事告诉我,一个 Child 对象有多个父对象,我想情况并非如此。
As per your class structure I can understand that you have OneToOne mapping between Parent and Child entities.
根据您的类结构,我可以理解您在父实体和子实体之间有 OneToOne 映射。
Regarding the exception is there a reason you are not using cascades between Parent and Child to handle the mapping automatically for the save, update and delete ? If you have not thought about it than you can give it a try by setting below configuration as specified here : Example Parent/Child - Hibernate
关于例外,您是否有理由不使用父级和子级之间的级联来自动处理保存、更新和删除的映射?如果您还没有考虑过它,那么您可以按照此处指定的方式设置以下配置来尝试一下:示例父/子 - Hibernate
cascade = {CascadeType.ALL}
Though I would suggest to change the mapping from ManyToOne to OneToOne between Child and Parent.
尽管我建议将 Child 和 Parent 之间的映射从 ManyToOne 更改为 OneToOne。
Please let me know.
请告诉我。
回答by Cassidy Laidlaw
I had a similar issue where I got an error saying "not-null property references a null or transient value" in tests but not while running the application normally.
我有一个类似的问题,我在测试中收到一条错误消息,指出“not-null 属性引用了一个空值或瞬态值”,但在正常运行应用程序时却没有。
It turned out I just needed to add one line to my hibernate.properties
file:
结果我只需要在我的hibernate.properties
文件中添加一行:
hibernate.check_nullability=false
For some reason, this option was set to false by default when running the application but true when testing. Adding it to hibernate.properties
didn't affect the running application but fixed the test.
出于某种原因,此选项在运行应用程序时默认设置为 false,但在测试时设置为 true。添加它hibernate.properties
不会影响正在运行的应用程序,但修复了测试。