繁体   English   中英

非空属性引用了持久值的空值或瞬态值

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM