2013-04-03 4 views
3

DAO 클래스에 다음 트랜잭션 단위를 사용하여 최대 절전 모드로 여러 행을 삽입하려고합니다.Hibernate에 일렬로 삽입 - 배치 삽입

@Override 
@SuppressWarnings("unchecked") 
@Transactional(readOnly = false, propagation=Propagation.REQUIRES_NEW, rollbackFor={Throwable.class}) 
public String insertZoneCharge(Long zoneId, List<Object[]> items) 
{ 
    Session session=sessionFactory.openSession(); 
    session.beginTransaction(); 

    //Configuration configuration=new Configuration(); 
    //configuration.setProperty("hibernate.jdbc.batch_size", "50"); 
    int i=1; 

    for(Object[] o:items) 
    { 
     if(o[2]!=null&&StringUtils.isNotBlank(o[2].toString())) 
     { 
      ZoneChargePK zoneChargeId=new ZoneChargePK(); 
      zoneChargeId.setWeightId(Long.parseLong(o[0].toString())); 
      zoneChargeId.setZoneId(zoneId); 

      model.ZoneCharge zoneCharge=new model.ZoneCharge(); 
      zoneCharge.setZoneChargePK(zoneChargeId); 
      zoneCharge.setCharge(new BigDecimal(o[2].toString()).setScale(2, RoundingMode.HALF_UP)); 
      session.save(zoneCharge); 

      if(++i%50==0) 
      { 
       session.flush(); 
       session.clear(); 
      } 
     } 
    } 

    session.getTransaction().commit(); 
    session.close(); 
    return "Data saved successfully."; 
} 

이 매개 변수의 매개 변수는 JSON 요청을 통해 제공됩니다. 관련이 없기 때문에 오라클 테이블 세부 사항에 대해서는 자세히 설명하지 않습니다.

내가 3 개의 값을 제공한다고 가정하면이 루프는 3 회 반복되고 3 개의 행이 해당 데이터베이스 테이블에 생성됩니다. 트랜잭션이 성공적으로 완료되면 콘솔에서 볼 수있는 다음 기본 Oracle INSERT 문이 세 번 실행됩니다.

insert into WAGAFASHIONDB.ZONE_CHARGE (CHARGE, WEIGHT_ID, ZONE_ID) values (?, ?, ?) 

디버그 및 추적 정보는 다음과 같습니다.

DEBUG [http-apr-8080-exec-84] (SqlStatementLogger.java:104) - insert into WAGAFASHIONDB.ZONE_CHARGE (CHARGE, WEIGHT_ID, ZONE_ID) values (?, ?, ?) 
TRACE [http-apr-8080-exec-84] (BasicBinder.java:83) - binding parameter [1] as [NUMERIC] - 1.00 
TRACE [http-apr-8080-exec-84] (BasicBinder.java:83) - binding parameter [2] as [BIGINT] - 164 
TRACE [http-apr-8080-exec-84] (BasicBinder.java:83) - binding parameter [3] as [BIGINT] - 22 

DEBUG [http-apr-8080-exec-84] (SqlStatementLogger.java:104) - insert into WAGAFASHIONDB.ZONE_CHARGE (CHARGE, WEIGHT_ID, ZONE_ID) values (?, ?, ?) 
TRACE [http-apr-8080-exec-84] (BasicBinder.java:83) - binding parameter [1] as [NUMERIC] - 2.00 
TRACE [http-apr-8080-exec-84] (BasicBinder.java:83) - binding parameter [2] as [BIGINT] - 221 
TRACE [http-apr-8080-exec-84] (BasicBinder.java:83) - binding parameter [3] as [BIGINT] - 22 

DEBUG [http-apr-8080-exec-84] (SqlStatementLogger.java:104) - insert into WAGAFASHIONDB.ZONE_CHARGE (CHARGE, WEIGHT_ID, ZONE_ID) values (?, ?, ?) 
TRACE [http-apr-8080-exec-84] (BasicBinder.java:83) - binding parameter [1] as [NUMERIC] - 3.00 
TRACE [http-apr-8080-exec-84] (BasicBinder.java:83) - binding parameter [2] as [BIGINT] - 163 
TRACE [http-apr-8080-exec-84] (BasicBinder.java:83) - binding parameter [3] as [BIGINT] - 22 

그래서, INSERT 세 개의 문이 실행 된 데이터베이스에 별도의 세 가지 여행이되었습니다 것으로 보인다.

한 번에 다중 행 INSERT 문 하나만 실행하면됩니다. 이 상황에서 Hibernate는 실제로 세 개의 분리 된 문장을 실행 하는가? 그렇다면 특정 배치에서 명령문을 실행하는 방법은 무엇입니까? 내 코드에 문제가 있습니까?


application-context.xml의 내 최대 절전 모드 구성은 다음과 같습니다.

<property name="hibernateProperties"> 
    <value> 
     hibernate.dialect=org.hibernate.dialect.Oracle10gDialect 
     hibernate.jdbc.batch_size=50 
     hibernate.cache.provider_class=org.hibernate.cache.EhCacheProvider    
     hibernate.format_sql=false 
     hibernate.show_sql=true 
     hibernate.order_updates=true 
     hibernate.connection.autocommit=false 
     hibernate.order_inserts=true 
     hibernate.order_updates=true 
     hibernate.cache.use_query_cache=false 
     hibernate.cache.use_second_level_cache=false 
     javax.persistence.validation.mode=callback    
    </value>   
    </property>   
+0

'Configuration configuration = new Configuration(); configuration.setProperty ("hibernate.jdbc.batch_size", "50");'는 의미가 없습니다. SessionFactory를 생성하면이를 수행해야합니다. –

+0

@orid -이 문장을 주석 처리했습니다. [이 답변] (http://stackoverflow.com/a/8310442/1391249)은 "* 트랜잭션이 완료 될 때까지는 ** 영구적으로 ** 만들지 않았습니다 **"라고 말합니다. 따라서 데이터베이스를 한 번만 방문하면이 작업을 수행 할 수 있습니까? – Tiny

답변

5

예상 사항이 잘못되었습니다. Hibernate는 하나의 insert 문을 생성하지 않을 것이다. 그러나 세 개의 insert 문을 일괄 처리에 추가하고이 일괄 처리를 실행하므로 데이터베이스에 대한 단일 왕복이 수행됩니다.

JDBC 일괄 업데이트에 대한 자세한 내용은 http://docs.oracle.com/javase/1.3/docs/guide/jdbc/spec2/jdbc2.1.frame6.html을 참조하십시오.