При использовании стандартных аннотаций JPA вы можете указать FetchType.LAZY
для полей без сбора (т.е. @ManyToOne
и @OneToOne
). Кажется, Hibernate внутренне использует "прокси" в этом случае. Но выбор прокси-сервера имеет свои проблемы с наследованием, и я думаю, что лучше использовать получение не-прокси в сочетании с инструментами байт-кода. К сожалению, Hibernate по-прежнему требует либо указать "no-proxy" в файле hbm
, либо использовать аннотацию @LazyToOne
для Hibernate.
Мой вопрос: поддерживает ли Hibernate параметр конфигурации, чтобы использовать стратегию выборки без прокси для всех не-коллекционных полей, которые FetchType.LAZY
?
Вот что мне нужно для этого: я хотел бы использовать только аннотации JPA в большинстве случаев, с одной стороны. С другой стороны, я бы хотел избежать проблем с наследованием и ленивыми полями. И мне не нравится идея обертывания всего в интерфейсах, потому что я использую DDD в своем текущем проекте, поэтому я думаю, что в моей модели домена не должно существовать никаких шаблонных мусора, а только чистая бизнес-логика.
У меня есть идея плохого обходного пути: с помощью модификации байт-кода я добавляю @LazyToOne
аннотацию везде @ManyToOne
. Но я бы предпочел встроенную функцию Hibernate, если она существует.
Здесь (хорошо известная) проблема с извлечением прокси, чтобы сделать вещи немного яснее:
@Entity @DiscriminatorColumn("t") @DiscriminatorValue("")
public abstract class A {
@Id private Integer id;
}
@Entity @DiscriminatorValue("B")
public abstract class B extends A {
}
@Entity @DiscriminatorValue("C")
public abstract class C extends A {
}
@Entity public class D {
@Id private Integer id;
@ManyToOne(fetch = FetchType.LAZY) private A a;
public A getA() {
return a;
}
}
подготовить:
D d = new D();
C c = new C();
d.setA(c);
em.persist(d);
и утверждение об ошибке (в другой EM, другая транзакция):
D d = em.createQuery("select d from D d", D.class).getSingleResult();
List<C> cs = em.createQuery("select c from C c", C.class).getResultList();
assert d.getA() instanceof C;
assert d.getA() == cs.get(0);
Вот что я сделал бы, чтобы зафиксировать вышеприведенные утверждения:
@Entity public class D {
@Id private Integer id;
@ManyToOne(fetch = FetchType.LAZY) @LazyToOne(LazyToOneOption.NO_PROXY)
private A a;
public A getA() {
return a;
}
}
И я не хочу, чтобы по умолчанию было включено то же самое, без аннотации @LazyToOne
.