_002_Hibernate的批量插入(JDBC)

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

1,通过Hibernate缓存

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

[java] view plain copy
  1. package com.anlw.util;  
  2.   
  3. import org.hibernate.Session;  
  4. import org.hibernate.SessionFactory;  
  5. import org.hibernate.Transaction;  
  6. import org.hibernate.boot.registry.StandardServiceRegistryBuilder;  
  7. import org.hibernate.cfg.Configuration;  
  8. import org.hibernate.service.ServiceRegistry;  
  9.   
  10. import com.anlw.entity.Student;  
  11.   
  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.   
  19.     public void HIbernateTest() {  
  20.         conf = new Configuration().configure();  
  21.         st = new StandardServiceRegistryBuilder().applySettings(conf.getProperties()).build();  
  22.         sf = conf.buildSessionFactory(st);  
  23.         try {  
  24.             sess = sf.openSession();  
  25.             tx = sess.beginTransaction();  
  26.             for (int i = 0; i < 10; i++) {  
  27.                 Student s = new Student();  
  28.                 s.setAge(i + 1);  
  29.                 s.setName("test");  
  30.                 sess.save(s);  
  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.   
  43.     public static void main(String[] args) {  
  44.         new SessionUtil().HIbernateTest();  
  45.     }  
  46. }  
如果数据量太大,会有可能出现内存溢出的异常;

小知识:

(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级别的一级缓存;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值