Hibernate @OneToOne с суперклассом, извлекает только поля суперкласса при соединении - PullRequest
1 голос
/ 25 октября 2011

Я отобразил мою иерархию наследования в Hibernate, используя столбцы InheritanceType.Single_Table и дискриминатор, чтобы различать разные объекты.Все подклассы суперкласса хранят свои поля во вторичных таблицах.В качестве примера:

@MappedSuperclass
public abstract class Base
{
   @Id 
   private String id;

   @Version
   private long version;
}

@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "type", discriminatorType = DiscriminatorType.STRING) 
public class Parent extends Base
{
    @Column(nullable=false)
    private BigDecimal value;
}

@Entity
@DiscriminatorValue("child1")
@SecondaryTable(name = "Child1")
public class Child1 extends Parent
{
     @Column(table="Child1")
     private String name;
}

@Entity
@DiscriminatorValue("child2")
@SecondaryTable(name = "Child2")
public class Child2 extends Parent
{
     @Column(table="Child2")
     private String name2;
} 

Теперь у меня есть объект, который имеет отношение @OneToOne с классом Parent.Этой сущности нужно работать только с полем значения из родительского класса.Ему никогда не понадобится работать с полями из любого подкласса Parent

@Entity
public class AnotherEntity extends Base
{
    @JoinColumn(name="parentId")
    @OneToOne(fetch=FetchType.Lazy, optional=true, targetEntity=Parent.class)
    private Parent parent;
 }

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

Например, это тип запроса, который я вижу:

Hibernate: 
select
    parent.id as id3_0_,
    parent_.version as version3_0_,
    parent.name1 as name110_3_0_,
    parent.name2 as name24_3_0_,
    parent.type as type3_0_ 
from
    Parent parent0_ 
left outer join
    Child1 parent0_2_ 
        on parent0_.id=parent0_2_.id 
left outer join
    Child2 parent0_3_ 
        on parent0_.id=parent0_3_.id 

Я не понимаюпочему Hibernate решает выбрать надмножество всех свойств, определенных в подклассах Parent, и объединить все вторичные таблицы?Я мог бы понять, как он присоединяется к вторичной таблице для сущности, определяемой значением дискриминатора родительского объекта, на который ссылаются, но в остальном я запутался.

Мой вопрос заключается в том, как мне выполнить требование о наличии только полейиз класса Parent, загруженного при извлечении отношения Parent в классе AnotherEntity?

Спасибо.

1 Ответ

4 голосов
/ 25 октября 2011

Вторичная таблица обычно используется для сопоставления содержимого одного объекта двум таблицам. Он не допускает отложенной выборки с использованием стандартных аннотаций JPA. Вы можете использовать проприетарную аннотацию Hibernate, чтобы загрузить ее, используя отдельный выбор, и только при необходимости. Смотри http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html_single/#mapping-declaration-join:

fetch: если установлено значение JOIN, по умолчанию Hibernate будет использовать внутреннее соединение извлечь вторичную таблицу, определенную классом или его суперклассами и внешнее соединение для вторичной таблицы, определенной подклассом. Если установлено SELECT, тогда Hibernate будет использовать последовательный выбор для вторичного таблица, определенная для подкласса, которая будет выдана, только если строка перевернется для представления экземпляра подкласса. Внутренние соединения будут по-прежнему использоваться для извлечения вторичного объекта, определенного классом и его суперкласс.

Поэтому установка атрибута fetch аннотации Hibernate @Table на SELECT будет делать то, что вы хотите: будет добавлено дополнительное предложение select для выбора значений только из соответствующей вторичной таблицы.

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

...