保存子对象列表时的org.hibernate.NonUniqueObjectException

时间:2014-10-01 02:04:16

标签: java hibernate hibernate-mapping

我需要在创建父对象时保存多个子对象。理想情况下,我想将它们保存在一个事务中,但是,我不断获得org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session

在此示例中,SubDiscipline具有许多SubdisciplinePlayers。

我觉得映射存在问题

的POJO:

Subdiscipline.java

public class Subdiscipline {

    private int id;
    private int disciplineId;
    private String name;
    private List<SubdisciplinePlayer> subdisciplinePlayers;

    public Subdiscipline() {
    }

    //standard constructors, getter & setters...
}

SubdisciplinePlayers.java

public class SubdisciplinePlayer implements Serializable {

    private int idPlayers;
    private int disciplineId;
    private int subDisciplineId;
    private int players;
    private int minPlayers;
    private int maxPlayers;

    private Subdiscipline subdiscipline;

    public SubdisciplinePlayer() {
    }
    //standard constructors, getter & setters...
}

Main.java:

public class Main {

    @SuppressWarnings("unchecked")
    public static void main(String[] args) {

        SessionFactory sf = HibernateUtil.getSessionFactory();
        Session session = sf.openSession();
        session.beginTransaction();

        Subdiscipline sd = new Subdiscipline("soccer_" + (new Date()).getTime(), new Date(), new Date(), new Status(1) );
        sd.setDisciplineId(4);
        session.save(sd);

        SubdisciplinePlayer sdp = new SubdisciplinePlayer();
        sdp.setDisciplineId(sd.getDisciplineId());
        sdp.setSubDisciplineId(sd.getId());
        sdp.setSubdiscipline(sd);
        sdp.setIdPlayers(555);

        SubdisciplinePlayer sdp2 = new SubdisciplinePlayer();
        sdp2.setDisciplineId(sd.getDisciplineId());
        sdp2.setSubDisciplineId(sd.getId());
        sdp2.setSubdiscipline(sd);
        sdp2.setIdPlayers(457);

        sd.setSubdisciplinePlayers(new ArrayList<SubdisciplinePlayer>());
        sd.getSubdisciplinePlayers().add(sdp);
        sd.getSubdisciplinePlayers().add(sdp2);

        session.save(sd);

        session.getTransaction().commit();
        session.close();

    }
}

映射

Subdiscipline Mapping

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping
PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
    <class name="net.viralpatel.hibernate.Subdiscipline" table="sub_discipline">
        <id name="id" column="sub_dis_id" unsaved-value="0">
            <generator class="increment"/>
        </id>
        <property name="disciplineId" column="dis_id" type="int"/>
        <property name="name" column="sub_discipline" type="string"/>           
        <bag name="subdisciplinePlayers" table="sdis_players" inverse="true" cascade="all">
            <key column="sub_dis_id" />
            <one-to-many class="net.viralpatel.hibernate.SubdisciplinePlayer" />
        </bag>

    </class>
</hibernate-mapping>

SubdisciplinePlayer Mapping

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping
PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
    <class name="net.viralpatel.hibernate.SubdisciplinePlayer" table="sdis_players">
        <composite-id>
            <key-property name="disciplineId" column="dis_id" type="int"/>
            <key-property name="subDisciplineId" column="sub_dis_id" type="int" />
        </composite-id>
        <property name="idPlayers" column="id_players" type="int"/>
        <property name="players" column="players" type="int"/>
        <property name="minPlayers" column="min_players" type="int"/>
        <property name="maxPlayers" column="max_players" type="int"/>
        <many-to-one name="subdiscipline" class="net.viralpatel.hibernate.Subdiscipline" cascade="none" insert="false" update="false">
            <column name="sub_dis_id"/>
        </many-to-one>
    </class>
</hibernate-mapping>

抛出异常

Exception in thread "main" org.hibernate.NonUniqueObjectException: a different object     with the same identifier value was already associated with the session:     [net.viralpatel.hibernate.SubdisciplinePlayer#net.viralpatel.hibernate.SubdisciplinePlayer@1cd7e9c3]

2 个答案:

答案 0 :(得分:2)

您已使用字段disciplineId&amp; subDisciplineId为您的实体SubdisciplinePlayer

现在,在您的程序中,您将创建2个具有相同复合ID的SubdisciplinePlayer实例。

SubdisciplinePlayer sdp = new SubdisciplinePlayer();
sdp.setDisciplineId(sd.getDisciplineId());
sdp.setSubDisciplineId(sd.getId());

SubdisciplinePlayer sdp2 = new SubdisciplinePlayer();
sdp2.setDisciplineId(sd.getDisciplineId());
sdp2.setSubDisciplineId(sd.getId());

因此,当您调用Session.save(sd)时,hibernate发现您正在尝试保存2个SubdisciplinePlayer实例并将异常抛出为:

org.hibernate.NonUniqueObjectException: a different objectwith the same identifier 
value was already associated with the session:     
[net.viralpatel.hibernate.SubdisciplinePlayer#
net.viralpatel.hibernate.SubdisciplinePlayer@1cd7e9c3]

要解决此问题,请确保SubdisciplinePlayer的复合ID应具有不同的值,因为主键应该是唯一的。

答案 1 :(得分:1)

尝试第二次保存时,请使用合并而不是保存。

   sd.setSubdisciplinePlayers(new ArrayList<SubdisciplinePlayer>());
   sd.getSubdisciplinePlayers().add(sdp);
   sd.getSubdisciplinePlayers().add(sdp2);
   session.merge(sd);

我为你列出了更多的参考资料。

Ref 1

Ref 2