意外的 JavaAssistLazyInitializer 即使使用 INNER JOIN FETCH QUERY



我需要将一个名为tabPremissa的嵌套字段提取到Premissa模型中,但我无法处理JavaAssistLazyInitializer。

我已经试过了

  1. unproxy the lazy field with ((HibernateProxy( entity(.getHibernateLazyInitializer((.getImplementation((
  2. Jpa存储库方法上的内部连接获取

代码如下:

前提.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;
}

亚分类前米萨.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 ";

休眠日志

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

编辑

我直接在数据库中搜索了一个示例,其中 Premissap有一个 SubcategoriaPremissas 并运行以下命令:

  1. s = subCategoriaPremissaRepository.findOne(1883L(;

  2. p = premissaRepository.findOne(9019L(;

在这种情况下,每个数据都正确加载,s 位于 p 中。 但是,如果执行顺序发生更改,则在调试时将 s 视为 JavaAssistLazyInitializer

您最有可能遇到的问题是 Hibernate 无法将获取的状态合并到您的第一级缓存(即您的EntityManager/Session中已经存在的现有对象中。因此,如果您以某种方式将实体代理放入您的EntityManager/Session,后续查询是否获取该实体并不重要,结果将始终是代理。Hibernate必须遵守JPA规范,该规范大致上说,具有相同主键的托管实体在EntityManager/Session中只能存在一次对象身份。

这是IMO避免OSIV(打开会话视图(反模式的最大原因之一,但很少被谈论。Hibernate可能会在某个时候解决这个问题,但现在,这就是它的行为方式。

因此,您现在可以做的一件事是调用EntityManager.clear()来清除整个第一级缓存或以有问题的实体作为参数的EntityManager.detach(),以从第一级缓存中删除它。

最新更新