문서의 이전 판입니다!
PreparedStatement#execute(String)으로 쿼리를 실행하는데, batch 모드가 되면 JDBC 표준 PreparedStatement#addBatch(String) 메소드를 호출해주는 것 뿐이다.session.flush()를 호출한다는 것은 Statement.executeBatch()를 호출한다는 의미인 듯 하다.addBatch/executeBatch는 insert 성능을 향상시켜준다. What You Didn't Know About JDBC BatchGenerationType.IDENTITY ID에 대해서는 Batch Insert가 작동하지 않는다. ID를 리턴받아 Entity 객체에 채워줘야 하기 때문으로 보인다.insert into xxx (…) values(…), (….), …. 형태로 합쳐주는 것이 아니다. 단지 addBatch를 할 뿐이다.insert 문을 insert into xxx (…) values(…), (…), (…)로 바꿔줌으로써 성능을 향상 시킬 수 있다.rewriteBatchedStatements=true 옵션을 추가해주면 된다.logger=com.mysql.jdbc.log.Slf4JLogger&profileSQL=true 옵션으로 로그를 통해 확인할 수 있다.<prop key="hibernate.jdbc.batch_size">[동시 Insert 갯수]</prop>
session.flush(); session.clear(); 호출session.clear()를 호출하는 이유는, insert 된 데이터들이 First Level Cache 메모리에 남아 있어서 메모리 고갈 발생할 수 있기 때문이다.org.hibernate.jdbc.AbstractBatcher 혹은 org.hibernate.engine.jdbc.batch.internal.AbstractBatchImpl 에서 남기는 로그 확인. 로거는 Hibernate 버전마다 다름.public void doBatch() { Session session = sessionFactory.openSession(); Transaction tx = session.beginTransaction(); for ( int i=0; i<100000; i++ ) { Customer customer = new Customer(.....); Cart cart = new Cart(...); customer.setCart(cart) // note we are adding the cart to the customer, so this object // needs to be persisted as well session.save(customer); if ( (i + 1) % 20 == 0 ) { //20, same as the JDBC batch size //flush a batch of inserts and release memory: session.flush(); session.clear(); } } tx.commit(); session.close(); }
Customer-Cart가 연관 관계가 있어서 하나의 Customer insert 후에 곧바로 Cart가 insert되고, 그 다음에 다시 Customer가 insert 되기 때문에 Customer는 Customer끼리, Cart는 Cart끼리 묶이지 않기 때문이다.<prop key="hibernate.order_inserts">true</prop> <prop key="hibernate.order_updates">true</prop>