spring JDBC批量操作

来源:互联网 发布:阿里云rds登录不上 编辑:程序博客网 时间:2024/05/22 05:17

绝大多数JDBC驱动针对批量调用相同的prepared statement对象提供了性能提升。通过将这些更新操作封装到一个批量操作中,可以大量减少与数据库的操作频繁度。 本章节将详细描述使用JdbcTemplate或者SimpleJdbcTemplate进行批量操作的流程。

 

1、使用JdbcTemplate进行批量操作

JdbcTemplate的批量操作特性需要实现特定的接口BatchPreparedStatementSetter 来 进行的, 通过实现这个接口,并将其传入batchUpdate 方法进行调用。 这个接口有两个方法需要实现。一个叫做getBatchSize 来提供当前需要批 量操作的数量。另外一个方法是setValues 允许你为prepared statement设置参数。这个方法将在整个过程中被调用的次数,则取决于你在getBatchSize 中所指定的大小。 下面的示例展示了根据传入的list参数更新actor表,而传入的list同时作为批量操作的参数。

Java代码  


 

如果是通过读取文件进行批量操作,那么你可能需要一个特定的批量操作的数量,不过最后一次的批量操作,你可能没有那么多数量的记录。 在这种情况下,你可以实现InterruptibleBatchPreparedStatementSetter 接 口,从而允许你在某些情况中断批量操作,isBatchExhausted 方法允许指定一个终止批量操作的信号量。

2、使用SimpleJdbcTemplate进行批量操作

SimpleJdbcTemplate 类提供了另外一种批量操作的方式。无需实现 一个特定的接口,只需要提供所有在调用过程中要用到的参数,框架会遍历这些参数值,并使用内置的prepared statement类进行批量操作。API将根据你是否使用命名参数而有所不同。对于使用命名参数的情况,需要提供一个SqlParameterSource 的数组, 其中的每个元素将将作为批量操作的参数。 你可以使用SqlParameterSource.createBatch 方法, 通过传入一个JavaBean的数组或者一个包含了参数键值对的Map数组来创建这个数组。

下面的示例展示了使用命名参数进行批量更新的方法:

Java代码  

public class JdbcActorDao implements ActorDao {  

    private SimpleJdbcTemplate simpleJdbcTemplate;  

  

    public void setDataSource(DataSource dataSource) {  

        this.simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource);  

    }  

  

    public int[] batchUpdate(final List<Actor> actors) {  

        SqlParameterSource[] batch = SqlParameterSourceUtils.createBatch(actors.toArray());  

        int[] updateCounts = simpleJdbcTemplate.batchUpdate(  

                "update t_actor set first_name = :firstName, last_name = :lastName where id = :id",  

                batch);  

        return updateCounts;  

    }  

  

    //  ... additional methods  

}  

 

对于使用传统的“?”作为参数占位符的情况,你可以传入一个List,包含了所有需要进行批量更新的对象。这样的对象数组必须与每个SQL Statement的占位符以及他们在SQL Statement中出现的位置一一对应。

下面是同样的例子,使用的传统的“?”作为参数占位符:

Java代码  

public class JdbcActorDao implements ActorDao {  

    private SimpleJdbcTemplate simpleJdbcTemplate;  

  

    public void setDataSource(DataSource dataSource) {  

        this.simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource);  

    }  

  

    public int[] batchUpdate(final List<Actor> actors) {  

        List<Object[]> batch = new ArrayList<Object[]>();  

        for (Actor actor : actors) {  

            Object[] values = new Object[] {  

                    actor.getFirstName(),  

                    actor.getLastName(),  

                    actor.getId()};  

            batch.add(values);  

        }  

        int[] updateCounts = simpleJdbcTemplate.batchUpdate(  

                "update t_actor set first_name = ?, last_name = ? where id = ?",  

                batch);  

        return updateCounts;  

    }  

  

    //  ... additional methods  

}  

 所有的批量更新的方法都会返回一组int的数组,表示在整个操作过程中有多少记录被批量更新。 这个数量是由JDBC驱动所返回的,有时这个返回并不可靠,尤其对于某些JDBC驱动只是简单的返回-2作为返回值

 

 

 

 【转】Spring JDBC Framework详解——批量JDBC操作、ORM映射  

 

2010-03-23 23:59:07|  分类: 框架、源码 |字号 订阅

这篇文章介绍的spring的jdbc操作比较全面,值得参考:

 

作者:niumd,转载请注明出处,谢谢   

 

发表时间:2010 年 03 月 17 日  

 

原文链接:http://ari.javaeye.com/admin/blogs/618449

 

 

 

一、Spring JDBC 概述

 

     Spring 提供了一个强有力的模板类JdbcTemplate简化JDBC操作,DataSource,JdbcTemplate都可以以Bean的方式定义在想xml配置文件,JdbcTemplate创建只需注入一个DataSource,应用程序Dao层只需要继承JdbcDaoSupport, 或者注入JdbcTemplate,便可以获取JdbcTemplate,JdbcTemplate是一个线程安全的类,多个Dao可以注入一个JdbcTemplate;

 

 

 

 

 

Xml代码 

<!--         Oracle数据源           -->  

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">  

        <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>  

        <property name="url" value="jdbc:oracle:thin:@oracle.devcake.co.uk:1521:INTL"/>  

        <property name="username" value="sa"/>  

        <property name="password" value=""/>  

</bean>  

  

  

<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">  

        <property name="dataSource" ref="dataSource"/>  

 </bean>  

<!--  set注入方式获取jdbcTemplate -->  

<bean id="customerDao" class="JdbcCustomerDao" >  

         <property name="jdbcTemplate" ref="jdbcTemplate"/>  

</bean>  

<!-- 注入dataSource,customerDao通过继承JdbcDaoSupport ,使用this.getJdbcTemplate()获取JdbcTemplate   -->  

<bean id="customerDao" class="JdbcCustomerDao" >  

         <property name="dataSource" ref="dataSource"/>  

</bean>  

 

 

然后将jdbcTemplate对象注入自定义的Dao、或者继承JdbcDaoSupport,例如:

 

Java代码 

public class JdbcCustomerDao extends JdbcDaoSupport implements CustomerDao {   

}   

  

public class JdbcCustomerDao implements CustomerDao {   

  

          private JdbcTemplate jdbcTemplate   

  

         public void setJdbcTemplate()JdbcTemplate jdbcTemplate{   

               this.jdbcTemplate=jdbcTemplate   

         }   

}  

 

 

 

二、 JdbcTemplate 提供以下主要方法简化JDBC操作:

 

 

 

 

 

2.1、List query(String sql,Ojbect[] args,RowMapper rowMapper)

 

     说明:常用的查询,sql待执行的sql语句,args是sql语句的参数,rowMapper负责将每一行记录转化为java对象存放在list,并最终返回,例如:

 

Java代码 

public List<Book> queryByAuthor(String author) {   

        String sql = "select * from book where author=?";   

        Collection c = getJdoTemplate().find(sql,   

                new Object[] { author },new BookRowMapper());   

        List<Book> books = new ArrayList<Book>();   

        books.addAll(c);   

        return books;   

}   

  

class BookRowMapper implements RowMapper{   

     public Object mapRow(ResultSet res, int index) throws SQLException {   

          Book book = new Book();   

          book.setId(rs.getInt("id"));   

          //省略set   

       return book;   

    }   

}  

 

 

   更新、删除、其他查询操作类似,举例如下,详细细节请参考spring api:

 

 

 

Java代码 

//返回值为一个长整形   

public long getAverageAge() {   

    return getJdbcTemplate().queryForLong("SELECT AVG(age) FROM employee");   

  }   

//返回一个整数   

public int getTotalNumberOfEmployees() {   

    return getJdbcTemplate().queryForInt("SELECT COUNT(0) FROM employees");   

  }   

  

//更新操作   

this.jdbcTemplate.update(   

        "insert into t_actor (first_name, surname) values (?, ?)",    

        new Object[] {"Leonor", "Watling"});  

 

 

 

 

 2.2、spring 2.5新功能,另类的jdbc ORM:BeanPropertyRowMapper

 

 

 

      上面我们检索时必须实现RowMapper,将结果集转化为java对象。Spring2.5 简化了这一操作,使得我们不必再实现RowMapper,实现此功能的俩个神奇东东便是:ParameterizedRowMapper,ParameterizedBeanPropertyRowMapper,貌似通过java反射机制实现了将resultset字段映射到java对象,但是数据表的列必须和java对象的属性对应,没有研究源码,有点类似于apache 的BeanUtil,不知为何这部分在spring开发参考手册没有,难道不是经典。

 

 

 

 

 

Java代码 

//使用ParameterizedBeanPropertyRowMapper   

@SuppressWarnings({"unchecked"})   

  public List<Customer> getAll() {   

      return getJdbcTemplate().query("select * from t_customer", ParameterizedBeanPropertyRowMapper.newInstance(Customer.class));   

  }   

  

//使用BeanPropertyRowMapper   

@SuppressWarnings({"unchecked"})   

  public List<Customer> getAll() {   

      return getJdbcTemplate().query("select * from t_customer", new BeanPropertyRowMapper(Customer.class));   

  }  

 

 

 

 

注意:ParameterizedBeanPropertyRowMapper是BeanPropertyRowMapper子类。另外表的字段名称必须和实体类的成员变量名称一致;

 

 

 

2.3、spring之JDBC批量操作

 

      jdbcTemplate.batchUpdate(final String[] sql) ,API解释:Issue multiple SQL updates on a single JDBC Statement using batching,翻译过来大致为:解决多个sql的插入、更新、删除操作在一个Statement中。性能一般。

 

   jdbcTemplate.batchUpdate(String sql, final BatchPreparedStatementSetter pss),类似于JDBC的PreparedStatement,性能较上着有所提高。

 

   我们举例说明如何使用,示例如下:

 

Java代码 

final int count = 2000;   

    final List<String> firstNames = new ArrayList<String>(count);   

    final List<String> lastNames = new ArrayList<String>(count);   

    for (int i = 0; i < count; i++) {   

      firstNames.add("First Name " + i);   

      lastNames.add("Last Name " + i);   

    }   

    jdbcTemplate.batchUpdate(   

            "insert into customer (id, first_name, last_name, last_login, comments) values (?, ?, ?, ?, ?)",   

            new BatchPreparedStatementSetter() {   

           //为prepared statement设置参数。这个方法将在整个过程中被调用的次数   

        public void setValues(PreparedStatement ps, int i) throws SQLException {   

                ps.setLong(1, i + 10);   

                ps.setString(2, firstNames.get(i));   

                ps.setString(3, lastNames.get(i));   

                ps.setNull(4, Types.TIMESTAMP);   

                ps.setNull(5, Types.CLOB);   

              }   

              //返回更新的结果集条数   

          public int getBatchSize() {   

                   return count;   

              }   

            });   

  }  

 

 

 

 

  BatchSqlUpdate类是SqlUpdate 的子类,适用于插入、删除、更新批量操作,内部使用PreparedStatement,所以效率很高,批量语句达到设定的batchSize,或者手动调用flush才会执行批量操作。注意:此类是非线程安全的,必须为每个使用者创建一个实例,或者在同一个线程中使用前调用reset。

 

   下面我们举例说明如何使用BatchSqlUpdate,来执行批量操作。示例如下:

 

Java代码 

class BatchInsert extends BatchSqlUpdate {   

  private static final String SQL = "insert into t_customer (id, first_name, last_name, last_login, "  

      + "comments) values (?, ?, ?, ?, null)";   

  

  BatchInsert(DataSource dataSource) {   

    super(dataSource, SQL);   

    declareParameter(new SqlParameter(Types.INTEGER));   

    declareParameter(new SqlParameter(Types.VARCHAR));   

    declareParameter(new SqlParameter(Types.VARCHAR));   

    declareParameter(new SqlParameter(Types.TIMESTAMP));   

  

    setBatchSize(10);   

  }   

  

}  

 

 

Java代码 

int count = 5000;   

    for (int i = 0; i < count; i++) {   

      batchInsert.update(new Object[] { i + 100L, "a" + i, "b" + i, null });   

    }  

0 0
原创粉丝点击