java - Hibernate多实体连接问题,产生额外查询

标签 java sql hibernate join hibernate-criteria

使用 @OneToOne Association (Hibernate 5.2) 连接多个实体时存在 N+1 问题

     @Entity
     @Table(name = "COMMON_CARDS")
     public class CommonCards {

       @Id
       @Column(name = "card_number")
       private String card_number;
       @Column(name = "card_id")
       private String card_id;
       @Column(name = "bank_C")
       private String bankC;
       @Column(name = "centre_Id")
       private String centreId;
       @Column(name = "bank_Id")
       private String bankId;
       @OneToOne(fetch = FetchType.LAZY)
       @JoinColumn(name = "CARD_NUMBER")
       private StipCards stipCards;

       @OneToOne(fetch = FetchType.LAZY)
       @NotFound(action = NotFoundAction.IGNORE)
       @JoinColumn(name = "CARD_NUMBER", insertable = false, updatable = false)
       private CardsExceptions cardsExceptions;

     /*getters and setters*/
     }

     @Entity
     @Table(name = "STIP_CARDS")
     public class StipCards {
       @Id
       @Column(name = "CARD_NUMBER")
       private String card_number;
       @Column(name = "CENTRE_ID")
       private String CENTRE_ID;
       @Column(name = "Expiry_Date_1")
       private String expriryDate1;
       @Column(name = "Expiry_Date_2")
       private String expriryDate2;
       @Column(name = "stat_code_1")
       private String statCode1;
       @Column(name = "stat_code_2")
       private String statCode2;

     /*getters and setters*/
     }

         @Entity
         @Table(name = "CARDS_EXCEPTIONS")
         public class CardsExceptions {
           @Id
           @Column(name = "CARD_NUMBER")
           private String cardNumber;
           @Column(name = "ACTION_CODE")
           private String actionCode;

         /*getters and setters*/
}

这里是从数据库获取记录列表的实现代码

CriteriaBuilder builder = session.getCriteriaBuilder();
    CriteriaQuery<CommonCards> criteria = builder.createQuery(CommonCards.class);
    Root<CommonCards> root = criteria.from(CommonCards.class);
    Join<Object, Object> joinStipCards = (Join<Object, Object>) root.fetch("stipCards", JoinType.INNER);
    Join<Object, Object> joinException = (Join<Object, Object>) root.fetch("cardsExceptions", JoinType.LEFT);

    Predicate predicate = builder.and(root.get("card_id").in(cardIds));
    predicate = builder.and(predicate, builder.and(builder.equal(joinStipCards.get("CENTRE_ID"), root.get("centreId"))));

    criteria.where(predicate);
    List<CommonCards> commonCards = session.createQuery(criteria).getResultList();

    for (CommonCards card : commonCards) {
      System.out.println(card.toString());
    }

这段代码生成两个select语句

第一条 SQL

SELECT commoncard0_.card_number  AS card_number1_5_0_
      ,stipcards1_.CARD_NUMBER   AS CARD_NUMBER1_2_1_
      ,cardsexcep2_.CARD_NUMBER  AS CARD_NUMBER1_1_2_
      ,commoncard0_.bank_C       AS bank_C2_5_0_
      ,commoncard0_.bank_Id      AS bank_Id3_5_0_
      ,commoncard0_.card_id      AS card_id4_5_0_
      ,commoncard0_.CARD_NUMBER  AS CARD_NUMBER1_5_0_
      ,commoncard0_.centre_Id    AS centre_Id5_5_0_
      ,stipcards1_.CENTRE_ID     AS CENTRE_ID2_2_1_
      ,stipcards1_.Expiry_Date_1 AS Expiry_Date_3_2_1_
      ,stipcards1_.Expiry_Date_2 AS Expiry_Date_4_2_1_
      ,stipcards1_.stat_code_1   AS stat_code_5_2_1_
      ,stipcards1_.stat_code_2   AS stat_code_6_2_1_
      ,cardsexcep2_.ACTION_CODE  AS ACTION_CODE2_1_2_
  FROM COMMON_CARDS commoncard0_
 INNER JOIN STIP_CARDS stipcards1_
    ON commoncard0_.CARD_NUMBER = stipcards1_.CARD_NUMBER
  LEFT OUTER JOIN CARDS_EXCEPTIONS cardsexcep2_
    ON commoncard0_.CARD_NUMBER = cardsexcep2_.CARD_NUMBER
 WHERE (commoncard0_.card_id IN (?,?,?,?))
   AND stipcards1_.CENTRE_ID = commoncard0_.centre_Id

SECOD SQL

当某些记录存在于前两个表中但不存在于cards_exception表(实体)中时,会生成第二条语句。 查询执行的次数取决于在cards_exceptions表中找不到多少记录。

SELECT cardsexcep0_.CARD_NUMBER AS CARD_NUMBER1_1_0_
      ,cardsexcep0_.ACTION_CODE AS ACTION_CODE2_1_0_
  FROM CARDS_EXCEPTIONS cardsexcep0_
 WHERE cardsexcep0_.CARD_NUMBER = ?

请解释为什么 Hibernate 生成额外的查询以及如何修复它。

最佳答案

您能详细说明您想要接收的内容吗?您创建变量 joinException 的目的是什么?代码中未使用它。

关于java - Hibernate多实体连接问题,产生额外查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60323518/

相关文章:

java - 如何添加性感的开/关 slider ?

java - Eclipse 安装新软件

php - MySQL:where子句错误中的未知列

java - Hibernate、JDBC、Mysql、无法登录数据库

hibernate - Grails 2.4.4中的Hibernate JPA冲突

java - 在 IBM Domino 应用程序中使用 Quartz Scheduler

java - 如何使用 google Guice 创建相同类型的多个实例

sql - 如何确定在定义的剧集中是否发生了一行

mysql - WHERE a OR b IN (x) 不匹配,但返回行

java - 使用 Hibernate 和 Postgres 读取/更新并发实体