it-swarm.com.ru

Свойство Not-null ссылается на нулевое или временное значение для постоянного значения

Я пытаюсь сохранить два разных объекта, используя 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 является нулевым или временным, даже если child был создан и сохранен перед этой операцией. Странно то, что это дает сбой только в модульном тесте, а в реальном приложении с предварительно вставленным дочерним элементом это работает так, как ожидалось.

PS: Я прекрасно знаю, что мог бы сопоставить ребенка с сохранением каскада, но это не идея здесь. Я просто хочу проверить, работают ли эти два независимо.

11
renke

Проблема здесь заключается в том, что вы сохраняете родительскую таблицу со значениями, установленными . Когда она сохраняется, ей нужен идентификатор дочерней таблицы, который должен быть сохранен уже, поскольку это был внешний ключ, и, следовательно, это были ненулевые ссылки на свойства. нулевое значение.

    @Test
    public void testSave() {
        Child child = new Child();
        child.setId(1);
        entityManager.persist(child); 

        Parent parent = new Parent();
        parent.setChild(child);

        entityManager.persist(parent); 
    }

Попробуйте это, чтобы сначала сохранить дочерний, а затем родительский. Также измените отображение

8
muthukumar

Первое, что вы используете @ManyToOne в Parent, который говорит мне, что у вас более одного родителя для одного дочернего объекта, я думаю, что это не так.

Что касается структуры вашего класса, я могу понять, что у вас есть сопоставление OneToOne между родительским и дочерним объектами.

Что касается исключения, есть ли причина, по которой вы не используете каскады между Parent и Child для автоматической обработки сопоставления для сохранения, обновления и удаления? Если вы не подумали об этом, вы можете попробовать, установив нижеприведенную конфигурацию, как указано здесь: Пример Parent/Child - Hibernate

cascade = {CascadeType.ALL}

Хотя я бы предложил поменять отображение с ManyToOne на OneToOne между Child и Parent.

Пожалуйста, дайте мне знать.

2
Shaikh Mohammed Shariq

Помимо наличия проблемы Родитель с 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;
2
Vlad Mihalcea

Попробуй это:

@ManyToOne(fetch = FetchType.LAZY,optional=false)
@JoinColun(name = "child_id", nullable = "false")
public Child getChild() {
    return child;
}
1
Tkachuk_Evgen

Для какого-то поля задано not-null="true", перед тем, как сохранить его в db ..__, необходимо указать это значение. Для всех полей в родительской таблице и для дочерней таблицы установите все ненулевые поля с соответствующим значением.

0
xrcwrn

Попробуйте указать @ManyToOne(fetch = FetchType.LAZY,cascade=PERSIST, mappedBy="parent") для public Child getChild() и сохранить только родительский объект. Оба будут сохранены. 

0
DS Stack