Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java EE (J2EE) и Spring > Проблема получения объектов в Hibernate


Автор: afe 3.9.2007, 14:55
Доброго времени суток, очень надеюсь на вашу помощь в разрешении проблемы, которая занимает мое внимание уже несколько дней.


Есть 2 таблицы regions и cities (отношение многие-к-одному), вот маппинги для них:

Код


<hibernate-mapping>
    <class name="City" table="CITIES">
        <id name="id" column="CITY_ID">
            <generator class="native"/>
        </id>
        <property name="name" column="NAME" not-null="true"/>

        <many-to-one name="region"
            class="Region"
            column="REGION_ID"
            outer-join="true"/>
    </class>
</hibernate-mapping>


Код

<hibernate-mapping>
    <class name="Region" table="REGIONS">
        <id name="id" column="REGION_ID">
            <generator class="native"/>
        </id>
        <property name="name" column="NAME" not-null="true"/>

        <set name="cities" lazy="true" cascade="save-update" inverse="true">
            <key column="REGION_ID" not-null="true"/>
            <one-to-many class="City"/>
        </set>

    </class>
</hibernate-mapping>


Классы Region и City:

Код

public class Region extends BaseObject {

    private String name = "";

    private List<City> cities;

    public Region() {
        super();
    }

    public void setName(String Name) {
        name = Name;
    }

    public String getName() {
        return name;
    }

    public List<City> getCities() {
        return cities;
    }

    public void setCities(List<City> cities) {
        this.cities = cities;
    }
}



Код

public class City extends BaseObject {

    private String name = "";

    private Region region;


    public City() {
        super();
    }

    public void setName(String Name) {
        name = Name;
    }

    public String getName() {
        return name;
    }

    public Region getRegion() {
        return region;
    }

    public void setRegion(Region region) {
        this.region = region;
    }
}



Делаю следующие действия: добавляю несколько записей в таблицу regions, затем пытаюсь извлечь все записи из нее с использованием Criteria.  Все отлично работает, если в конфиге хибернейта указан флажок создания структуры базы заново(<property name="hbm2ddl.auto">create</property>). Если же проделывать те же операции, но схему базы не создавать, то при попытке извлечения списка всех регионов вываливается эксепшн org.hibernate.PropertyAccessException: IllegalArgumentException occurred while calling setter of  domain.Region.cities.

Есть глобальная разница в инициализации персистентных объектов, создании внутренних хибернейтовских структур при применении hbm2ddl.auto=create и без? Есть ли идеи как побороть эксепш? Буду очень признателен. Если нужно, для детализации проблемы, могу выложить весь стек-трэйс и код получения объектов...


Автор: boevik 3.9.2007, 21:47
А что указано вместо create?
Я указал update, и у меня вроде всё работает.

Автор: afe 4.9.2007, 09:52
C update то же самое..

Ребят,  ну может есть еще идеи? Пример же тривиальный..и решение наверняка где-то на поверхности, может есть хоть предложения/идеи в какую сторону глянуть? 

Автор: tux 4.9.2007, 10:23
Цитата(afe @  4.9.2007,  09:52 Найти цитируемый пост)
Ребят,  ну может есть еще идеи?

Есть. Выкладывай стэктрейс и код.

Автор: afe 4.9.2007, 10:50
Эксепшены:

Код

    at org.hibernate.property.BasicPropertyAccessor$BasicSetter.set(BasicPropertyAccessor.java:104)
    at org.hibernate.tuple.entity.AbstractEntityTuplizer.setPropertyValues(AbstractEntityTuplizer.java:337)
    at org.hibernate.tuple.entity.PojoEntityTuplizer.setPropertyValues(PojoEntityTuplizer.java:200)
    at org.hibernate.persister.entity.AbstractEntityPersister.setPropertyValues(AbstractEntityPersister.java:3566)
    at org.hibernate.engine.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:129)
    at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:854)
    at org.hibernate.loader.Loader.doQuery(Loader.java:729)
    at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:236)
    at org.hibernate.loader.Loader.doList(Loader.java:2220)
    at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2104)
    at org.hibernate.loader.Loader.list(Loader.java:2099)
        at org.hibernate.loader.criteria.CriteriaLoader.list(CriteriaLoader.java:94)
        at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1569)
    at org.hibernate.impl.CriteriaImpl.list(CriteriaImpl.java:283)
    at com.si.hermes.dao.hibernateimpl.BaseDAOImpl.findByCriteria(BaseDAOImpl.java:99)
    at com.si.hermes.dao.hibernateimpl.BaseDAOImpl.findAll(BaseDAOImpl.java:59)
    at com.si.hermes.services.hibernateimpl.RegionServiceImpl.getAllRegions(RegionServiceImpl.java:118)
    at com.si.hermes.services.TestRegionService.testUpdateRegion(Unknown Source)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at com.si.hermes.services.ServicesTestRunner.main(Unknown Source)



Код с затаившимся багом smile :

Код


public class RegionServiceImpl implements RegionService {

...

public List<Region> getAllRegions() {
        RegionDAO regionDAO = DAOFactory.DEFAULT.getRegionDAO();
        return regionDAO.findAll();
    }

...



Код


public class BaseDAOImpl<T, ID extends Serializable> {

    private Class<T> persistentClass;

    private Session session;

    public BaseDAOImpl(Class<T> persistentClass, Session session)
    {
        this.persistentClass = persistentClass;
        this.session = session;
    }

    protected Session getSession() {
        return session;
    }

    public Class<T> getPersistentClass() {
        return persistentClass;
    }

    @SuppressWarnings("unchecked")
    public T findById(ID id, boolean lock) {
        Object entity;

        try{
            if (lock)
         entity = getSession().load(getPersistentClass(), id, LockMode.UPGRADE);
        else
                 entity = getSession().load(getPersistentClass(), id);

        } catch(ObjectNotFoundException e) {
            return null;
        }

        return (T) entity;
    }

    public T findById(ID id) {
        return findById(id, false);
    }

    @SuppressWarnings("unchecked")
    public List<T> findAll() {
        return findByCriteria();
    }

    @SuppressWarnings("unchecked")
    public List<T> findByExample(T exampleInstance) {
        return findByCriteria(Example.create(exampleInstance));
    }

    @SuppressWarnings("unchecked")
    public T makePersistent(T entity) {
        getSession().saveOrUpdate(entity);//
        return entity;
    }

    public void makeTransient(T entity) {
        getSession().delete(entity);
    }

    public Set<T> listToSet(List<T> listT) {
        Set<T> resT = new LinkedHashSet<T>();
        for (T t : listT) {
            resT.add(t);
        }
        return resT;
    }

    
    @SuppressWarnings("unchecked")
    protected List<T> findByCriteria(Criterion... criterion) {
        Criteria crit = session.createCriteria(getPersistentClass());
        for (Criterion c : criterion) {
            if (c != null) crit.add(c);
        }
        return crit.list();
    }

}

Автор: tux 4.9.2007, 11:18
В твоих экспепшнах эксепшна нет ни одного, приводи полный лог. Из того, что ты привел можно понять только то, что у тебя есть Hibernate.

Автор: afe 4.9.2007, 12:53
Цитата(tux @ 4.9.2007,  11:18)
В твоих экспепшнах эксепшна нет ни одного, приводи полный лог. Из того, что ты привел можно понять только то, что у тебя есть Hibernate.

Нет больше ничего. Это полный лог. Венчается он эксепшеном, который был приведен выше...привожу еще раз:
12:42:34,829 ERROR main BasicPropertyAccessor:set:94 - IllegalArgumentException in class: com.si.hermes.domain.Region, setter method of property: cities
12:42:34,845 ERROR main BasicPropertyAccessor:set:98 - expected type: java.util.List, actual value: org.hibernate.collection.PersistentSet

Автор: tux 4.9.2007, 13:37
Цитата(afe @  4.9.2007,  12:53 Найти цитируемый пост)
Нет больше ничего. Это полный лог.

Это не полный лог.

У тебя тип данных для атрибута cities не совпадает в коде и в маппинге. Поменяй либо тип в коде на Set, либо в маппинге на list.

Автор: afe 4.9.2007, 13:46
Ну это видно, что Hibernate ругается на несовпадение типов...это по логу видно...но вопрос был в том, что все хорошо работает, если схема создается заново, почему-то тогда нет проблемы в приведении Set к List...
И еще, не выбираются из базы именно коллекции регионов...один регион выбирается..но у него тоже есть набор городов..должно не работать ведь и в этом случае...а не выборочно так...

Автор: tux 4.9.2007, 21:34
Несколько поразмыслив могу вывести следуюшее. Зависимость такого поведения от проперти hbm2ddl.auto заключается только в том, что в этом случае Hibernate пересоздает таблицы. Естественно, они при этом оказываются пустыми. Вот это и есть ключевое слово - пустые. По запросу Hibernate не возвращает тебе ни одного объекта региона, и, как следствие, не строит ни одного сета с городами для регионов. Исключение вываливается как раз при построении списка городов, но поскольку списка нет, то и дело до этого не доходит. Поэтому исключение вываливается только тогда, когда hbm2ddl.auto=false, а в таблице регионов есть какие-то записи. В общем, правь маппинги.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)