When using standard JPA annotations, you can specify FetchType.LAZY
on non-collection fields (i.e. @ManyToOne
and @OneToOne
). It seems Hibernate internally uses "proxy" fetching in this case. But proxy fetching has its problems with inheritance and I think it is better to use no-proxy fetching in combination with bytecode instrumentation. Unfortunately, Hibernate still requires you either to specify "no-proxy" in the hbm
-file or to use the Hibernate-specific @LazyToOne
annotation.
My question is: does Hibernate support a configuration option to use a no-proxy fetch strategy for all non-collection fields, that are FetchType.LAZY
?
Here is what I need this for: I would like to use only JPA annotations in most cases on the one hand. On the other hand, I'd like to avoid issues with inheritance and lazy fields. And I don't like the idea of wrapping everything in interfaces, because I use DDD in my current project, so I think that no boilerplate garbage should exist in my domain model, only pure business logic.
I have an idea of a poor workaround: by using bytecode modification, I add @LazyToOne
annotation everywhere @ManyToOne
appears. But I would prefer a built-in Hibernate feature, if exists.
Here is (well known) issue with proxy fetching, to make things a bit clearer:
@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;
}
}
prepare:
D d = new D();
C c = new C();
d.setA(c);
em.persist(d);
and fail assertion (in another EM, another transaction):
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);
Here's what I would do to fix the assertions above:
@Entity public class D {
@Id private Integer id;
@ManyToOne(fetch = FetchType.LAZY) @LazyToOne(LazyToOneOption.NO_PROXY)
private A a;
public A getA() {
return a;
}
}
And I don't want the same thing to be enabled by default, without @LazyToOne
annotation.