`

Hibernate批量操作(JDBC批量操作)

阅读更多

部分内容转自 :http://gaolixu.iteye.com/blog/519086

部分内容转自 :http://superjavason.iteye.com/blog/255423

 

--------------------------------------------------------------------------------------------

 

hibernate.jdbc.fetch_size 50

hibernate.jdbc.batch_size 25

这面这两项属性很重要

 

配置方法如下:

<session-factory>
    ...
    <property name="hibernate.jdbc.batch_size">50</property>
    ...
</session.factory>

 

--------------------------------------------------

 

Fetch Size (抓取大小):

是设定JDBC的Statement读取数据的时候每次从数据库中取出的记录条数。

一般我们查询时会返回一个ResultSet对象,他其实是一个数据库的游标,要时刻保持与数据库的连接,不可断开。 

例如一次查询结果是1万条记录,对于Oracle的JDBC驱动来说,是不会1次性把1万条结果全返出来的,而只会返出Fetch Size数量的记录,当不够用时,再去数据库取Fetch Size条数据,当然这一过程你是完全感觉不出来的。

 

 

Fetch Size设的越大,读数据库的次数越少,速度越快,越耗内存;

Fetch Size设的越小,读数据库的次数越多,速度越慢,前期会省内存(后期1万条都读出来了还是要用内存的)。

 

Oracle数据库的JDBC驱动默认的Fetch Size=10,是一个非常保守的设定,根据我的测试,当Fetch Size=50的时候,性能会提升1倍之多,当Fetch Size=100,性能还能继续提升20%,Fetch Size继续增大,性能提升的就不显著了。

因此我建议使用Oracle的一定要将Fetch Size设到50。

 

不过并不是所有的数据库都支持Fetch Size特性,例如MySQL就不支持。

 

MySQL就像我上面说的那种最坏的情况,他总是一下就把1万条记录完全取出来,内存消耗会非常非常惊人!这个情况就没有什么好办法了 :(

 

---------------------------------------------------------------------------

Batch Size是设定对数据库进行批量删除,批量更新和批量插入的时候的批次大小,有点相当于设置Buffer缓冲区大小的意思。

 

Batch Size越大,批量操作的向数据库发送sql的次数越少,速度就越快。我做的一个测试结果是当Batch Size=0的时候,使用Hibernate对Oracle数据库删除1万条记录需要25秒,Batch Size = 50的时候,删除仅仅需要5秒!!!

 

这有点像平时我们写程序写硬盘文件一样,设立一个Buffer,每次写入Buffer,等Buffer满了以后,一次写入硬盘,道理相同。

 

-----------------------------------------------------------------------------

hibernate.max_fetch_depth  设置外连接抓取树的最大深度取值. 建议设置为03之间

就是每次你在查询时,会级联查询的深度,譬如你对关联vo设置了eager的话,如果fetch_depth值太小的话,会发多很多条sql

-----------------------------------------------------------------------------

1 伪批量删除

	public void delete(final List<Integer> ids)
	{
		final Session session = hibernateUtil.getCS();
		final Query q = session.createQuery("delete from Img where userId=:userId and id in(:ids)");
		final User user = (User) ActionContext.getContext().getSession().get("s");
		q.setInteger("userId", user.getId());
		q.setParameterList("ids", ids);
		q.executeUpdate();
	}

 

 2 批量插入

大家说下面的代码,50次flush一下, 如果同时也设置了<property name="hibernate.jdbc.batch_size">40(或其它值)</property>会怎么样呢?

 

Session session = sessionFactory.openSession(); 
Transaction tx = session.beginTransaction();   
for ( int i=0; i<100000; i++ ) { 
    Customer customer = new Customer(.....); 
    //如果你的 hibernate.cache.use_second_level_cache 是 true, 请在会话级别上关闭他    
    //向(任何一级)缓存中加载大量数据通常也意味着它们很快会被清除出去,这会增加GC开销。  
    session.setCacheMode(CacheMode.IGNORE);
    session.save(customer); 
    if ( i % 50 == 0 ) { 
          //将本批插入的对象立即写入数据库并释放内存 
          session.flush(); 
          session.clear(); 
    } 
} 
tx.commit(); 
session.close();

--------------------------------------------------------------------------------------------------------------

 

JDBC批量操作

 

Statement加批量的方法

 conn.setAutoCommit(false);   
 Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY);   
 for(int x = 0; x < size; x++){   
   stmt.addBatch("INSERT INTO adlogs(ip,website,yyyymmdd,hour,object_id) VALUES('192.168.1.3', 'localhost','20081009',8,'23123')");   
 }   
stmt.executeBatch();   
conn.commit(); 

 

使用PreparedStatement加批量的方法

try {   
      Class.forName("com.mysql.jdbc.Driver");   
      conn = DriverManager.getConnection(o_url, userName, password);   
      conn.setAutoCommit(false);   
      String sql = "INSERT adlogs(ip,website,yyyymmdd,hour,object_id) VALUES(?,?,?,?,?)";   
      PreparedStatement prest = conn.prepareStatement(sql,ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY);   
      for(int x = 0; x < size; x++){   
         prest.setString(1, "192.168.1.1");   
         prest.setString(2, "localhost");   
         prest.setString(3, "20081009");   
         prest.setInt(4, 8);   
         prest.setString(5, "11111111");   
         prest.addBatch();   
      }   
      prest.executeBatch();   
      conn.commit();   
      conn.close();   
} catch (SQLException ex) {   
   Logger.getLogger(MyLogger.class.getName()).log(Level.SEVERE, null, ex);   
} catch (ClassNotFoundException ex) {   
     Logger.getLogger(MyLogger.class.getName()).log(Level.SEVERE, null, ex);   
}  

 

 

注意上面JDBC驱动使用的是mysql的, 好像不支持批量更新,所以大家一定要使用oracle的JDBC驱动试验啊。

 

分享到:
评论
3 楼 pizza823 2010-07-13  
我是这样做的,前端页面获取到多个checkbox的值,定义了一个var array = new Array()
来存放,通过url传递 比如.jsp?ID=array
我后台获取String ID = String ID = request.getParameter("ID");

DAO
	//批量删除
    @SuppressWarnings("unchecked")
	public void deleteUser(final String ids) throws Exception {
        final String queryString = "delete from BaUser where recId in (:ids) ";
        hibernateTemplate.execute(new HibernateCallback() {
            public Object doInHibernate(Session session) throws HibernateException{
                Query query = session.createQuery(queryString);
                query.setString("ids", ids);
                return query.executeUpdate();
            }
        });
    }

Controller
	protected void delete(Writer writer , HttpServletRequest request) throws Exception {

        String ID = request.getParameter("ID");
        System.out.println(ID);
        userDao.deleteUser(ID);
	}
我多选了几个,但是它只删除第一个,其它的没有删除
但是查看信息的时候,却是正确是sql语句啊

26,28,29 //输出获取到的ID
[17:19:08] [DEBUG] -- Opening Hibernate Session
[17:19:08] [DEBUG] -- opened session at timestamp: 12790127482
[17:19:08] [TRACE] -- located HQL query plan in cache (delete from BaUser where recId in (:ids) )
[17:19:08] [TRACE] -- located HQL query plan in cache (delete from BaUser where recId in (:ids) )
[17:19:08] [TRACE] -- executeUpdate: delete from BaUser where recId in (:ids)
[17:19:08] [TRACE] -- named parameters: {ids=26,28,29}
[17:19:08] [DEBUG] -- about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
[17:19:08] [DEBUG] -- opening JDBC connection
[17:19:08] [DEBUG] -- delete from T_BA_USERS where REC_ID in (?)
Hibernate: delete from T_BA_USERS where REC_ID in (?)
[17:19:08] [TRACE] -- preparing statement
[17:19:08] [TRACE] -- binding '26,28,29' to parameter: 1
[17:19:08] [DEBUG] -- about to close PreparedStatement (open PreparedStatements: 1, globally: 1)

2 楼 linsongbin1 2009-10-08  
我之前是使用StringBuffer构造字符串的,
然后在使用session.setParameter();
但是楼主提供的这种方式更加的简洁。
1 楼 hackpro 2009-05-16  
对于传于的参数,可以定义为 数组
public void delete(final String[] ids)  

   q.setInteger("userId", Arrays.asList(ids));  

这样,单个删除或批量都可以了

当然数组的定义要和你的 img 实体字段类型相同,否则就会报错

相关推荐

    hibernate批量删除

    在我们的Java项目中,批量更新是指在一个事务中更新大批量数据,批量删除是指在一个事务中删除大批量数据。批量删除虽然在Hibernate里也可以实现,但...其实Hibernate提供的JDBC接口,可以方便的进行批量的更新和删除。

    hibernate-batch-size-test:Hibernate hibernate.jdbc.batch_size 测试

    Hibernate hibernate.jdbc.batch_size 测试带有 MySQL JDBC 驱动程序的 Hibernate 批量插入示例。 에 관한 설명

    Hibernate+JDBC实现批量插入、更新及删除的方法详解

    主要介绍了Hibernate+JDBC实现批量插入、更新及删除的方法,结合实例形式较为详细的分析了Hibernate与JDBC针对数据库的批量操作相关实现技巧,需要的朋友可以参考下

    Hibernate问题解决

    Hibernate 批量删除和更新 4、如何有选择地取表的字段信息? 5、如果表无主键,是否在Hibernate中一定不能实现了? 7、left join与right join具体应如何在Hibernate中配置? 8、统计如何实现?如何配置...

    基础操作1

    批量操作在xml文件中配置使用hibernate自带的 JDBC实现:批量跟新(1)hibernate自带(2)JDBC实现批量删除hibernate实现 JD

    hibernate效率问题

    hibernate效率注意的几个问题,批量删除和批量更新建议用JDBC,这是一个原则,当然有的时候可能必须用Hibernate来批量更新和批量删除,那么这个时候我想说的就是,Hibernate批量更新和删除效率并非传说中的那么差,...

    Hibernate3性能优化 Hibernate_regerence3.12

    有很多人认为Hibernate天生效率比较低,确实,在普遍情况下,需要将执行转换为SQL语句的 Hibernate 的效率低于直接JDBC存取,然而,在经过比较好的性能优化之后,Hibernate的性能还是让人相当...3.批量数据操作 4.杂项

    jpa-hibernate-jdbc:比较同一个数据库的JPA,Hibernate和JDBC的性能

    背景开发人员普遍担心,使用工具(ORM)将严重影响其应用程序的性能,尤其是在数据库包含大量记录或需要批量获取数据的情况下。 一些开发人员创建了工作基准,表明使用ORM与使用原始JDBC相比,可导致性能下降10或100...

    Hibernate+中文文档

    3.4. Hibernate JDBC和连接(connection)属性 3.5. Hibernate缓存属性 3.6. Hibernate事务属性 3.7. 其他属性 3.8. Hibernate SQL方言 (hibernate.dialect) 3.9. Hibernate日志类别 3.10. JTA ...

    Hibernate配置各种数据源详解

    Hibernate配置各种数据源 &lt;hibernate-configuration&gt; &lt;!– 各属性的配置–&gt; &lt;!—为true表示将Hibernate发送给数据库的sql显示出来 –&gt; ...– 设定对数据库进行批量删除 –&gt; ”jdbc.batch_size”&gt;30&lt;/property&gt;

    精通 Hibernate:Java 对象持久化技术详解(第2版).part2

     9.4.4 直接通过JDBC API来进行批量操作  9.5 使用元数据  9.6 通过Hibernate调用存储过程  9.7 小结  9.8 思考题 第10章 映射组成关系  10.1 建立精粒度对象模型  10.2 建立粗粒度关系数据模型  10.3 映射...

    mysql三种批量增加的性能分析

    最近在深入学习hibernate,在进行批量操作时,发现hibernate批量操作性能非常低.于是就想找一个性能较高的方法,在对jdbc、jdbcTemplate、hibernate进行测试后,发现jdbc的执行效率是最高的,jdbcTemplate也很相近,...

    详解jdbc实现对CLOB和BLOB数据类型的操作

    主要介绍了详解jdbc实现对CLOB和BLOB数据类型的操作的相关资料,这里实现写入操作与读写操作,需要的朋友可以参考下

    P6SPY JDBC拦截打印sql语句 非常好的调试工具

     -- 由于每个应用的数据库连接配置,可能不一样,有些是Hibernate, OJB, Spring或者其它。。。。请按照相应的配置文件修改即可。  -- dbcp还要再试试,才知道是否支持,理论是支持的。 4. 编辑spy.properties...

    HibernateAPI中文版.chm

    3.4. Hibernate JDBC和连接(connection)属性 3.5. Hibernate缓存属性 3.6. Hibernate事务属性 3.7. 其他属性 3.8. Hibernate SQL方言 (hibernate.dialect) 3.9. Hibernate日志类别 3.10. JTA ...

    hibernate3.2中文文档(chm格式)

    3.4. Hibernate JDBC和连接(connection)属性 3.5. Hibernate缓存属性 3.6. Hibernate事务属性 3.7. 其他属性 3.8. Hibernate SQL方言 (hibernate.dialect) 3.9. Hibernate日志类别 3.10. JTA ...

    基于SpringJDBC的轻量级ORM框架sborm.zip

    3、QueryBuilder:单表查询基本上都可以实现零Sql(除非查询条件特别复杂的),更新、删除等操作也可以通过QueryBuilder进行批量处理,不局限于根据主键来处理。 4、分表操作的支持:对于分表操作和常规的使用...

    Hibernate中文详细学习文档

    3.3. JDBC连接 3.4. 可选的配置属性 3.4.1. SQL方言 3.4.2. 外连接抓取(Outer Join Fetching) 3.4.3. 二进制流 (Binary Streams) 3.4.4. 二级缓存与查询缓存 3.4.5. 查询语言中的替换 3.4.6. Hibernate的统计...

    Hibernate实战(第2版 中文高清版)

     12.2 大批量和批量操作   12.2.1 使用HQL和JPA QL的大批量语句   12.2.2 利用批量处理   12.2.3 使用无状态的会话   12.3 数据过滤和拦截   12.3.1 动态数据过滤   12.3.2 拦截Hibernate事件   ...

Global site tag (gtag.js) - Google Analytics