최대 절전 모드 둘 다 복합 기본 키가 있는 경우 관련 없는 두 테이블에 가입
저는 자바 애플리케이션을 사용해서 쓰고 있습니다.hibernate 5.2
없이는HQL
두개의 테이블이 있습니다.Transactions
그리고.ResponseCode
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
응답 코드 엔티티
@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 rcCode에 대해 세 번 second select 문을 실행합니다.
는.ResponseCode
테이블에는 하나의 응답 코드에 대한 여러 언어가 포함되어 있습니다.
은 이 개체가 에 대해 인 first select 하지만, select , 개체가 일부 트랜잭션에 대해 포함하는 트랜잭션의 최종 결과인 first 문에서 제공되는 언어를 미터링하지 않습니다.en
어 rccge
language rc description.
오라클에서 최종적으로 어떤 언어 설명을 선택했느냐에 따라 달라질 것 같습니다.
최대 절전 모드 생성 선택 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
최대 절전 모드 생성 선택 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 = ?'
추신 에 내가 만든다면.
OneToMany
N + 1 하여 30000다 N + 1고로 각 응답 코드 설명을 .
어떻게 고치는지 아세요?
@OneToOne
.@OneToMany
합니다.fetch
join
.다.
Join<Transaction, ResponseCode> join =
(Join<Transaction,ResponseCode>)transaction.fetch("rc",JoinType.LEFT);
그리고 당신은 그것을 사용해 볼 수 있습니다.@OneToOne
드디어 알게 되었습니다.
조건 API는 관련 없는 엔티티 가입을 지원하지 않습니다.JPQL도 그것을 지원하지 않습니다.그러나 Hibernate는 5.1부터 HQL에서 지원합니다. https://discourse.hibernate.org/t/join-two-table-when-both-has-composite-primary-key/1966
아마도 몇 가지 해결책이 있겠지만, 이 경우 Criteria API 대신 HQL을 사용하는 것이 더 좋은 방법이라고 생각합니다.
다음은 HQL 구현 코드 스니펫입니다(엔티 클래스에서 변경된 것이 없습니다).
String hql = "FROM Transaction t \r\n" +
" LEFT OUTER JOIN FETCH t.rc r \r\n" +
" WHERE (t.merchantID IN (:merchant_id))\r\n" +
" AND (t.authRequestDate BETWEEN :from AND :to)\r\n" +
" AND (r.rcLang = :rcLang or r.rcLang is null)\r\n";
Query query = session.createQuery(hql,Transaction.class);
query.setParameter("merchant_id", tRequest.getMerchantList());
query.setParameter("rcLang", tRequest.getLang());
query.setParameter("from", dateFrom);
query.setParameter("to", dateTo);
List<Transaction> dbTransaction = query.getResultList();
지도를 바꿔야 합니다.rcCode
레코드를 고유하게 식별하지 않으므로 식별자가 될 수 없습니다.저는 그것이 많은 문제를 가져올 것이라고 생각합니다.ResponseCode
다른 식별자를 가져야 합니다.
@OneToOne
대 대 1합니다를 의미합니다.당신은 하나의 거래, 하나의 응답 코드를 가지고 있지만 많은 언어를 가지고 있습니다.
)할 수 .@OneToOne
Transaction
그리고.ResponseCode
(복합 키를 통해) 특정 언어를 사용합니다.
합니다.@OneToMany
그은 , , 으로부터 합니다.ResponseCode
의 테이블에 앉음Transaction
블
그러나 트랜잭션, 응답 코드(코드 자체 및 일반 정보 포함), 응답 코드 현지화(다른 언어의 메시지 포함) 등 3개의 테이블이 필요할 수도 있습니다.트랜잭션 일대일 응답_codes, 응답_codes 일대다 rc_localization.
에 동면 없을 수도 .Transaction
그리고.ResponseCode
.
public class Transaction implements java.io.Serializable {
...
@Column(name="rc")
private String rc;
...
}
한 를 할 수 .ResponseCode
암호와 언어로두 가지 선택: 1 - 선택Transaction
2 - (String rc-code함); 2 - selectResponseCode
와 함께) 로) rc Transaction
.
두 엔터티의 매핑이 잘못되었습니다.
부터 ResponseCode
독립체. 표은 표 모델은 다음과 같이 구성된 복합 기본 키를 보여 줍니다로 구성된 복합 를 보여 .RcCode
그리고.Lang
기둥들 은 다음과 같이 합니다.rcCode
기본 키로 속성을 지정합니다.다를 해야 합니다.@Id
주석rcLang
ResponseCode
독립체.
은 .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;
@Id
@Column(name = "rc_lang")
private String rcLang;
// Contructors and getters/setters
}
한 후ReponseCode
,성을 모두 .Transaction
독립체. 의 Hibernate5.2 를 사용하면 Hibernate 의 2 개를 사용할 수 있습니다 로 할 수 .@JoinColumn
주석, 주석 Older 및은 이러한 을 추가 이전 Hibernate 버전과 버전 2.1 의 JPA 표준은 이러한 주석을 추가로 래핑해야 합니다에 .@JoinColumns
주석.
의 고정 .Transaction
엔티티:
@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_id", referencedColumnName = "id")
@JoinColumn(name="rc_lang", referencedColumnName = "lang")
private ResponseCode rc;
// Contructos and getters/setters
를 .ResponseCode
체의 Transaction
, 그건 틀렸습니다.응답 코드가 PK가 아니며, 지정된 트랜잭션 엔티티에 대한 응답 코드 엔티티를 고유하게 식별하지 않습니다.예: 응답 코드가 있는 트랜잭션의 경우000
응답 코드 엔티티는 2개('en' 및 'ge' 언어 포함)입니다.
대신 컬렉션을 매핑해 보는 것이 좋습니다.
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinColumn(name="rc")
private List<ResponseCode> rcList;
쿼리 WHERE 조건은 트랜잭션에만 적용되므로 트랜잭션 개체를 쿼리하기만 하면 됩니다.최대 절전 모드 캐시는 각 응답 코드에 필요한 최종 하위 쿼리를 최적화합니다('000'에 대한 쿼리 하나, '116'에 대한 쿼리 하나 등).
언급URL : https://stackoverflow.com/questions/53916500/hibernate-join-two-unrelated-table-when-both-has-composite-primary-key
'programing' 카테고리의 다른 글
Oracle procedure에서 선택 결과를 변수에 저장하는 방법 (0) | 2023.10.14 |
---|---|
가로 세로에서 소프트 키보드 입력에 대해 전체 화면 편집 보기를 비활성화하시겠습니까? (0) | 2023.10.14 |
안드로이드:영상 보기에서 영상을 각도만큼 회전 (0) | 2023.10.14 |
git 저장소를 데이터베이스 백엔드로 사용 (0) | 2023.10.14 |
Windows에서 COM(시리얼) 포트를 나열하시겠습니까? (0) | 2023.10.14 |