programing

최대 절전 모드 둘 다 복합 기본 키가 있는 경우 관련 없는 두 테이블에 가입

lastcode 2023. 10. 14. 10:17
반응형

최대 절전 모드 둘 다 복합 기본 키가 있는 경우 관련 없는 두 테이블에 가입

저는 자바 애플리케이션을 사용해서 쓰고 있습니다.hibernate 5.2 없이는HQL

두개의 테이블이 있습니다.Transactions그리고.ResponseCode

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

응답 코드 엔티티

@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 = ?'

추신 에 내가 만든다면.OneToManyN + 1 하여 30000다 N + 1고로 각 응답 코드 설명을 .

어떻게 고치는지 아세요?

@OneToOne.@OneToMany합니다.fetchjoin.다.

 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합니다를 의미합니다.당신은 하나의 거래, 하나의 응답 코드를 가지고 있지만 많은 언어를 가지고 있습니다.

)할 수 .@OneToOneTransaction그리고.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 - 선택Transaction2 - (String rc-code함); 2 - selectResponseCode와 함께) 로) rc Transaction.

두 엔터티의 매핑이 잘못되었습니다.

부터 ResponseCode독립체.표 모델은 다음과 같이 구성된 복합 기본 키를 보여 줍니다구성된 복합 를 보여 .RcCode그리고.Lang기둥들 은 다음과 같이 합니다.rcCode기본 키로 속성을 지정합니다.다를 해야 합니다.@Id 주석rcLangResponseCode독립체.

은 .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

반응형