Hibernate的批量插入

转自https://blog.csdn.net/an_2016/article/details/51759890

一、批量插入(两种方式)

1,通过Hibernate缓存

如果这样写代码进行批量插入(初始设想):


 
 
  1. package com.anlw.util;
  2. import org.hibernate.Session;
  3. import org.hibernate.SessionFactory;
  4. import org.hibernate.Transaction;
  5. import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
  6. import org.hibernate.cfg.Configuration;
  7. import org.hibernate.service.ServiceRegistry;
  8. import com.anlw.entity.Student;
  9. public class SessionUtil {
  10. Configuration conf = null;
  11. ServiceRegistry st = null;
  12. SessionFactory sf = null;
  13. Session sess = null;
  14. Transaction tx = null;
  15. public void HIbernateTest() {
  16. conf = new Configuration().configure();
  17. st = new StandardServiceRegistryBuilder().applySettings(conf.getProperties()).build();
  18. sf = conf.buildSessionFactory(st);
  19. try {
  20. sess = sf.openSession();
  21. tx = sess.beginTransaction();
  22. for ( int i = 0; i < 10; i++) {
  23. Student s = new Student();
  24. s.setAge(i + 1);
  25. s.setName( "test");
  26. sess.save(s);
  27. }
  28. tx.commit();
  29. } catch (Exception e) {
  30. if (tx != null) {
  31. tx.rollback();
  32. }
  33. } finally {
  34. sess.close();
  35. sf.close();
  36. }
  37. }
  38. public static void main(String[] args) {
  39. new SessionUtil().HIbernateTest();
  40. }
  41. }
如果数据量太大,会有可能出现内存溢出的异常;

小知识:

(1).Hibernate一级缓存,对其容量没有限制,强制使用,由于所有的对象都被保存到这个缓存中,内存总会达到一定数目时出现内存溢出的情况;

(2).Hibernate二级缓存可以进行大小配置;

要解决内存溢出的问题,就应该定时的将Sessiion缓存中的数据刷到数据库,正确的批量插入方式:

(1).设置批量尺寸(博主至今还没有明白下面这个属性和flush()方法的区别)

<property name="hibernate.jdbc.batch_size">2</property>

配置这个参数的原因就是尽量少读数据库,该参数值越大,读数据库的次数越少,速度越快;上面这个配置,是Hibernate是等到程序积累了100个sql之后在批量提交;

(2).关闭二级缓存(这个博主也不是很明白)

<property name="hibernate.cache.use_second_level_cache">false</property>

除了Session级别的一级缓存,Hibernate还有一个SessionFactory级别的二级缓存,如果启用了二级缓存,从机制上来说,Hibernate为了维护二级缓存,在批量插入时,hibernate会将对象纳入二级缓存,性能上就会有很大损失,也可能引发异常,因此最好关闭SessionFactory级别的二级缓存;

(3).在一二设置完成的基础上,清空Session级别的一级缓存;


 
 
  1. package com.anlw.util;
  2. import org.hibernate.Session;
  3. import org.hibernate.SessionFactory;
  4. import org.hibernate.Transaction;
  5. import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
  6. import org.hibernate.cfg.Configuration;
  7. import org.hibernate.service.ServiceRegistry;
  8. import com.anlw.entity.Student;
  9. public class SessionUtil {
  10. Configuration conf = null;
  11. ServiceRegistry st = null;
  12. SessionFactory sf = null;
  13. Session sess = null;
  14. Transaction tx = null;
  15. public void HIbernateTest() {
  16. conf = new Configuration().configure();
  17. st = new StandardServiceRegistryBuilder().applySettings(conf.getProperties()).build();
  18. sf = conf.buildSessionFactory(st);
  19. try {
  20. sess = sf.openSession();
  21. tx = sess.beginTransaction();
  22. for ( int i = 0; i < 10; i++) {
  23. Student s = new Student();
  24. s.setAge(i + 1);
  25. s.setName( "test");
  26. sess.save(s);
  27. if(i% 100 == 0){ //以每100个数据作为一个处理单元
  28. sess.flush(); //保持与数据库数据的同步
  29. sess.clear(); //清楚Session级别的一级缓存的全部数据,及时释放占用的内存
  30. }
  31. }
  32. tx.commit();
  33. } catch (Exception e) {
  34. if (tx != null) {
  35. tx.rollback();
  36. }
  37. } finally {
  38. sess.close();
  39. sf.close();
  40. }
  41. }
  42. public static void main(String[] args) {
  43. new SessionUtil().HIbernateTest();
  44. }
  45. }

2,绕过Hibernate,直接调用JDBC API


 
 
  1. package com.anlw.util;
  2. import java.sql.Connection;
  3. import java.sql.PreparedStatement;
  4. import java.sql.SQLException;
  5. import org.hibernate.Session;
  6. import org.hibernate.SessionFactory;
  7. import org.hibernate.Transaction;
  8. import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
  9. import org.hibernate.cfg.Configuration;
  10. import org.hibernate.jdbc.Work;
  11. import org.hibernate.service.ServiceRegistry;
  12. public class SessionUtil {
  13. Configuration conf = null;
  14. ServiceRegistry st = null;
  15. SessionFactory sf = null;
  16. Session sess = null;
  17. Transaction tx = null;
  18. public void HIbernateTest() {
  19. conf = new Configuration().configure();
  20. st = new StandardServiceRegistryBuilder().applySettings(conf.getProperties()).build();
  21. sf = conf.buildSessionFactory(st);
  22. try {
  23. sess = sf.openSession();
  24. tx = sess.beginTransaction();
  25. //执行Work对象指定的操作,即调用Work对象的execute()方法
  26. //Session会把当前使用的数据库连接传给execute()方法
  27. sess.doWork( new Work() {
  28. @Override
  29. public void execute(Connection arg0) throws SQLException { //需要注意的是,不需要调用close()方法关闭这个连接
  30. //通过JDBC API执行用于批量插入的sql语句
  31. String sql = "insert into student(name,age) values(?,?)";
  32. PreparedStatement ps = arg0.prepareStatement(sql);
  33. for( int i= 0;i< 10;i++){
  34. ps.setString( 1, "kobe");
  35. ps.setInt( 2, 12);
  36. ps.addBatch();
  37. }
  38. ps.executeBatch();
  39. }
  40. });
  41. tx.commit();
  42. } catch (Exception e) {
  43. if (tx != null) {
  44. tx.rollback();
  45. }
  46. } finally {
  47. sess.close();
  48. sf.close();
  49. }
  50. }
  51. public static void main(String[] args) {
  52. new SessionUtil().HIbernateTest();
  53. }
  54. }
注意:通过JDBC API中的PreparedStatement接口来执行sql语句,sql语句涉及到的数据不会被加载到Session的缓存中,因此不会占用内存空间,因此直接调用JDBC API批量化插入的效率要高于Hibernate缓存的批量插入;





本人用的是第二种方法,速度比第一种很快

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值