在咱们作.net系统的时候,所作的最多见的批量操做就是批量导入、插入、更新、删除等等,之前咱们怎么作呢?基本上有如下几种方式:html
一、利用循环调用insert方法,一条条插入。java
- public boolean insertStudent(List<Student> studentList)
- {
- try{
- if(studentList.count !=0){
- for(int i=0;i<studentList.count;i++){
-
- }
- return true;
- }
- }catch(Exception ex){
- throw New Exception("插入失败,请重试!")
- return false;
- }
- }
二、利用循环作sql语句拼接,而后批量执行sql语句。mysql
- public boolean insertStudent(List<Student> studentList)
- {
- try{
- if(studentList.count !=0){
- stringBuffer strSqltxt="";
- for(int i=0;i<studentList.count;i++){
- strSqltxt.append("insert into TableName (……) values (……);"
- }
- cmd.executesql(strSqltxt.toString());
- }
- }catch(Exception ex){
- throw New Exception("插入失败,请重试!")
- return false;
- }
- }
但是,对于封装比较完善的hibernate持久层,咱们又能怎么作呢?web
最多见的,也是利用循环来批量操做,可是,这里有一个必需要注意的点,就是缓存或者说是session区的空间是有限的,禁不起咱们无限制的存放,因此,当咱们执行如下操做时,会抛异常,内存溢出OutOfMemoryException!sql
- Session session = sessionFactory.openSession();
- Transaction tx = session.beginTransaction();
- for ( int i=0; i<100000; i++ ) {
- Customer customer = new Customer(.....);
- session.save(customer);
- }
- tx.commit();
- session.close();
这样是不能够的,可是在这时,hibernate也给咱们提供了解决方法,就是咱们能够经过设置JDBC的批量抓去数量参数(batch size)来设置一个合适的值,好比说10-50-100不等,配置:数据库
- <span style="font-size:18px;"><property name="hibernate.jdbc.batch_size">100</property></span>
另外,咱们还能够显示的禁用二级缓存,之前咱们也提到过:缓存
<property name="hibernate.cache.use_second_level_cache">false</property>session
正确代码:app
- Session session = sessionFactory.openSession();
- Transaction tx = session.beginTransaction();
- for ( int i=0; i<100000; i++ ) {
- Customer customer = new Customer(.....);
- session.save(customer);
- if(i%100==0){
- session.fulsh();
- session.clear();
- }
- }
- tx.commit();
- session.close();
这样就能解决咱们的那个内存溢出的问题,由于当你的存储对象数超过你设定的能接受的合理值的时候,程序会自动将持久化对象flush进数据缓存起来,而后清空session,进行下一轮存储,待全部数据所有完成,执行commit进行提交,数据库更新数据,说的简单,这样的效率是不咋地的,不信你能够试试,你想一想,先发出sql,100一轮,执行1000轮用来缓存sql语句,而后数据库统一执行sql,时间啊!less
StatelessSession(无状态session)接口
可是这不是问题,由于hibernate还给咱们提供了一个StatelessSession(无状态session)接口,做为选择,Hibernate提供了基于命令的API:
一、能够用detached object(托管对象)的形式把数据以流的方法加入到数据库,或从数据库输出。
二、StatelessSession没有持久化上下文,也不提供多少高层的生命周期语义。
三、无状态session不实现第一级cache;
四、也不和第二级缓存交互,也不和查询缓存交互。
五、它不实现事务化写,也不实现脏数据检查。
六、用stateless session进行的操做甚至不级联到关联实例。
七、stateless session忽略集合类(Collections)。
八、经过stateless session进行的操做不触发Hibernate的事件模型和拦截器。
九、无状态session对数据的混淆现象免疫,由于它没有第一级缓存。
十、无状态session是低层的抽象,和低层JDBC至关接近。换句话说,它能够直接操做数据。
- StatelessSession session = sessionFactory.openStatelessSession();
- Transaction tx = session.beginTransaction();
-
- ScrollableResults customers = session.getNamedQuery("GetCustomers")
- .scroll(ScrollMode.FORWARD_ONLY);
- while ( customers.next() ) {
- Customer customer = (Customer) customers.get(0);
- customer.updateStuff(...);
- session.update(customer);
- }
-
- tx.commit();
- session.close();
DML(Data Manipulation Language数据操做语言)风格操做
再有就是特殊服务(业务需求)须要咱们采用DML(Data Manipulation Language数据操做语言)风格操做,从一张表导入另外一张表数据,比方说从学生表(T_Studeng)里面往大三学生表(T_ThreeStudent)里面倒数据.
- Session session = sessionFactory.openSession();
- Transaction tx = session.beginTransaction();
-
- String hqlInsert = "insert into ThreeStudent(id, name) select s.id, s.name from Student s where ...";
- int createdEntities = s.createQuery( hqlInsert )
- .executeUpdate();
- tx.commit();
- session.close();
以上就是对批量操做的一点总结,万望对你们能有点帮助