Я пишу Java-приложение, используя hibernate 5.2
, но без HQL
есть две таблицы, Transactions
и ResponseCode
Логика оператора select, которую я хочу сгенерировать в 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
объект 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 Создает два оператора выбора, первый оператор получает список транзакций, а второй оператор получает сведения о коде ответа, который включен в список транзакций.
пример: если имеется 30000 транзакций и 15000 транзакций имеют код ответа 000, 5000 транзакций имеют код ответа 116, а транзакция 10000 имеет код ответа 400, второй оператор выбора будет выполнен три раза, для 000,116 и 400 кода rc.
но проблема в том, что таблица ResponseCode
содержит несколько языков для одного кода ответа
первый оператор выбора содержит ограничение на язык, но второй оператор выбора не имеет этого ограниченияи он не измеряет, какой язык указан в первом операторе, конечный результат объекта транзакций содержит для некоторых транзакций en
описание языка и для некоторых транзакций ge
описание языка.
Я думаю, это зависит от того, какое описание языка было выбрано оракулом наконец
Сгенерированный в спящем режиме выберите 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 = ?'
Ps Если я сделаю отношение OneToMany
, он получит 30000 транзакций и выполнит 30000 дополнительных запросов для получения кода ответаописание для каждой операции
Знаете ли вы, как это исправить?