2012-10-04 5 views
0

JPA를 사용하여 데이터베이스에 엔터티를 삽입했지만 삽입을 수행하고 마지막으로 삽입 된 레코드의 기본 키를 가져와야하는 문제에 부딪혔습니다 .JPA에서 마지막으로 삽입 한 레코드의 기본 키 가져 오기

PostgreSQL을 사용하면 레코드 ID를 반환하는 INSERT RETURNING 문을 사용하지만 엔티티 관리자가이 모든 작업을 수행하면 SELECT CURRVAL을 사용하는 것이 유일한 방법입니다.

그래서 문제는 OpenMQ를 통해 메시지 드리븐 빈 (대개 각 소스에서 한 번에 10-100 개의 메시지)으로 데이터를 보내는 여러 데이터 소스가 있고이 MDB 내부에서 엔티티 관리자를 통해 PostgreSQL에이를 유지합니다. 이 시점에서 나는 이라고 생각한다.에는 "CURRVAL"을 사용하여 마지막 레코드 ID를 얻지 못할 정도로 많은 삽입 작업을하는 "경쟁 조건"과 같은 효과가있을 것이라고 생각한다.

내 MDB는 아래의 엔티티 관리자를 통해 3 개의 엔티티 bean을 유지합니다.

이 작업을 더 효과적으로 수행하는 방법에 대한 도움이 필요합니다.

public void onMessage(Message msg) { 
    Integer agPK = 0; 
    Integer scanPK = 0; 
    Integer lookPK = 0; 

    Iterator iter = null; 
    List<Ag> agKeys = null; 
    List<Scan> scanKeys = null; 

    try { 
     iag = (IAgBean) (new InitialContext()).lookup(
       "java:comp/env/ejb/AgBean"); 

     TextMessage tmsg = (TextMessage) msg; 


     // insert this into table only if doesn't exists 
     Ag ag = new Ag(msg.getStringProperty("name")); 

     agKeys = (List) (iag.getPKs(ag)); 

     iter = agKeys.iterator(); 

     if (iter.hasNext()) { 
      agPK = ((Ag) iter.next()).getId(); 
     } 
     else { 
      // no PK found so not in dbase, insert new 
      iag.addAg(ag); 
      agKeys = (List) (iag.getPKs(ag)); 
      iter = agKeys.iterator(); 

      if (iter.hasNext()) { 
       agPK = ((Ag) iter.next()).getId(); 
      } 
     } 


     // insert this into table always 
     iscan = (IScanBean) (new InitialContext()).lookup(
       "java:comp/env/ejb/ScanBean"); 

     Scan scan = new Scan(); 
     scan.setName(msg.getStringProperty("name")); 
     scan.setCode(msg.getIntProperty("code")); 

     iscan.addScan(scan); 

     scanKeys = (List) iscan.getPKs(scan); 

     iter = scanKeys.iterator(); 

     if (iter.hasNext()) { 
      scanPK = ((Scan) iter.next()).getId(); 
     } 


     // insert into this table the two primary keys above 

     ilook = (ILookBean) (new InitialContext()).lookup(
       "java:comp/env/ejb/LookBean"); 

     Look look = new Look(); 

     if (agPK.intValue() != 0 && scanPK.intValue() != 0) { 
      look.setAgId(agPK); 
      look.setScanId(scanPK); 

      ilook.addLook(look); 
     } 
// ... 
+0

새 레코드를 삽입하기 전에 SELECT nextval() *을 사용하십시오. –

+0

방금 ​​엔티티가 flush() 후에 seq val로 pk를 실제로 populats한다는 것을 알았습니다. 작동하고있는 것처럼 보입니다. 시도 { em.persist (r); em.flush(); r.getId(); – Ender

+0

@DondiMichaelStroma Er, no. nextval()은 시퀀스를 진행시킨다. 그렇게하면 어떤 레코드에도 할당되지 않는 ID가 생깁니다. –

답변

2

JPA 사양에서는 ID 생성 전략을 사용하는 경우 persist 이후 엔티티에 유효한 ID가 채워져 있어야합니다. 아무 것도 할 필요가 없습니다.

관련 문제