Вопрос по java – Hibernate CollectionOfElements EAGER извлекает дубликаты элементов

38

У меня есть класс с именем SynonymMapping, который имеет коллекцию значений, сопоставленных как CollectionOfElements

@Entity(name = "synonymmapping")
public class SynonymMapping {

    @Id private String keyId;

    //@CollectionOfElements(fetch = FetchType.EAGER)
    @CollectionOfElements
    @JoinTable(name="synonymmappingvalues", joinColumns={@JoinColumn(name="keyId")})
    @Column(name="value", nullable=false)
    @Sort(type=SortType.NATURAL)
    private SortedSet<String> values;

    public SynonymMapping() {
        values = new TreeSet<String>();
    }

    public SynonymMapping(String key, SortedSet<String> values) {
        this();
        this.keyId = key;
        this.values = values;
    }

    public String getKeyId() {
        return keyId;
    }

    public Set<String> getValues() {
        return values;
    }
}

У меня есть тест, в котором я храню два объекта SynonymMapping в базе данных, а затем прошу базу данных вернуть все сохраненные объекты SynonymMapping, ожидая получения двух сохраненных объектов.

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

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

Я думаю, что это связано с соединениями, которые создаются под Hibernate, но я не могу найти однозначного ответа в Интернете.

Может кто-нибудь сказать мне, почему нетерпеливый выбор дублирует объекты?

Благодарю.

Каждый с Исключением & quot; Найдено более одной строки с данным идентификатором & quot; должен знать об этом. Это действительно экономит много часов, не зная, что, черт возьми, происходит не так. Смотрите @ user176668 ответ !! Gotham Llianen

Ваш Ответ

6   ответов
63

Я столкнулся с той же проблемой - когда вы устанавливаете FetchType.EAGER для @CollectionOfElements, Hibernate пытается получить все за один раз, то есть, используя один единственный запрос для каждой записи элемента, связанной с & quot; master & quot; объект. Эта проблема может быть успешно решена за счет запроса N + 1, если вы добавите аннотацию @Fetch (FetchMode.SELECT) в свою коллекцию. В моем случае я хотел иметь объект MediaObject с набором его элементов метаданных (видеокодек, аудиокодек, размеры и т. Д.). Отображение для коллекции metadataItems выглядит следующим образом:

@CollectionOfElements (targetElement = String.class, fetch = FetchType.EAGER)
@JoinTable(name = "mo_metadata_item", joinColumns = @JoinColumn(name = "media_object_id"))
@MapKey(columns = @Column(name = "name"))
@Column (name = "value")
@Fetch (FetchMode.SELECT)
private Map<String, String> metadataItems = new HashMap<String, String>();
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
0

ВместоFetchMode.SELECT с N + 1 запросами лучше использоватьBatchSize e.q.@BatchSize(size = 200).

DISTINCT а такжеCriteria.DISTINCT_ROOT_ENTITY не помогает, если вам нужно получить более 1 ассоциации. Для этого случая посмотрите другие решения:https://stackoverflow.com/a/46013654/548473

0

Я достиг этого с помощью простого добавления

session.createCriteria(ModelClass.class).setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);

Это поможет удалить дубликаты.

29

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

Причина, по которой вы получаете дубликаты, заключается в том, что Hibernate внутренне объединяет ваши корневые таблицы и таблицы коллекций. Обратите внимание, что они действительно являются дубликатами, например за 2 SynonymMappings с 3 элементами коллекции каждый вы получите 6 результатов (2x3), 3 копии каждой сущности SynonymMapping. Таким образом, самый простой обходной путь - это обернуть результаты в набор, тем самым гарантируя, что они уникальны.

Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
6

Я столкнулся с этой проблемой, и я решил ее с помощью

criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);

Это удаляет дубликаты, вызванные объединением дочерних таблиц.

2

Вы можете использовать предложение SELECT DISTINCT (Hibernate Query Language) следующим образом

SELECT DISTINCT synonym FROM SynonymMapping synonym LEFT JOIN FETCH synonym.values

Предложение DISTINCT удаляет дубликаты ссылок в Hibernate.

Хотя и компонент, и коллекция значений-типов имеют свой жизненный цикл, связанный с классом объекта-владельца, вы должны объявить их в предложении select, чтобы получить их. (LEFT JOIN FETCH synonym.values)

Ответ ChssPly76 является другим подходом, но не забывает переопределять равно и метод хэш-кода в соответствии с Set semantic

С уважением,

Error: User Rate Limit Exceeded Rachel

Похожие вопросы