线程" main"中的例外情况org.hibernate.PropertyValueException:not-null属性引用null或transient值

时间:2014-04-03 13:32:11

标签: java hibernate one-to-many

我试图在hibernate中实现一对多关系而不使用连接表并面临一个奇怪的错误。有人可以帮忙吗?

User.Java

import java.util.Set;

public class User {

    private int id;
    private Set<Address> addresses;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public Set<Address> getAddresses() {
        return addresses;
    }

    public void setAddresses(Set<Address> addresses2) {
        this.addresses = addresses;
    }
}

Address.java

public class Address {

    private int id;
    private User user;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }
}

User.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="User"
     table="USER">
        <id name="id" column="user_id">
            <generator class="native">
                <param name="sequence">HIBERNATE_SEQUENCE
                </param>
            </generator>
        </id>
        <set name="addresses" inverse="true">
        <key column="address_id"/>
        <one-to-many class="Address"/>
    </set>
    </class>
</hibernate-mapping>

** Address.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="Address"
     table="Address">
        <id name="id" column="address_id">
            <generator class="native">
                <param name="sequence">HIBERNATE_SEQUENCE
                </param>
            </generator>
        </id>
        <many-to-one name="user" 
        column="user_id"
        not-null="true"/>

    </class>
</hibernate-mapping>

测试人员类

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class HibernateTest {

/**
 * @param args
 */
public static void main(String[] args) {
    // TODO Auto-generated method stub
    User user = new User();
    Address address1 = new Address();
    Address address2 = new Address();
    Address address3 = new Address();
    Address address4 = new Address();
    Set<Address> addresses = new HashSet<Address>();
    addresses.add(address1);addresses.add(address2);addresses.add(address3);        addresses.add(address4);
    user.setAddresses(addresses);
    SessionFactory factory = (new Configuration()).configure().buildSessionFactory();
    Session session = factory.openSession();
    session.beginTransaction();
    session.save(user);
    session.save(address1);
    session.save(address2);
    session.save(address3);
    session.save(address4);
    session.getTransaction().commit();
    session.close();
}

}

错误staccktrace

Apr 3, 2014 6:50:59 PM org.hibernate.tool.hbm2ddl.SchemaExport execute
INFO: HHH000230: Schema export complete
Hibernate: select HIBERNATE_SEQUENCE.nextval from dual
Hibernate: select HIBERNATE_SEQUENCE.nextval from dual
Exception in thread "main" org.hibernate.PropertyValueException: not-null property references a null or transient value : Address.user
at org.hibernate.engine.internal.Nullability.checkNullability(Nullability.java:106)
at     org.hibernate.action.internal.AbstractEntityInsertAction.nullifyTransientReferencesIfNotAlready(AbstractEntityInsertAction.java:132)
at org.hibernate.action.internal.AbstractEntityInsertAction.makeEntityManaged(AbstractEntityInsertAction.java:141)
at org.hibernate.engine.spi.ActionQueue.addResolvedEntityInsertAction(ActionQueue.java:199)
at org.hibernate.engine.spi.ActionQueue.addInsertAction(ActionQueue.java:177)
at org.hibernate.engine.spi.ActionQueue.addAction(ActionQueue.java:164)
at org.hibernate.event.internal.AbstractSaveEventListener.addInsertAction(AbstractSaveEventListener.java:332)
at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:288)
at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:194)
at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:137)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:209)
at org.hibernate.event.internal.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:55)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:194)
at org.hibernate.event.internal.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:49)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:90)
at org.hibernate.internal.SessionImpl.fireSave(SessionImpl.java:715)
at org.hibernate.internal.SessionImpl.save(SessionImpl.java:707)
at org.hibernate.internal.SessionImpl.save(SessionImpl.java:702)
at HibernateTest.main(HibernateTest.java:38)

在论坛上,我读到这个问题可以通过在User.xml中使用inverse =“true”解决,但这解决了问题。

有人可以帮忙吗?

2 个答案:

答案 0 :(得分:0)

在你的user.hbm.xml

将一个改为多个,如下所示

  <set name="addresses" inverse="true" lazy="true" fetch="select">
            <key>
                <column name="address_id" not-null="true" />
            </key>
            <one-to-many class="Address" />
        </set>

并运行它。

在两个映射文件中,

not null都应为true。

执行后告诉我。

答案 1 :(得分:0)

在映射中,您指定了Address实体中的用户属性不为空。

 <many-to-one name="user" 
        column="user_id"
        not-null="true"/>

但是在您的代码中,您尝试使用null用户属性保存地址。您必须调用 如果要将address1与用户关联,请在保存address1之前address1.setUser(user)

编辑: 你在行地址设置器

上犯了一个错误
this.addresses = addresses;

应该是

this.addresses = addresses2;

顺便说一下,您可以将此方法添加到用户实体

private void associateAddressesWithUser(){
    for(Address address : addresses) address.setUser(this);
}

并在地址设置器(在用户实体上)进行了这些更改

   public void setAddresses(Set<Address> addresses2) {
       this.addresses = addresses2;
       associateAddressesWithUser(); 
   }