当前位置: 首页 > 知识库问答 >
问题:

当JOIN FETCH与主ID以外的引用列一起使用时,Hibernate执行多个查询

鲍国兴
2023-03-14

我有以下问题。

每当使用JOIN FETCH子句使用查询调用我的存储库时,Hibernate都会生成一个根本不需要的附加查询。这里的主要问题是,根据相应的数据库结构,两个实体(对应于两个单独的表)应该由与两个实体的ID不同的列连接(即@JoinCol列在实体顺序中表示的“Custerid”(name=“Custerid”,引用的列名称=“Custerid”)”)。

存储库如下所示:

public interface CustomerRepository extends CrudRepository<Customer, Long>{

    Customer findByMsisdn(String msisdn);

    @Query("SELECT c FROM Customer c JOIN FETCH c.orders WHERE c.msisdn =:msisdn")
    Customer getCustomersAndOrdersByMsisdn(@Param("msisdn") String msisdn);
}

每当我调用getCustomersandersbymsisdn方法时,都会生成以下两个查询(当然,我们只希望生成查询1):

--Query1
select
   customer0_.id as id1_0_0_,
   orders1_.id as id1_1_1_,
   customer0_.customerid as customer2_0_0_,
   customer0_.msisdn as msisdn3_0_0_,
   customer0_.status as status4_0_0_,
   orders1_.customerid as customer4_1_1_,
   orders1_.orderid as orderid2_1_1_,
   orders1_.orderstatus as ordersta3_1_1_,
   orders1_.customerid as customer4_1_0__,
   orders1_.id as id1_1_0__ 
from
   customers customer0_ 
   inner join
      orders orders1_ 
      on customer0_.customerid = orders1_.customerid 
where
   customer0_.msisdn =?

--Query2
select
      customer0_.id as id1_0_0_,
      customer0_.customerid as customer2_0_0_,
      customer0_.msisdn as msisdn3_0_0_,
      customer0_.status as status4_0_0_ 
   from
      customers customer0_ 
   where
      customer0_.customerid =?

我的两个实体(为了清楚起见,我在这里使用了getter和setter,它们当然存在于我的代码中)是:

@Entity
@Table(name = "customers")
public class Customer implements Serializable {
    static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;


    @Column(name = "msisdn")
    private String msisdn;

    @Column(name = "status")
    private String status;

    @Column(name = "customerid", unique = true)
    @NaturalId
    private String customerid;

    @OneToMany(mappedBy = "customer", cascade = CascadeType.ALL,fetch = FetchType.LAZY)
    private Set<Order> orders;

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Customer customer = (Customer) o;
        return id == customer.id &&
                msisdn.equals(customer.msisdn) &&
                customerid.equals(customer.customerid);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, msisdn, customerid);
    }
}

@Entity
@Table(name = "orders")
public class Order implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;

    @Column(name = "orderid")
    private int orderid;

    @Column(name = "orderstatus")
    private String orderstatus;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "customerid", referencedColumnName = "customerid")
    private Customer customer;


    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Order orders = (Order) o;
        return id == orders.id &&
                orderid == orders.orderid;
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, orderid);
    }
}

共有1个答案

何聪
2023-03-14

这是绝对正常的,因为连接是使用自然id而不是实体的id进行的。Hibernate使用实体的id而不是定义的自然id来对实体执行操作。

因此,在进行连接时,hibernate需要获取具有自然id的客户的实体。

要了解更多信息,请阅读文章@naturaid–通过Hibernate保存自然ID的好方法?

 类似资料:
  • 我有域类 - 用户、角色、组、组角色 用户域 用户.hbm.xml 我有user_grouprole表作为一个连接表为一个用户和一组分组程序我有user_role表作为一个连接表为一个用户和一组角色 组域 Group.hbm.xml 组角色 GroupRole.hbm.xml 当我尝试使用主类进行测试时,我得到了一个映射错误,比如Hibernate映射错误,比如外键(FK5110401A83989

  • 如何将Restrictions.in与列表字段一起使用? 这是我的模型: 我尝试只获取具有某些功能的组: 但这会返回一个错误: 引起原因:org.hibernate.exception.GenericJDBCExc0019:在索引:: 1缺少IN或OUT参数org.hibernate.exception.internal.在org.hibernate.engine.jdbc.spi.SqlExce

  • 我有一个带有Spring(5.7.2)Web/Security的REST API项目。 我只有一个表,它包含一个id和一个名称。 当我删除光盘时,我的DiscsService会 当我需要插入或更新时,我会: 我了解到,当您希望在同一事务中使用值(提交之前)时,将使用,并且将同步并清空SQL缓存。 在我的例子中,我看到我在数据库中插入/更新或删除了值。 我应该使用flush()(我认为不应该),但可

  • 对于时区API-https://docs.oracle.com/javase/7/docs/API/java/util/TimeZone.html#getTimeZone(java.lang.string),在哪里可以找到可以用作参数的ID列表?

  • 考虑和<代码>雇员< /代码>和<代码>地址< /代码>关系。在和之间有一对一的映射。以下是模型: 现在,当我执行以下HQL查询时,它会在内部生成两个查询。一个取员工,另一个取地址。 由Hibernate生成的SQL查询 因为我使用的是,所以我希望Hibernate只执行一个带有JOIN的查询,一次性获取员工和地址数据。 你知道为什么它要执行两个查询吗?我如何让Hibernate使用join只执行

  • 我希望在一个select请求中运行以下查询: 问题是所有内容都是由单独的多个查询获取的。我只希望团队和团队的球员和每个球员的技能在一个请求中被获取。但是相反,我有多个选择查询来获取每个团队、玩家、每个玩家的统计数据和技能。 以下是与注释一起使用的实体: 游戏实体: 团队实体: 玩家实体: 你能指出所犯的错误吗?我需要一个选择查询来加载游戏,它是团队、团队的球员和每个球员的技能。 编辑1:以下是po