I need to fetch a nested field called tabPremissa into Premissa model, but I can't handle JavaAssistLazyInitializer.
I Already tried
The code is as follows:
Premissa.java
@Entity
@Table(name = "premissa")
public class Premissa implements Draggable {
@Id
@SequenceGenerator(name = SEQ, sequenceName = SEQ, allocationSize = 1)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = SEQ)
@Column(name = "id")
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "id_subcategoria_premissa", nullable=false)
private SubCategoriaPremissa subCategoriaPremissa;
}
SubCategoriaPremissa.java
@Entity
@Table(name = "subcategoria_premissa")
public class SubCategoriaPremissa implements Draggable {
@Id
@SequenceGenerator(name = SEQ, sequenceName = SEQ, allocationSize = 1)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = SEQ)
@Column(name = "id")
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "id_tab_premissa", nullable=false)
private TabPremissa tabPremissa;
}
@Query
String QUERY_TAB_ORDER_BY_TAB_AND_ORDER = " SELECT P From Premissa P "
+ " INNER JOIN FETCH P.subCategoriaPremissa SCP "
+ " INNER JOIN FETCH SCP.tabPremissa TP "
+ " WHERE TP in :tabs "
+ " ORDER BY SCP.tabPremissa, P.ordem ";
Hibernate log
select
premissa0_.id as id1_70_0_,
subcategor1_.id as id1_85_1_,
tabpremiss2_.id as id1_86_2_,
premissa0_.campo_1 as campo_2_70_0_,
premissa0_.campo_2 as campo_3_70_0_,
premissa0_.campo_3 as campo_4_70_0_,
premissa0_.campo_4 as campo_5_70_0_,
premissa0_.id_centro_custo as id_cent15_70_0_,
premissa0_.considera_zero as consider6_70_0_,
premissa0_.descricao as descrica7_70_0_,
premissa0_.id_empresa as id_empr16_70_0_,
premissa0_.id_grupo_economico as id_grup17_70_0_,
premissa0_.id_clone as id_clone8_70_0_,
premissa0_.logica_totalizador as logica_t9_70_0_,
premissa0_.nome as nome10_70_0_,
premissa0_.ordem as ordem11_70_0_,
premissa0_.id_pai as id_pai18_70_0_,
premissa0_.style_table as style_t12_70_0_,
premissa0_.id_subcategoria_premissa as id_subc19_70_0_,
premissa0_.tipo_operacao_premissa as tipo_op13_70_0_,
premissa0_.unidade_medida as unidade14_70_0_,
subcategor1_.id_clone as id_clone2_85_1_,
subcategor1_.label_1 as label_3_85_1_,
subcategor1_.label_2 as label_4_85_1_,
subcategor1_.label_3 as label_5_85_1_,
subcategor1_.label_4 as label_6_85_1_,
subcategor1_.nome as nome7_85_1_,
subcategor1_.ordem as ordem8_85_1_,
subcategor1_.id_pai as id_pai9_85_1_,
subcategor1_.id_tab_premissa as id_tab_10_85_1_,
tabpremiss2_.id_categoria_premissa as id_categ8_86_2_,
tabpremiss2_.definicao_json as definica2_86_2_,
tabpremiss2_.enum_link_id as enum_lin3_86_2_,
tabpremiss2_.hexa_bg_color as hexa_bg_4_86_2_,
tabpremiss2_.nome as nome5_86_2_,
tabpremiss2_.ordem as ordem6_86_2_,
tabpremiss2_.id_pai as id_pai9_86_2_,
tabpremiss2_.status_edit as status_e7_86_2_
from
premissa premissa0_
inner join
subcategoria_premissa subcategor1_
on premissa0_.id_subcategoria_premissa=subcategor1_.id
inner join
tab_premissa tabpremiss2_
on subcategor1_.id_tab_premissa=tabpremiss2_.id
where
tabpremiss2_.id in (
? , ?
)
order by
subcategor1_.id_tab_premissa,
premissa0_.ordem
EDIT
I searched one example directly on database where Premissa p has a SubcategoriaPremissa s and ran the following commands:
s = subCategoriaPremissaRepository.findOne(1883L);
p = premissaRepository.findOne(9019L);
In this case, every data is loaded properly and s is located in p. However, if the order of execution is changed, s is considered JavaAssistLazyInitializer while debugging
The problem you are most likely having is that Hibernate is unable to merge fetched state into existing objects already present in your first level cache a.k.a. your EntityManager
/Session
. So if you somehow get an entity proxy into your EntityManager
/Session
, it doesn't matter if subsequent queries fetch that entity, the result will always be the proxy. Hibernate must adhere to the JPA specification that roughly says, managed entities with the same primary key must only exist once object-identity-wise in an EntityManager
/Session
.
This is IMO one of the biggest reasons to avoid the OSIV(Open-Session-In-View) anti-pattern, but is rarely talked about. Hibernate might at some point fix this, but for now, this is how it behaves.
So one thing you can do right now is to invoke EntityManager.clear()
to clear the whole first level cache or EntityManager.detach()
with the problematic entity as argument, to remove just that from the first level cache.