Hibernate Many-toMany关系:如何修复org.hibernate.exception.GenericJDBCException:无法初始化集合异常?

时间:2012-08-07 12:34:50

标签: hibernate many-to-many associations

我使用hibernate网站上的hibernate_reference.pdf来使用Hibernate多对多关联。我正在使用文档中描述的相同实体Event.java和Person.java。

我看到很多人面临“无法初始化集合异常”,许多人解决了这个问题,但是在流程帖子中的堆栈中提到的解决方案都没有解决我的问题。可能是那些解决方案不适用于多对多关联,或者我的配置存在一些问题。以下是我的hbm.xml文件:

Event.hbm.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 package="roseindia.tutorial.hibernate">
    <class name="Event" table="EVENTS">

        <id name="id" column="EVENT_ID">
            <generator class="native" />
        </id>

        <property name="date" type="timestamp" column="EVENT_DATE" />
        <property name="title" type="string" />
        <property name="location" type="string" column="LOC" />

        <set name="participants" table="PERSON_EVENT" inverse="true" lazy="false" cascade="all" >
            <key column="EVENT_ID" not-null="true" />
            <many-to-many column="PERSON_ID" class="Person" />
        </set>
    </class>
</hibernate-mapping>

Event.java

public class Event implements java.io.Serializable {
    private long id;
    private String title;
    private Date date;
    private String location;

    public Event() {
        //participants = new HashSet<Person>(0);
    }

    private Set participants = new HashSet(0);

    public Set getParticipants() {
        return participants;
    }

    public void setParticipants(Set participants) {
        this.participants = participants;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((date == null) ? 0 : date.hashCode());
        //result = prime * result + (int) (id ^ (id >>> 32));
        result = prime * result
                + ((location == null) ? 0 : location.hashCode());
        //result = prime * result + ((participants == null) ? 0 : participants.hashCode());
        result = prime * result + ((title == null) ? 0 : title.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Event other = (Event) obj;
        if (date == null) {
            if (other.date != null)
                return false;
        } else if (!date.equals(other.date))
            return false;

        if (location == null) {
            if (other.location != null)
                return false;
        } else if (!location.equals(other.location))
            return false;

        if (title == null) {
            if (other.title != null)
                return false;
        } else if (!title.equals(other.title))
            return false;
        return true;
    }

    @SuppressWarnings("unchecked")
    public void addToParticipants(Person person) {
        this.getParticipants().add(person);
        //person.addToEvent(this);
        person.getEvents().add(this);
    }

    public void removeFromParticipants(Person person) {
        this.getParticipants().remove(this);
        person.getEvents().remove(person);
    }

    public long getId() {
        return id;
    }

    private void setId(long id) {
        this.id = id;
    }

    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
        this.date = date;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getLocation() {
        return this.location;
    }

    public void setLocation(String location) {
        this.location = location;
    }
}

Person.hbm.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 package="roseindia.tutorial.hibernate">
    <class name="Person" table="PERSON">
        <id name="id" column="PERSON_ID">
            <generator class="native" />
        </id>
        <property name="age" />
        <property name="firstname" />
        <property name="lastname" />

        <set name="events" table="PERSON_EVENT" inverse="false" lazy="true" cascade="all" >
            <key column="PERSON_ID" not-null="true" />
            <many-to-many column="EVENT_ID" class="Event" />
        </set>

        <set name="emailAddresses" table="PERSON_EMAIL_ADDR">
            <key column="PERSON_ID" />
            <element type="string" column="EMAIL_ADDR" />
        </set>
    </class>
</hibernate-mapping>

Person.java

import java.util.HashSet;
import java.util.Set;

public class Person implements java.io.Serializable {
    private Set events = new HashSet<Event>();
    private Set emailAddresses = new HashSet();

    public Set getEmailAddresses() {
        return emailAddresses;
    }

    public void setEmailAddresses(Set emailAddresses) {
        this.emailAddresses = emailAddresses;
    }

    public void addToEvent(Event event) {
        this.getEvents().add(event);
        //event.addToParticipants(this);
        event.getParticipants().add(this);
    }

    public void removeFromEvent(Event event) {
        this.getEvents().remove(event);
        //event.removeFromParticipants(this);
        event.getParticipants().remove(this);
    }

    public Set getEvents() {
        return events;
    }

    public void setEvents(Set events) {
        this.events = events;
    }

    public Long getId() {
        return id;
    }

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

    public int getAge() {
        return age;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + age;
        result = prime * result
                + ((firstname == null) ? 0 : firstname.hashCode());
        result = prime * result
                + ((lastname == null) ? 0 : lastname.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Person other = (Person) obj;
        if (age != other.age)
            return false;

        if (firstname == null) {
            if (other.firstname != null)
                return false;
        } else if (!firstname.equals(other.firstname))
            return false;

        if (lastname == null) {
            if (other.lastname != null)
                return false;
        } else if (!lastname.equals(other.lastname))
            return false;
        return true;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getFirstname() {
        return firstname;
    }

    public void setFirstname(String firstname) {
        this.firstname = firstname;
    }

    public String getLastname() {
        return lastname;
    }

    public void setLastname(String lastname) {
        this.lastname = lastname;
    }

    private Long id;
    private int age;
    private String firstname;
    private String lastname;

    public Person() {
    }
}

ManyToManyExample.java

public class ManyToManyExample {

    /**
     * @param args
     */
    public static void main(String[] args) {
        Session session = null;
        try {
            SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
            session = sessionFactory.openSession();
            Transaction tx1 = session.beginTransaction();

            System.out.println("Loading Record");
            Event theEvent = (Event) session.get(Event.class, new Long(1));
            session.refresh(theEvent);
            Person person = new Person();
            person.setAge(31);
            person.getEvents().add(theEvent);
            person.setFirstname("RRRRRR");
            person.setLastname("NNNNNN");
            person.getEmailAddresses().add("RRRRRR@yahoo.com");

            theEvent.getParticipants().add(person); // Adding person ref. to event for many to many relation

            session.save(theEvent);
            session.save(person);
            tx1.commit(); 

            System.out.println("Done...");

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            session.flush();
            session.close();
        }
    }
}

运行以上示例时出现以下错误: INFO DefaultLoadEventListener:129 - 执行加载命令时出错 org.hibernate.exception.GenericJDBCException:无法初始化集合:[roseindia.tutorial.hibernate.Event.participants#1]     在org.hibernate.exception.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:82)     在org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:70)     在org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)     在org.hibernate.loader.Loader.loadCollection(Loader.java:1351)     在org.hibernate.loader.collection.CollectionLoader.initialize(CollectionLoader.java:101)     at org.hibernate.persister.collection.AbstractCollectionPersister.initialize(AbstractCollectionPersister.java:484)     at org.hibernate.event.def.DefaultInitializeCollectionEventListener.onInitializeCollection(DefaultInitializeCollectionEventListener.java:60)     在org.hibernate.impl.SessionImpl.initializeCollection(SessionImpl.java:1346)     at org.hibernate.collection.AbstractPersistentCollection.forceInitialization(AbstractPersistentCollection.java:269)     在org.hibernate.engine.PersistenceContext.initializeNonLazyCollections(PersistenceContext.java:745)     在org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:208)     在org.hibernate.loader.Loader.loadEntity(Loader.java:1255)     在org.hibernate.loader.entity.EntityLoader.load(EntityLoader.java:139)     在org.hibernate.loader.entity.EntityLoader.load(EntityLoader.java:124)     在org.hibernate.persister.entity.BasicEntityPersister.load(BasicEntityPersister.java:2453)     at org.hibernate.event.def.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:387)     at org.hibernate.event.def.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:368)     在org.hibernate.event.def.DefaultLoadEventListener.load(DefaultLoadEventListener.java:166)     在org.hibernate.event.def.DefaultLoadEventListener.load(DefaultLoadEventListener.java:140)     在org.hibernate.event.def.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:249)     在org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:123)     在org.hibernate.impl.SessionImpl.get(SessionImpl.java:561)     在org.hibernate.impl.SessionImpl.get(SessionImpl.java:556)     at roseindia.tutorial.hibernate.ManyToManyExample.main(ManyToManyExample.java:24) 引起:java.sql.SQLException:[Microsoft] [ODBC SQL Server驱动程序]无效的描述符索引     at sun.jdbc.odbc.JdbcOdbc.createSQLException(JdbcOdbc.java:6956)     at sun.jdbc.odbc.JdbcOdbc.standardError(JdbcOdbc.java:7113)     at sun.jdbc.odbc.JdbcOdbc.SQLGetDataDouble(JdbcOdbc.java:3656)     at sun.jdbc.odbc.JdbcOdbcResultSet.getDataDouble(JdbcOdbcResultSet.java:5574)     at sun.jdbc.odbc.JdbcOdbcResultSet.getLong(JdbcOdbcResultSet.java:632)     at sun.jdbc.odbc.JdbcOdbcResultSet.getLong(JdbcOdbcResultSet.java:650)     在org.hibernate.type.LongType.get(LongType.java:26)     在org.hibernate.type.NullableType.nullSafeGet(NullableType.java:77)     在org.hibernate.type.NullableType.nullSafeGet(NullableType.java:68)     at org.hibernate.persister.collection.AbstractCollectionPersister.readKey(AbstractCollectionPersister.java:612)     在org.hibernate.loader.Loader.readCollectionElement(Loader.java:545)     在org.hibernate.loader.Loader.readCollectionElements(Loader.java:344)     在org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:299)     在org.hibernate.loader.Loader.doQuery(Loader.java:384)     在org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:203)     在org.hibernate.loader.Loader.loadCollection(Loader.java:1344)     ......还有20个

我通过使用session.get(...)获取事件来创建人物对象并添加事件。对于多对多关系,在将每个对象添加到人的事件列表之后,我正在进行其他操作并将事件对象中的人员添加到参与者列表并抛出异常。非常感谢任何有用或指导!

我使用SQL Server 2008作为数据库。

1 个答案:

答案 0 :(得分:1)

尝试更改jdbc驱动程序包,可以使用jtds-1.2.jar,并将驱动程序类设置为net.sourceforge.jtds.jdbc.Driver