当前位置: 首页 > 面试题库 >

访问关联实体的ID时Hibernate生成SQL查询

东郭鸿福
2023-03-14
问题内容

我有一些看起来像这样的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代理(因为它是惰性的)代替了。如果要访问父母的ID,请执行以下调用:

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

据我了解,该调用不应往返于数据库,因为Id存储在EntityA表中,并且代理应仅返回该值。但是,在我的情况下,这会生成一条SQL语句,该语句将提取EntityB并仅返回ID。

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


问题答案:

据我了解,该调用不应往返于数据库,因为Id存储在EntityA表中,并且代理应仅返回该值。

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

那是不幸的,但可以预料的。这是字段级别访问的限制之一。基本上,我们没有办法知道getId()实际上只能访问id字段。因此,为了安全起见,我们需要加载整个对象。

因此,将代码更改为:

@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;
    }
    ...
}

参考文献

  • 在字段上使用注释时,在getId-call上加载的代理
  • proxy getId =>为什么生成sql!
  • HHH-3718(如果可以解决此问题)


 类似资料:
  • 问题内容: 我有一个连接到另一个的Hibernate实体:。在数据库中,我有一列在上具有外键约束。假设我正在延迟加载,那么当我加载的实例时,我希望能够在不引起表查找的情况下进行访问。 我希望返回的代理能够完成请求,因为它已经从列中加载了孩子的ID 。但是,我在桌上看到另一个查询。 为什么需要这个额外的查询,我该如何避免呢?在这种情况下,我只对外键ID感兴趣,而不希望加载整个行。 类: 表格: 问题

  • 我有一个与多个代码/标签实体关联的主jpa实体。 当我使用时,我可以看到Hibernate正在创建一个带有多个“left join”的SQL查询,这是我应该手工完成的。 有没有办法做到这一点,怎么做?

  • 我一直在理解Laravel查询生成器和纯SQL之间的融合。 我有2张桌子: user:包含具有主键的用户 User_Action:这是一个表,其中包含由和动作的组成的PRIMARYs记录。 ex: 使用者 用户操作 我的需要: 现在我想检索一个用户列表,其中包含每个用户的最新操作。因此,我只需要在从到的连接中获取一行,并且这一行必须是具有最新日期时间的一行。我的前任也是如此;我只想获取dateti

  • 我有两个实体,我想保存到数据库中,付款和付款项。付款可以有更多的付款项目。 主要实体: 第二个实体: 所以,我用1个PaymentItem填充一个Payment,并尝试保存它。请注意,Payment没有自动生成的ID,我从其他地方获取ID并手动设置。 现在,当我试图保存它时,Hibernate会转到数据库,查看是否存在一个现有条目及其项(不是,数据库是空的)。 我知道这一点,因为我打开了Hiber

  • 子类: 我将它保存在我的DAO中,如下所示: 当我试图保存对象ship,它会给我以下错误: