带有二级缓存的 Hibernate 6.2+ 忽略了预先加载

Hibernate 6.2+ with 2nd level cache ignores eager loading

提问人:user3612610 提问时间:11/9/2023 更新时间:11/10/2023 访问量:18

问:

我有带有 hibernate 6.2.13.Final 和 jcache/ehcache 用于二级缓存的项目:

<dependency>
    <groupId>org.hibernate.orm</groupId>
    <artifactId>hibernate-core</artifactId>
    <version>6.2.13.Final</version>
</dependency>

<dependency>
    <groupId>org.hibernate.orm</groupId>
    <artifactId>hibernate-envers</artifactId>
    <version>6.2.13.Final</version>
</dependency>

<!-- API for 2nd Level Cache -->
<dependency>
    <groupId>org.hibernate.orm</groupId>
    <artifactId>hibernate-jcache</artifactId>
    <version>6.2.13.Final</version>
</dependency>
<!-- Implementation for 2nd Level Cache -->
<dependency>
    <groupId>org.ehcache</groupId>
    <artifactId>ehcache</artifactId>
    <classifier>jakarta</classifier>
    <version>3.10.8</version>
</dependency>

我有实体和缓存。我知道 Eager Loading 是一种反模式,但软件很复杂,目前无法更改。@ManyToOne(fetch = FetchType.EAGER)

@Entity
@Cacheable
@Audited
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class FooType {

    @Id
    @GeneratedValue(generator = "system-uuid")
    @GenericGenerator(name = "system-uuid", strategy = "uuid2")
    @Size(max = 36)
    @Column(length = 36)
    @UserInterface(showInForm = false, showInList = false)
    @Comment("Primary key")
    private String id;

    @Version
    @NotNull
    @UserInterface(showInForm = false, showInList = false)
    @Comment("Version column for optimistic locking")
    private int version;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public int getVersion() {
        return version;
    }

    public void setVersion(int version) {
        this.version = version;
    }
}
@Entity
@Cacheable
@Audited
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Foo {

    @Id
    @GeneratedValue(generator = "system-uuid")
    @GenericGenerator(name = "system-uuid", strategy = "uuid2")
    @Size(max = 36)
    @Column(length = 36)
    @UserInterface(showInForm = false, showInList = false)
    @Comment("Primary key")
    private String id;

    @Version
    @NotNull
    @UserInterface(showInForm = false, showInList = false)
    @Comment("Version column for optimistic locking")
    private int version;
    
    @ManyToOne(fetch = FetchType.EAGER)
    private FooType;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public int getVersion() {
        return version;
    }

    public void setVersion(int version) {
        this.version = version;
    }
    
    public FooType getFooType() {
        return fooType;
    }
    
    public void setFooType(FooType fooType) {
        this.fooType = fooType;
    }
}

当我查询一个条目时,一切都很好。

entityManager.find(Foo.class, id);

但是,当我查询多个条目时,在结果中延迟加载,并且是一个休眠代理对象。FooTypeFoo

final TypedQuery<Foo> fooQuery = entityManager.createQuery("FROM Foo f", Foo.class);
final List<Foo> fooList = fooQuery.getResultList();

休眠 6.2 并禁用了二级缓存

当我停用第二级缓存时,结果按预期急切加载。

<property name="hibernate.cache.use_second_level_cache" value="false" />

Hibernate 6.1 并启用了第二级缓存

当我将 Hibernate 版本更改为 6.1.7.Final 并启用第二级缓存时,结果按预期急切加载。

休眠 6.4.0.CR1

与 6.2 相同的问题

我不确定这是一个错误还是缓存中的预期变化?但是,我在 hibernate 6.2 迁移指南中没有找到任何关于此的内容。我该如何处理这个问题,我需要在启用第二级缓存的情况下加载结果。

Hibernate 缓存 Eager-Loading

评论


答:

0赞 user3612610 11/10/2023 #1

我在 Hibernate 论坛上得到了答案:

仅仅因为您看到正在为关联设置代理对象并不意味着它是延迟加载的。有时,由于其他原因,Hibernate ORM 需要使用代理,但会确保对象作为加载操作的一部分进行初始化。

在 Hibernate 论坛中讨论 Jackson 的提示。