意外的JavaAssistLazyInitializer甚至带有INNER JOIN FETCH查询

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

我已经尝试过

  1. (((HibernateProxy)实体).getHibernateLazyInitializer()。getImplementation()
  2. 代替惰性字段。 JpaRepository方法上的
  3. INNER JOIN FETCH

代码如下:

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,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

编辑

我直接在Premissa p 具有SubcategoriaPremissa s 的数据库中搜索了一个示例,并运行了以下命令:

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

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

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

levisor 回答:意外的JavaAssistLazyInitializer甚至带有INNER JOIN FETCH查询

您最有可能遇到的问题是Hibernate无法将获取的状态合并到一级缓存(也就是EntityManager / Session)中已经存在的现有对象中。因此,如果您以某种方式将实体代理添加到EntityManager / Session中,则后续查询是否获取该实体都没有关系,结果将始终是代理。 Hibernate必须遵守JPA规范,该规范粗略地说,具有相同主键的受管实体必须仅在EntityManager / Session中以对象身份存在一次。

这是IMO避免OSIV(Open-Session-In-View)反模式的最大原因之一,但很少有人提及。 Hibernate可能会在某种程度上解决此问题,但是现在,这是它的行为方式。

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

本文链接:https://www.f2er.com/2956254.html

大家都在问