hibernate @DiscriminatorValue не относится к ассоциациям - PullRequest
2 голосов
/ 09 ноября 2009

У меня есть следующая иерархия наследования.

@Entity
@Table(FRUIT)
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColum(name="FRUIT_TYPE",discriminatorType=STRING)
public class Fruit {
..
@Id
private FruitId id;
...
}

@DiscriminatorValue("APPLE")
public class Apple extends Fruit {
...
@ManyToOne
private FruitBowl bowl; //this association is only present in the subclass

...
}

class FruitBowl .. {
...
        @OneToMany(fetch = FetchType.LAZY, mappedBy = "bowl")
    @IndexColumn(name="POSITION",base = 1) 
        List<Apple> apples;
...

Когда я делаю session.load(Apple.class,...), он добавляет FRUIT_TYPE = 'APPLE' к запросу выбора. Но если я делаю выбор на FruitBowl (который имеет отношение 1: m к Apple), запрос на выборку на Apple не содержит FRUIT_TYPE = 'APPLE'. Почему это происходит? Как мне исправить проблему?

Запрос - Запрос для FruitBowl

select fruitbowl0_.BOWL_ID as BOWL1_1_0_ from FRUITBOWL fruitbowl0_ where fruitbowl0_.BOWL_ID=? 

- Запрос Fruit для получения яблок (записи с fruit_type = 'A') - но оно не включает это условие

select apples0_.ENTITY_ID as ENTITY3_1_, apples0_.POS as POS1_, apples0_.POS as POS0_0_, apples0_.ENTITY_ID as ENTITY3_0_0_, apples0_.COLOR as COLOR0_0_ from FRUIT apples0_ where apples0_.ENTITY_ID=?

Ответы [ 2 ]

4 голосов
/ 17 октября 2012

Вы можете добавить @DiscriminatorOptions(force=true) к вашему классу "Fruit", что заставит hibernate использовать дескриптор при запросе этих отношений.

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

0 голосов
/ 09 ноября 2009

(отредактировано на основе сопоставлений / запросов SQL / примеров данных, размещенных в вопросе / комментариях).

Ваше сопоставление указывает, что FruitBowl содержит коллекцию Apple с. Поэтому Hibernate не будет добавлять условие значения дискриминатора к запросу загрузчика для этой коллекции, поскольку заранее знает, что могут быть возвращены только Apple экземпляров.

Запросы SQL, которые вы отправили, делают именно это - загружают FruitBowl по идентификатору и затем загружают apples коллекцию для этого FruitBowl экземпляра. Проблема связана с данными, которые вы разместили:

 fruit_type entity_id  pos  color
     A         1        1   white
     B         1        2   blue

Есть еще один экземпляр Fruit со значением дискриминатора B - Banana? :-) - имеет тот же entity_id и, таким образом, извлекается как часть запроса на загрузку коллекции. Вопрос здесь - как это было вставлено во-первых? Есть два возможных сценария:

  1. Banana является подклассом Apple. В этом случае все правильно, он должен быть возвращен как часть apples collection.
  2. Вы вставили вышеуказанные данные вручную для целей тестирования. Эти данные являются недопустимыми с точки зрения Hibernate - они будут вставлены НИКОГДА самой Hibernate; это в свою очередь приводит к поведению, которое вы видите. Вам нужно либо избавиться от строки Banana, либо удалить ее entity_id (тем самым удалив ее из коллекции apples).

Вообще говоря, смешивать иерархию объектов и элементы коллекции в одной таблице не очень хорошая идея. Попробуйте переопределить иерархию как «таблица на подкласс» или сопоставить коллекцию apples с использованием @JoinTable - обратите внимание, что в последнем случае она станет однонаправленной.

...