Hibernate一对多问题

发布于 2024-10-06 04:42:45 字数 7409 浏览 3 评论 0原文

我正在对一对多映射进行概念验证,但没有成功。我的架构如下:

Student ---->Phone

class Student

public class Student implements java.io.Serializable 
{
   private Set<Phone> studentPhoneNumbers = new HashSet<Phone>();
   // other setters and getters and constructors
}

class Phone

public class Phone implements java.io.Serializable 
{ 
  private Student student;
// other setters and getters and constructors
}

Student 映射文件:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated Dec 5, 2010 7:56:05 PM by Hibernate Tools 3.4.0.Beta1 -->
<hibernate-mapping>
    <class name="com.BiddingSystem.domain.Student" table="STUDENT">
        <id name="studentId" type="long">
            <column name="STUDENTID" />
            <generator class="native" />
        </id>
        <property name="studentName" type="java.lang.String">
            <column name="STUDENTNAME" />
        </property>
        <set name="studentPhoneNumbers" table="PHONE" inverse="true" cascade="all">
            <key>
                <column name="STUDENTID" not-null="true" />
            </key>
            <one-to-many class="com.BiddingSystem.domain.Phone" />
        </set>
    </class>
</hibernate-mapping>

电话映射文件:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated Dec 5, 2010 7:56:05 PM by Hibernate Tools 3.4.0.Beta1 -->
<hibernate-mapping>
    <class name="com.BiddingSystem.domain.Phone" table="PHONE">
        <id name="phoneId" type="long">
            <column name="PHONEID" />
            <generator class="native" />
        </id>
        <property name="phoneType" type="java.lang.String">
            <column name="PHONETYPE" />
        </property>
        <property name="phoneNumber" type="java.lang.String">
            <column name="PHONENUMBER" />
        </property>
        <many-to-one name="student" class="com.BiddingSystem.domain.Student" not-null="true">
            <column name="STUDENTID" not-null="true"/>
        </many-to-one>
    </class>
</hibernate-mapping>

但是当我这样做时:

            Session session = gileadHibernateUtil.getSessionFactory().openSession();
        Transaction transaction = session.beginTransaction();

        Set<Phone> phoneNumbers = new HashSet<Phone>();
        phoneNumbers.add(new Phone("house","32354353"));
        phoneNumbers.add(new Phone("mobile","9889343423"));

        Student student = new Student("Eswar", phoneNumbers);
        session.save(student);

        transaction.commit();
        session.close();

我收到以下错误:

    Caused by: org.hibernate.PropertyValueException: not-null property references a null or transient value: com.BiddingSystem.domain.Phone.student
        at org.hibernate.engine.Nullability.checkNullability(Nullability.java:101)
        at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:313)
        at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:204)
        at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:144)


    at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:210)
        at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:195)
        at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:117)
        at 

org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:93)
    at org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:677)
    at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:669)
    at org.hibernate.engine.CascadingAction$5.cascade(CascadingAction.java:252)
    at org.hibernate.engine.Cascade.cascadeToOne(Cascade.java:392)
    at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:335)
    at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:204)
    at org.hibernate.engine.Cascade.cascadeCollectionElements(Cascade.java:425)
    at org.hibernate.engine.Cascade.cascadeCollection(Cascade.java:362)
    at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:338)
    at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:204)
    at org.hibernate.engine.Cascade.cascade(Cascade.java:161)
    at org.hibernate.event.def.AbstractSaveEventListener.cascadeAfterSave(AbstractSaveEventListener.java:476)
    at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:354)
    at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:204)
    at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:144)
    at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:210)
    at org.hibernate.event.def.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:56)
    at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:195)
    at org.hibernate.event.def.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:50)
    at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:93)
    at org.hibernate.impl.SessionImpl.fireSave(SessionImpl.java:705)
    at org.hibernate.impl.SessionImpl.save(SessionImpl.java:693)
    at org.hibernate.impl.SessionImpl.save(SessionImpl.java:689)
    at com.BiddingSystem.server.GreetingServiceImpl.greetServer(GreetingServiceImpl.java:52)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at net.sf.gilead.gwt.PersistentRemoteService.processCall(PersistentRemoteService.java:174)
    ... 21 more

有人可以帮助为此设置正确的属性吗 电话映射 xml 文件

<many-to-one name="student" class="com.BiddingSystem.domain.Student" not-null="true">
            <column name="STUDENTID" not-null="true"/>
</many-to-one>

和学生映射文件

<set name="studentPhoneNumbers" table="PHONE" inverse="true" cascade="all">
            <key>
                <column name="STUDENTID" not-null="true" />
            </key>
            <one-to-many class="com.BiddingSystem.domain.Phone" />
</set>

I am doing a proof of concept for one to many mapping with no success. My schema is as follows:

Student ---->Phone

class Student

public class Student implements java.io.Serializable 
{
   private Set<Phone> studentPhoneNumbers = new HashSet<Phone>();
   // other setters and getters and constructors
}

class Phone

public class Phone implements java.io.Serializable 
{ 
  private Student student;
// other setters and getters and constructors
}

Student Mapping File:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated Dec 5, 2010 7:56:05 PM by Hibernate Tools 3.4.0.Beta1 -->
<hibernate-mapping>
    <class name="com.BiddingSystem.domain.Student" table="STUDENT">
        <id name="studentId" type="long">
            <column name="STUDENTID" />
            <generator class="native" />
        </id>
        <property name="studentName" type="java.lang.String">
            <column name="STUDENTNAME" />
        </property>
        <set name="studentPhoneNumbers" table="PHONE" inverse="true" cascade="all">
            <key>
                <column name="STUDENTID" not-null="true" />
            </key>
            <one-to-many class="com.BiddingSystem.domain.Phone" />
        </set>
    </class>
</hibernate-mapping>

Phone Mapping File:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated Dec 5, 2010 7:56:05 PM by Hibernate Tools 3.4.0.Beta1 -->
<hibernate-mapping>
    <class name="com.BiddingSystem.domain.Phone" table="PHONE">
        <id name="phoneId" type="long">
            <column name="PHONEID" />
            <generator class="native" />
        </id>
        <property name="phoneType" type="java.lang.String">
            <column name="PHONETYPE" />
        </property>
        <property name="phoneNumber" type="java.lang.String">
            <column name="PHONENUMBER" />
        </property>
        <many-to-one name="student" class="com.BiddingSystem.domain.Student" not-null="true">
            <column name="STUDENTID" not-null="true"/>
        </many-to-one>
    </class>
</hibernate-mapping>

But when I am doing this:

            Session session = gileadHibernateUtil.getSessionFactory().openSession();
        Transaction transaction = session.beginTransaction();

        Set<Phone> phoneNumbers = new HashSet<Phone>();
        phoneNumbers.add(new Phone("house","32354353"));
        phoneNumbers.add(new Phone("mobile","9889343423"));

        Student student = new Student("Eswar", phoneNumbers);
        session.save(student);

        transaction.commit();
        session.close();

I am getting the following errors:

    Caused by: org.hibernate.PropertyValueException: not-null property references a null or transient value: com.BiddingSystem.domain.Phone.student
        at org.hibernate.engine.Nullability.checkNullability(Nullability.java:101)
        at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:313)
        at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:204)
        at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:144)


    at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:210)
        at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:195)
        at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:117)
        at 

org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:93)
    at org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:677)
    at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:669)
    at org.hibernate.engine.CascadingAction$5.cascade(CascadingAction.java:252)
    at org.hibernate.engine.Cascade.cascadeToOne(Cascade.java:392)
    at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:335)
    at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:204)
    at org.hibernate.engine.Cascade.cascadeCollectionElements(Cascade.java:425)
    at org.hibernate.engine.Cascade.cascadeCollection(Cascade.java:362)
    at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:338)
    at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:204)
    at org.hibernate.engine.Cascade.cascade(Cascade.java:161)
    at org.hibernate.event.def.AbstractSaveEventListener.cascadeAfterSave(AbstractSaveEventListener.java:476)
    at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:354)
    at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:204)
    at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:144)
    at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:210)
    at org.hibernate.event.def.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:56)
    at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:195)
    at org.hibernate.event.def.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:50)
    at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:93)
    at org.hibernate.impl.SessionImpl.fireSave(SessionImpl.java:705)
    at org.hibernate.impl.SessionImpl.save(SessionImpl.java:693)
    at org.hibernate.impl.SessionImpl.save(SessionImpl.java:689)
    at com.BiddingSystem.server.GreetingServiceImpl.greetServer(GreetingServiceImpl.java:52)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at net.sf.gilead.gwt.PersistentRemoteService.processCall(PersistentRemoteService.java:174)
    ... 21 more

Can someone help in setting the proper attributes for this
phone mapping xml file

<many-to-one name="student" class="com.BiddingSystem.domain.Student" not-null="true">
            <column name="STUDENTID" not-null="true"/>
</many-to-one>

and Student mapping file

<set name="studentPhoneNumbers" table="PHONE" inverse="true" cascade="all">
            <key>
                <column name="STUDENTID" not-null="true" />
            </key>
            <one-to-many class="com.BiddingSystem.domain.Phone" />
</set>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

困倦 2024-10-13 04:42:45

您需要将 Student 对象推入 Phone 对象:

foreach (Phone phone : student.getStudentPhoneNumbers()) {
    phone.setStudent(student);
}

更典型的代码片段将首先创建 Student 实例,然后向其中添加电话号码。我经常实现一个方法来帮助解决这个问题,例如在 Student.java 中:

public void addPhoneNumber(Phone phone) {
    phone.setStudent(this);
    getStudentPhoneNumbers().add(phone);
}
public void addPhoneNumber(String type, String number) {
    addPhoneNumber(new Phone(type, number));
}

所以现在你可以说 student.addPhoneNumber("home", "12354") 它会简单地执行 DTRT。

You need to push the Student object into the Phone objects:

foreach (Phone phone : student.getStudentPhoneNumbers()) {
    phone.setStudent(student);
}

A more typical piece of code would create the Student instance first, and then add the phone numbers to it. I've often implemented a method to help with this, e.g. in Student.java:

public void addPhoneNumber(Phone phone) {
    phone.setStudent(this);
    getStudentPhoneNumbers().add(phone);
}
public void addPhoneNumber(String type, String number) {
    addPhoneNumber(new Phone(type, number));
}

So now you can say student.addPhoneNumber("home", "12354") and it will simply DTRT.

阪姬 2024-10-13 04:42:45

由于您使用带有 inverse=true 选项的双向关联,因此子对象将独立保留。父对象不关心与子对象的同步。因此,在这种情况下,将有一个针对父对象的插入查询和与子对象一样多的插入查询。因此,子对象在插入时需要具有父对象的引用。此外,您还在父级和子级定义了 not-null=true 。

当我们使用 inverse=false 时,将首先保存父对象,然后在不引用父对象的情况下保存子对象,最后父对象将使用更新查询更新其与子对象的关系。

希望这有帮助。

Since you are using Bi-Direction association with inverse=true option, the child objects will be persisted independently. The parent object doesn't take care about synchronization with child objects. So in this case, there will one insert query for parent object and as many insert query as the child objects. So, child object need to have reference of parent object at insert time. Also you have defined not-null=true at parent as well as child side.

When we use inverse=false, parent will be saved first, then child will be saved without reference of parent object and at last the parent will update its relationship with child using the update queries.

Hope this helps.

迷路的信 2024-10-13 04:42:45

1).电话号码必须有学生,因此首先创建一个学生对象 (stu = new Student()) 并
然后调用phone.setStudent(stu);

前任:

   Set<Phone> phoneNumbers = new HashSet<Phone>();

   Phone p1 = new Phone("house", "32354353");

   phoneNumbers.add(p1);
   Phone p2 = new Phone("mobile", "9889343423");
   phoneNumbers.add(p2);

   Student student = new Student("Eswar", phoneNumbers);
   student.setPhones(phoneNumbers);
   session.save(student); //Till now, This code is work if you use cascade = 'all' in            //my_mapping_file.xml or

   session.save(p1); session.save(p2); //call session.save on both phone objects

1). Phone number must have a student so create a student object (stu = new Student()) first and
then call phone.setStudent(stu);

ex:

   Set<Phone> phoneNumbers = new HashSet<Phone>();

   Phone p1 = new Phone("house", "32354353");

   phoneNumbers.add(p1);
   Phone p2 = new Phone("mobile", "9889343423");
   phoneNumbers.add(p2);

   Student student = new Student("Eswar", phoneNumbers);
   student.setPhones(phoneNumbers);
   session.save(student); //Till now, This code is work if you use cascade = 'all' in            //my_mapping_file.xml or

   session.save(p1); session.save(p2); //call session.save on both phone objects
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文