java - 当两个不相关的表都有复合主键时,Hibernate 连接两个表

标签 java sql oracle hibernate jpa

我正在使用 hibernate 5.2 编写 Java 应用程序,但没有 HQL

有两个表,TransactionsResponseCode

enter image description here

我想要由 Hibernate 生成的 select 语句的逻辑应该如下所示:

SELECT t.tranType
      ,t.tranId
      ,t.requestDate
      ,t.rcCode
      ,t.tranAmount
      ,r.description
      ,r.status
  FROM transactions t
  LEFT OUTER JOIN responseCode r
    ON t.rcCode = r.rcCode
   AND (r.lang = 'en')
 WHERE (t.merchant_id =5 )

但是我的代码有问题,这是我的实现片段

交易实体

@Entity
@Table(name = "transactions")
public class Transaction implements java.io.Serializable {
    private static final long serialVersionUID = 1L;

        @Column(name = "merchant_id", nullable = true)
        private String merchantID;

        @Column(name = "tran_amount", nullable = true)
        private String tranAmount;

        @Id
        @Column(name = "tran_type", nullable = true)
        private String tranType;

        @Column(name = "auth_request_date", nullable = true)
        @Temporal(TemporalType.TIMESTAMP)
        private Date authRequestDate;

        @Id
        @Column(name = "tran_id", nullable = true)
        private String tranID;

        @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
        @JoinColumn(name="rc")
        private ResponseCode rc;

        // Contructos and getters/setters

响应代码实体

@Entity
@Table(name = "response_codes")

public class ResponseCode implements java.io.Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @Column(name = "response_code")
    private String rcCode;

    @Column(name = "rc_status")
    private String rcStatus;

    @Column(name = "rc_description")
    private String rcDesc;

    @Column(name = "rc_lang")
    private String rcLang;
    // Contructos and getters/setters

实现代码

CriteriaBuilder builder = session.getCriteriaBuilder();
CriteriaQuery<Transaction> criteria = builder.createQuery(Transaction.class);
Root<Transaction> transaction = criteria.from(Transaction.class);
Join<Transaction, ResponseCode> bJoin = transaction.join("rc",JoinType.LEFT);
bJoin.on(builder.equal(bJoin.get("rcLang"), tRequest.getLang()));

Predicate predicate = builder.and(transaction.get("merchantID").in(tRequest.getMerchantList()));
predicate = builder.and(predicate, builder.between(transaction.get("authRequestDate"), dateFrom, dateTo));
criteria.where(predicate);

Hibernate 生成两个 select 语句,第一个语句获取事务列表,第二个语句获取事务列表中包含的响应代码详细信息。

example: if there is 30000 transaction, and 15000 transaction has 000 response code, 5000 transaction has 116 response code and 10000 transaction has 400 response code, it will run second select statement three times, for 000,116 and 400 rcCode.

但问题是 ResponseCode 表包含一个响应代码的多种语言 enter image description here

第一个 select 语句包含对语言的限制,但第二个 select 语句没有此限制,并且它不计量第一个语句中提供的语言,事务对象的最终结果包含某些事务 en 语言 rc 描述和某些事务 ge 语言 rc 描述。

I think it depends on which language description was selected by oracle at last

Hibernate 生成的 select I

SELECT t.tran_type
      ,t.tran_id
      ,t.auth_request_date
      ,t.merchant_id
      ,t.rc
      ,t.tran_amount
  FROM transactions t
  LEFT OUTER JOIN response_codes r
    ON t.rc = r.response_code
   AND (r.rc_lang = ?)
 WHERE (t.merchant_id IN (?))
   AND (t.AUTH_REQUEST_DATE BETWEEN ? AND ?)
 ORDER BY t.AUTH_REQUEST_DATE ASC

Hibernate 生成 select II

SELECT r.response_code  
      ,r.rc_description 
      ,r.rc_lang        
      ,r.rc_status      
  FROM response_codes r
 WHERE r.response_code = ? 
 //this select statement should have 'AND r.rc_lang = ?'

P.s If I make OneToMany relation it gets 30000 transaction and performs 30000 additional query to get response Code description for each operation, known as N + 1 problem

你知道如何解决吗?

最佳答案

将关系从 @OneToOne 更改为 @OneToMany 并使用 fetch 而不是 join ,它将仅执行一个查询,希望它能起作用。

 Join<Transaction, ResponseCode> join =
        (Join<Transaction,ResponseCode>)transaction.fetch("rc",JoinType.LEFT);

您也可以尝试使用@OneToOne

关于java - 当两个不相关的表都有复合主键时,Hibernate 连接两个表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53922786/

相关文章:

java - hibernate 创建表时如何排列列?

SQL:更新记录而不丢失其内容

java - 几秒钟后更改按钮的背景

java - 计算用于检查 StackOverflowException 的方法调用堆栈大小

mysql - 如何匹配对角线上两列(同一张表)的值,不匹配时显示结果

mysql - sql查询各部分的执行顺序是什么

oracle - 使用 Oracle 客户端跟踪和 tkprof 审查提交的 SQL 查询

java - 使用 PDB 的 Oracle Dataguard 上的 DB 的 Weblogic 数据源配置

java - 内部错误 : Unknown or unimplemented accessor type: 9

java - 如何根据 cpu/内存使用或待处理请求返回 503 服务器忙?