복붙노트

[SPRING] Oracle을 사용하여 Hibernate에서 마지막으로 삽입 된 행의 ID를 검색 할 수 없습니다.

SPRING

Oracle을 사용하여 Hibernate에서 마지막으로 삽입 된 행의 ID를 검색 할 수 없습니다.

Spring 버전 3.0.2에서 Hibernate Tools 3.2.1.GA를 사용하고 있습니다. Oracle (10g) 데이터베이스에 마지막으로 삽입 된 행의 ID를 다음과 같이 검색하려고합니다.

Session session=NewHibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();

Country c=new Country();

c.setCountryId(new BigDecimal(0));
c.setCountryName(request.getParameter("txtCountryName"));
c.setCountryCode(request.getParameter("txtCountryCode"));
Zone z=(Zone) session.get(Zone.class, new BigDecimal(request.getParameter("zoneId")));
c.setZone(z);
session.save(c);

session.flush();    
System.out.println(c.getCountryId());    
session.getTransaction().commit();       

이 문은 System.out.println (c.getCountryId ()); 데이터가 데이터베이스에 직렬화되고 트랜잭션이 커밋되기 전에 현재 삽입 된 ID를 반환 할 것으로 예상되지만 이전 코드 스 니펫의 다음 행 (나에게 표시되는 것으로 추정 됨) 때문에 그렇지 않습니다.

c.setCountryId(new BigDecimal(0));

필자의 경우 (삽입하는 동안) 왜이 문장이 필요한지 잘 모르겠습니다. 나는이 진술을 어디에도 보지 못했다. 이 줄을 생략하면 다음과 같은 예외가 throw됩니다.

이 문장이 있는지 c.setCountryId (new BigDecimal (0)); 삽입하는 동안 정말로 필요합니까? 이것은 오라클 데이터베이스에서 시퀀스 생성 기본 키이며 그 라인 때문에이 문은 System.out.println (c.getCountryId ()); 항상 현재 세션에서 현재 삽입 된 ID를 반환 할 것으로 예상되는 0을 반환합니다.

그렇다면이 경우 마지막으로 생성 된 ID를 어떻게 얻을 수 있습니까? 잘못된 길을 따르고 있습니까? 다른 길은 있습니까?

편집하다:

CREATE TABLE  "COUNTRY" 
(   
    "COUNTRY_ID" NUMBER(35,0) NOT NULL ENABLE, 
    "COUNTRY_CODE" VARCHAR2(10), 
    "COUNTRY_NAME" VARCHAR2(50), 
    "ZONE_ID" NUMBER(35,0), 

    CONSTRAINT "COUNTRY_PK" PRIMARY KEY ("COUNTRY_ID") ENABLE, 
    CONSTRAINT "COUNTRY_FK" FOREIGN KEY ("ZONE_ID")
                            REFERENCES  "ZONE" ("ZONE_ID") ON DELETE CASCADE ENABLE
)
/

CREATE OR REPLACE TRIGGER  "BI_COUNTRY" 
before insert on "COUNTRY"               
for each row  

begin   
    select "COUNTRY_SEQ".nextval into :NEW.COUNTRY_ID from dual; 
end; 

/
ALTER TRIGGER  "BI_COUNTRY" ENABLE
/ 

해결법

  1. ==============================

    1.save ()를 호출하기 전에이 클래스의 ids를 수동으로 할당해야한다는 예외는 'Assigned'라는 식별자 생성 전략을 사용하고 있음을 의미합니다.

    save ()를 호출하기 전에이 클래스의 ids를 수동으로 할당해야한다는 예외는 'Assigned'라는 식별자 생성 전략을 사용하고 있음을 의미합니다.

    전략을 정의하지 않으면 최대 절전 모드가 '할당 됨'으로 기본 설정됩니다. 'assigned'전략은 hibernate가 애플리케이션이 자신의 ID를 제공 할 것으로 기대한다는 것을 의미한다.

    Oracle에서 시퀀스 ID 생성기를 사용하려면 다음 구성으로 그렇게 할 수 있습니다.

    xml -

       <id name="countryId" type="java.lang.Integer">  
            <column name="Country_Id" />  
            <generator class="sequence">  
                <param name="sequence">Country_Id_Seq</param>               
            </generator>  
        </id>
    

    특수 효과를 사용하는 경우 -

       @Id
       @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="Country_Id_Seq")
       @SequenceGenerator(name="Country_Id_Seq", sequenceName="Country_Id_Seq"  )
       private Integer sequence;
    

    그리고 코드는 그렇게 보일 것입니다 -

    Country c=new Country();
    
    c.setCountryName(request.getParameter("txtCountryName"));
    c.setCountryCode(request.getParameter("txtCountryCode"));
    Zone z=(Zone) session.get(Zone.class, new BigDecimal(request.getParameter("zoneId")));
    c.setZone(z);
    session.save(c);
    
    session.flush();    
    System.out.println(c.getCountryId()); 
    

    'session.save (c)'가 실행되면, hibernate는 다음과 같은 sql 호출을 수행하고, id를 검색하여 Country 객체에 설정한다.

    select Country_Id_Seq.nextVal from dual;
    

    방아쇠 문제

    행을 삽입 할 때 트리거를 사용하여 ID를 증가시키기 때문에 최대 절전 시퀀스에 문제가 발생할 수 있습니다. Hibernate는 시퀀스를 사용하여 ID를 생성하고 데이터베이스는 트리거를 사용하여 ID를 증가시킵니다. 이로 인해 ID가 두 번 증가합니다.

    이 문제를 해결할 수있는 세 가지 옵션이 있습니다.

  2. ==============================

    2.시퀀스에 의해 생성 된 ID 열의 값이면 엔티티 정의의 ID 열과 해당 시퀀스를 연결하여 삽입 중에 Hibernate에 의해 ID 값으로 속성이 채워지도록해야합니다.

    시퀀스에 의해 생성 된 ID 열의 값이면 엔티티 정의의 ID 열과 해당 시퀀스를 연결하여 삽입 중에 Hibernate에 의해 ID 값으로 속성이 채워지도록해야합니다.

    특수 효과 사용 :

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "CountryIdSequence")
    @SequenceGenerator(name = "CountryIdSequence", sequenceName = "COUNTRY_ID_SEQUENCE")
    @Column(name = "COUNTRY_ID")
    private BigDecimal countryId;
    

    hbm 사용 :

    <id name="countryId" type="big_decimal">
        <column name="COUNTRY_ID" />
        <generator class=""sequence">
            <param name="sequence">COUNTRY_ID_SEQUENCE</param>
        </generator>
    </id>
    

    그런 다음 저장 후 사용할 수 있습니다.

    데이터베이스 계층에서 엔티티에 대한 모든 변경 사항은 객체를 새로 고칠 때까지 최대 절전 엔티티 계층에 반영되지 않습니다.

    session.save(c);
    session.flush();    
    // Refresh the object for columns modified in the DB by IDENTITY / SEQUENCE / Triggers.
    session.refresh(c);
    System.out.println(c.getCountryId());  
    
  3. from https://stackoverflow.com/questions/13300808/cannot-retrieve-the-id-of-the-last-inserted-row-in-hibernate-using-oracle by cc-by-sa and MIT license