I want to insert records in database using Hibernate Native SQL.The code is like below
Session session = sessionFactory.openSession();
Transaction tx = ses
Hibernate have a Batch functionality.But in above case I am using Native SQL,as per my observation hibernate batch is not much effective in case of Native SQL.Yes,surely it avoids the out of memory error but does not improves much performance.
Hence I retreated to implemented JDBC Batch in Hibernate.Hibernate provides method doWork()
to get Connection from Hibernate Session.
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
//get Connction from Session
session.doWork(new Work() {
@Override
public void execute(Connection conn) throws SQLException {
PreparedStatement pstmt = null;
try{
String sqlInsert = "insert into sampletbl (name) values (?) ";
pstmt = conn.prepareStatement(sqlInsert );
int i=0;
for(String name : list){
pstmt .setString(1, name);
pstmt .addBatch();
//20 : JDBC batch size
if ( i % 20 == 0 ) {
pstmt .executeBatch();
}
i++;
}
pstmt .executeBatch();
}
finally{
pstmt .close();
}
}
});
tx.commit();
session.close();
Here is the same example for Java 8, Hibernate-JPA 2.1:
@Repository
public class SampleNativeQueryRepository {
private final Logger log = LoggerFactory.getLogger(SampleNativeQueryRepository.class);
@PersistenceContext
private EntityManager em;
public void bulkInsertName(List<String> list){
Session hibernateSession = em.unwrap(Session.class);
String sql = "insert into sampletbl (name) values (:name) ";
hibernateSession.doWork(connection -> {
try (PreparedStatement preparedStatement = connection.prepareStatement(sql)) {
int i = 1;
for(String name : list) {
preparedStatement.setString(1, name);
preparedStatement.addBatch();
//Batch size: 20
if (i % 20 == 0) {
preparedStatement.executeBatch();
}
i++;
}
preparedStatement.executeBatch();
} catch (SQLException e) {
log.error("An exception occurred in SampleNativeQueryRepository.bulkInsertName: {}", e);
}
});
}
}
If you don't need to worry about SQL injection. i.e you are not getting data from user side then you can do this.
StringBuilder sqlInsert = new StringBuilder("insert into sampletbl (name) values ");
for(String name : list){
sqlInsert.append("("+name++"),");
}
sqlInsert.setLength(sqlInsert.length() - 1);
session.createSQLQuery( sqlInsert.toString()).executeUpdate();
It will create a query like this.
insert into sampletbl (name) values ("name1"), ("name2")....
This way your query will run only once and not for each and every item in the list.