gpt4 book ai didi

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

转载 作者:搜寻专家 更新时间:2023-10-30 21:11:54 26 4
gpt4 key购买 nike

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

有两个表,TransactionsResponseCode

enter image description here

我想由 Hibernate 生成的 select 语句的逻辑应该如下所示 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

ResponseCode 实体

@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 生成的选择 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 生成的选择 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/53916500/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com