java - Hibernate 在访问关联实体的 id 时生成 SQL 查询

标签 java hibernate orm proxy lazy-loading

我有看起来像这样的 Hibernate 实体(省略了 getter 和 setter):

@Entity
public class EntityA {
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "parent_id")
    private EntityB parent;
}

@Entity
public class EntityB extends SuperEntity {
    @OneToMany(mappedBy = "parent")
    @Fetch(FetchMode.SUBSELECT)
    @JoinColumn(name = "parent_id")
    private Set<EntityA> children;
}

@MappedSuperclass
public class SuperEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id")
    private long itemId;
}

当我查询 EntityA 时,它加载正常,父关联被 Hibernate 代理替换(因为它是惰性的)。如果我想访问 parent 的 ID,我执行以下调用:

EntityA entityA = queryForEntityA();
long parentId = entityA.getParent().getItemId();

据我所知,调用不应该往返于数据库,因为 Id 存储在 EntityA 表中,代理应该只返回该值。但是,在我的例子中,这会生成一条 SQL 语句,该语句获取 EntityB,然后才返回 Id。

我该如何调查问题?这种不正确行为的一些可能原因是什么?

最佳答案

As I understand that call should NOT make a roundtrip to the database, as the Id is stored in the EntityA table, and the proxy should only return that value.

使用属性访问类型。您遇到的行为是字段访问类型的“限制”。以下是 Emmanuel Bernard 的解释:

That is unfortunate but expected. That's one of the limitations of field level access. Basically we have no way to know that getId() indeed only go and access the id field. So we need to load the entire object to be safe.

所以把你的代码改成:

@Entity
public class EntityA {
    private EntityB parent;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "parent_id")
    public EntityB getParent() {
        return parent; 
    }
    ...
}

@MappedSuperclass
public class SuperEntity {
    private long itemId;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id")
    public long getItemId() { 
        return itemId;
    }
    ...
}

相关问题

引用资料

关于java - Hibernate 在访问关联实体的 id 时生成 SQL 查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3736818/

相关文章:

java - 让JSP登录表单更安全

java - Hibernate映射一对多关系:Parent's PK to Child's FK

java - Hibernate 不断在不同位置寻找配置文件

java - Eclipse Checkstyle vs Formatter vs Cleanup?

java - 如何将 JSON (org.jooq.JSON) 转换为 Java 对象 (POJO)

java - 最快和优化的方式来读取 xml

java - Quarkus Panache Hibernate : How to clear the cache, 使实体世界与数据库状态匹配?

java - JPA 2 : How many methods are allowed in one entity with @Prepersist annotation?

ios - DBAccess:提交不起作用

java - @SecondaryTable 的 Hibernate 映射和继承问题