@ElementCollection Java Persistence (Hibernate) вызывает загрузку дубликатов - PullRequest
11 голосов
/ 19 июля 2011

При использовании @ElementCollection, load all загружает несколько экземпляров объекта. Более конкретно, он загружает один экземпляр для каждого элемента в collectionOfStrings.

Например, для базы данных с одним экземпляром MyClass с collectionOfStrings.size () == 4, вызов для загрузки всех значений MyClass вернет список размера 4 (все один и тот же объект) вместо одного объекта.

Есть ли чистый и простой способ решить эту проблему или ожидается поведение?

// Parent class is a @MappedSuperclass which may or may not be relevant to the issue
@Entity
public class MyClass extends ParentClass {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    @ElementCollection(fetch=FetchType.EAGER)
    @IndexColumn(name="indexColumn")
    private List<String> collectionOfStrings;

    // other instance variables, constructors, getters, setters, toString, hashcode and equals
}

public class MyClassDAO_Hibernate extends GenericHibernateDAO<MyClass, Long> implements MyClassDAO {

    @Override
    public List<MyClass> loadAll() {
        List<MyClass> entityList = null;
        Session session = getSession();
        Transaction trans = session.beginTransaction();
        entityList = findByCriteria(session);
        trans.commit();
        return entityList;
    }

}

protected List<T> findByCriteria(Session session, Criterion... criterion) {
    Criteria crit = session.createCriteria(getPersistentClass());
    for (Criterion c : criterion) {
        crit.add(c);
    }
    return crit.list();
}

MyClassDAO myClassDAO = new MyClassDAO_Hibernate(); // in reality, implementation type is determined with a Factory
...
List<MyClass> myClassInstances = myClassDAO.loadAll();

Спасибо, HeavyE

Редактировать: добавлен вызов findByCriteria.

Ответы [ 3 ]

8 голосов
/ 20 июля 2011

Я не уверен, является ли это ошибкой или допустимым поведением, но это можно исправить, применив DISTINCT_ROOT_ENTITY преобразователь результата:

protected List<T> findByCriteria(Session session, Criterion... criterion) {
    Criteria crit = session.createCriteria(getPersistentClass());
    for (Criterion c : criterion) {
        crit.add(c);
    }
    crit.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
    return crit.list();
}
3 голосов
/ 11 февраля 2012

Это наблюдается только тогда, когда коллекция извлекается с нетерпением.Hibernate преобразует это отображение аннотации в запрос внешнего соединения, который вызывает кратные значения в списке корневых элементов для каждого связанного элемента collectionOfString.

См. Тикет HHH-6783 в средстве отслеживания проблем Hibernate ORMэто точная проблема.И, видимо, нет решения.: - (

Ссылка на Hibernate FAQ , которая касается проблем с внешним объединением, также приведена здесь.

Я имею дело с точно такой же проблемой. Использование@ElementCollection имеет смысл в моем случае, но не за счет проверки всех моих реализаций уровня доступа к данным. Что делать?

2 голосов
/ 19 июля 2011

Это правильное поведение Списка.Список допускает дублирование объектов, и именно поэтому вам нужен индексированный столбец.

Это общий тип коллекции, который может отображаться с помощью Hibernate:

Set - это коллекция, в которой ни один элемент не встречается более одного раза.По моему опыту, это наиболее распространенный тип постоянных коллекций.

Сумка - это набор, в котором предметы могут встречаться более одного раза: они очень неэффективны, потому что в спящем режиме не могут определить, какие предметы вы положилив него те же, что и в нем (при условии, что они равны), поэтому необходимо удалить всю коллекцию и повторно сохранить ее из памяти.

Список является индексированныммешок.Индекс позволяет hibernate знать, является ли конкретный объект в памяти тем же, что и эквивалентный объект в БД, поэтому полное удаление / повторная вставка не требуется.

Карта это как список, за исключением того, что индекс не должен быть вычисляемым (обычно последовательным) целым числом, это может быть что угодно, даже другой объект.

Так что в вашем случае я рекомендую вам использовать Set.

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