Использование нескольких списков в Hibernate - PullRequest
2 голосов
/ 11 февраля 2012

У меня есть класс Person, сопоставленный с таблицей PERSON, и класс Address, сопоставленный с таблицей ADDRESS.Я хочу, чтобы у каждого Person было двух списков Address es: homeAddresses и officeAddresses.Таблица ADDRESS имеет одно поле внешнего ключа, PERSONID, для обоих случаев, но имеет два отдельных поля индекса списка: home_add_idx для записей, принадлежащих homeAddresses, и off_add_idx для записей, принадлежащихв officeAddresses.Для любой данной записи ADDRESS одно из этих полей индекса списка будет NULL.Все это прекрасно работает при вставке, но когда я пытаюсь получить записи, я получаю исключение, «столбец нулевого индекса для коллекции».(Полная трассировка стека ниже.)

Как я могу это сделать?

Person.java:

public class Person implements Serializable {
    private String personId;
    private String personName;
    private List<Address> homeAddresses = new ArrayList<Address>();
    private List<Address> officeAddresses = new ArrayList<Address>();

    public String getPersonId() { return personId; }
    public void setPersonId(String s) { personId = s; }
    public String getPersonName() { return personName; }
    public void setPersonName(String s) { personName = s; }
    public List<Address> getHomeAddresses() { return homeAddresses; }
    public void setHomeAddresses(List<Address> L) { homeAddresses = L; }
    public List<Address> getOfficeAddresses() { return officeAddresses; }
    public void setOfficeAddresses(List<Address> L) { officeAddresses = L; }
}

Address.java:

public class Address implements Serializable {
    private String id;
    private String houseNo;
    // [SNIP - street, city, country]
    private String postalCode;

    public String getId() { return id; }
    public void setId(String s) { id = s; }
    public String getHouseNo() { return houseNo; }
    public void setHouseNo(String s) { houseNo = s; }
    // [SNIP - getters for street, city, country]
    public String getPostalCode() { return postalCode; }
    public void setPostalCode(String s) { postalCode = s; }
}

Person.hbm.xml:

<hibernate-mapping>
<class name="com.nadhi.list.test.Person" table="PERSON">
    <id name="personId" type="java.lang.String">
        <column name="PERSONID" />
        <generator class="assigned" />
    </id>
    <property name="personName" type="java.lang.String">
        <column name="PERSONNAME" />
    </property>
    <list name="homeAddresses" inverse="false" table="ADDRESS" lazy="false" cascade="all">
        <key>
            <column name="PERSONID"/>
        </key>
       <list-index column="home_add_idx"></list-index>
        <one-to-many class="com.nadhi.list.test.Address" />
    </list>
    <list name="officeAddresses" inverse="false" table="ADDRESS" lazy="false" cascade="all">
        <key>
            <column name="PERSONID"/>
        </key>
       <list-index column="off_add_idx"></list-index>
        <one-to-many class="com.nadhi.list.test.Address" />
    </list>
</class>
</hibernate-mapping>

Address.hbm.xml:

<hibernate-mapping>
<class name="com.nadhi.list.test.Address" table="ADDRESS">
    <id name="id" type="java.lang.String">
        <column name="ID" />
        <generator class="assigned" />
    </id>
    <property name="houseNo" type="java.lang.String">
        <column name="HOUSENO" />
    </property>
    <!-- [SNIP - mappings for street, city, country] -->
    <property name="postalCode" type="java.lang.String">
        <column name="POSTALCODE" />
    </property>
</class>
</hibernate-mapping>

Когда я вставляю данные, я вставляю отдельный домашний и офисный адрес для одного и того же лица.Вставляет правильно.Однако, когда я пытаюсь получить объект Person, я получаю следующее исключение:

org.hibernate.HibernateException: null index column for collection: com.nadhi.list.test.Person.officeAddresses
at org.hibernate.persister.collection.AbstractCollectionPersister.readIndex(AbstractCollectionPersister.java:770)
at org.hibernate.collection.PersistentList.readFrom(PersistentList.java:402)
at org.hibernate.loader.Loader.readCollectionElement(Loader.java:1156)
at org.hibernate.loader.Loader.readCollectionElements(Loader.java:774)
at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:622)
at org.hibernate.loader.Loader.doQuery(Loader.java:829)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:274)
at org.hibernate.loader.Loader.loadCollection(Loader.java:2166)
at org.hibernate.loader.collection.CollectionLoader.initialize(CollectionLoader.java:62)
at org.hibernate.persister.collection.AbstractCollectionPersister.initialize(AbstractCollectionPersister.java:627)
at org.hibernate.event.def.DefaultInitializeCollectionEventListener.onInitializeCollection(DefaultInitializeCollectionEventListener.java:83)
at org.hibernate.impl.SessionImpl.initializeCollection(SessionImpl.java:1863)
at org.hibernate.collection.AbstractPersistentCollection.forceInitialization(AbstractPersistentCollection.java:479)
at org.hibernate.engine.StatefulPersistenceContext.initializeNonLazyCollections(StatefulPersistenceContext.java:900)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:279)
at org.hibernate.loader.Loader.doList(Loader.java:2533)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2276)
at org.hibernate.loader.Loader.list(Loader.java:2271)
at org.hibernate.loader.criteria.CriteriaLoader.list(CriteriaLoader.java:119)
at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1716)
at org.hibernate.impl.CriteriaImpl.list(CriteriaImpl.java:347)
at org.hibernate.impl.CriteriaImpl.uniqueResult(CriteriaImpl.java:369)
at com.nadhi.list.test.Main.getPerson(Main.java:113)
at com.nadhi.list.test.Main.main(Main.java:36)

В базе данных я вижу, что для домашнего адреса индекс столбца офисного адреса пуст;а для служебного адреса индекс столбца домашнего адреса пуст.Но разве этого не ожидается?Что мне нужно сделать, чтобы получить данные правильно?

1 Ответ

2 голосов
/ 11 февраля 2012

Я думаю, вам нужно заменить поле внешнего ключа ADDRESS.PERSONID двумя отдельными полями внешнего ключа & mdash; один для домашних адресов, один для служебных адресов.

Поля списка индексов, вы можете оставить их как есть, или вы можете объединить их в одно поле, или вы можете полностью удалить их и использовать <bag> вместо <list> отображения. (Очевидно, что последний подход хорош только в том случае, если вас не волнует порядок адресов в списке; я не знаю, так ли это.)

Когда вы думаете об этом & mdash; имеет смысл, что столбец списка-индекса не выполняет то, что вы хотите. Этот столбец используется только для списков (не наборов и сумок), поэтому он не может быть очень универсальным способом указать, к какой коллекции принадлежит запись. Поэтому имеет смысл, что он используется только для указания списка-индекса для записи, которая уже была определена как принадлежащая правильной коллекции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...