收藏私塾在线
 

欢迎您来到私塾在线网!   

请登录! 

免费注册 


zhang的笔记
状态: 离线
人气:5107342
访问用户量:4228
笔记经验:
总积分:261656
级别:VIP5
搜索本笔记
ta的交流分类
ta的交流主题贴(544)
ta的所有交流贴(1049)
ta的全部笔记
全部笔记(255)
未分类笔记(1)
Java Web(9)
并发实践(1)
课程问题(0)
Java(22)
架构(1)
缓存(5)
JavaEE(0)
JVM(12)
跟我学spring3(68)
Spring Sec……(43)
Spring 3.x……(25)
Spring Sec……(20)
跟开涛学Spring……(17)
深入剖析Spring……(18)
性能调优(10)
前端(2)
Tomcat源码解读(1)
spring sec……(0)
存档
2014-01(7)
2013-12(10)
2012-10(4)
2012-09(2)
2012-08(31)
2012-07(10)
2012-06(5)
2012-05(41)
2012-04(3)
2012-03(41)
2012-02(54)
2011-11(17)
2011-10(30)

2012-12-27 09:10:54
【第七章】 对JDBC的支持 之 7.4 Spring提供的其它帮助 ——跟我学spring3
浏览(28190)|评论(1)   交流分类:Java|笔记分类: 跟我学spring3

 7.4  Spring提供的其它帮助

7.4.1  SimpleJdbc方式

       Spring JDBC抽象框架提供SimpleJdbcInsert和SimpleJdbcCall类,这两个类通过利用JDBC驱动提供的数据库元数据来简化JDBC操作。

 

1、SimpleJdbcInsert:用于插入数据,根据数据库元数据进行插入数据,本类用于简化插入操作,提供三种类型方法:execute方法用于普通插入、executeAndReturnKey及executeAndReturnKeyHolder方法用于插入时获取主键值、executeBatch方法用于批处理。

 

java代码:
@Test
public void testSimpleJdbcInsert() {
    SimpleJdbcInsert insert = new SimpleJdbcInsert(jdbcTemplate);
    insert.withTableName("test");
    Map<String, Object> args = new HashMap<String, Object>();
    args.put("name", "name5");
    insert.compile();
    //1.普通插入
    insert.execute(args);
    Assert.assertEquals(1, jdbcTemplate.queryForInt("select count(*) from test"));
    //2.插入时获取主键值
    insert = new SimpleJdbcInsert(jdbcTemplate);
    insert.withTableName("test");
    insert.setGeneratedKeyName("id");
    Number id = insert.executeAndReturnKey(args);
    Assert.assertEquals(1, id);
    //3.批处理
    insert = new SimpleJdbcInsert(jdbcTemplate);
    insert.withTableName("test");
    insert.setGeneratedKeyName("id");
    int[] updateCount = insert.executeBatch(new Map[] {args, args, args});
    Assert.assertEquals(1, updateCount[0]);
    Assert.assertEquals(5, jdbcTemplate.queryForInt("select count(*) from test"));
}
  • new SimpleJdbcInsert(jdbcTemplate)首次通过DataSource对象或JdbcTemplate对象初始化SimpleJdbcInsert;
  • insert.withTableName("test")用于设置数据库表名;
  • args用于指定插入时列名及值,如本例中只有name列名,即编译后的sql类似于“insert into test(name) values(?)”;
  • insert.compile()可选的编译步骤,在调用执行方法时自动编译,编译后不能再对insert对象修改;
  • 执行:execute方法用于执行普通插入;executeAndReturnKey用于执行并获取自动生成主键(注意是Number类型),必须首先通过setGeneratedKeyName设置主键然后才能获取,如果想获取复合主键请使用setGeneratedKeyNames描述主键然后通过executeReturningKeyHolder获取复合主键KeyHolder对象;executeBatch用于批处理;

 

2、SimpleJdbcCall:用于调用存储过程及自定义函数,本类用于简化存储过程及自定义函数调用。

 

java代码:
@Test
public void testSimpleJdbcCall1() {
    //此处用mysql,因为hsqldb调用自定义函数和存储过程一样
    SimpleJdbcCall call = new SimpleJdbcCall(getMysqlDataSource());
    call.withFunctionName("FUNCTION_TEST");
    call.declareParameters(new SqlOutParameter("result", Types.INTEGER));
    call.declareParameters(new SqlParameter("str", Types.VARCHAR));
    Map<String, Object> outVlaues = call.execute("test");
    Assert.assertEquals(4, outVlaues.get("result"));
}
  • new SimpleJdbcCall(getMysqlDataSource()):通过DataSource对象或JdbcTemplate对象初始化SimpleJdbcCall;
  • withFunctionName("FUNCTION_TEST")定义自定义函数名;自定义函数sql语句将被编译为类似于{?= call …}形式;
  • declareParameters描述参数类型,使用方式与StoredProcedure对象一样;
  • 执行:调用execute方法执行自定义函数;

 

java代码:
@Test
public void testSimpleJdbcCall2() {
    //调用hsqldb自定义函数得使用如下方式
    SimpleJdbcCall call = new SimpleJdbcCall(jdbcTemplate);
    call.withProcedureName("FUNCTION_TEST");
call.declareParameters(new SqlReturnResultSet("result",
new ResultSetExtractor<Integer>() {
        @Override
        public Integer extractData(ResultSet rs)
throws SQLException, DataAccessException {
          while(rs.next()) {
            return rs.getInt(1);
          }
          return 0;
    }}));
    call.declareParameters(new SqlParameter("str", Types.VARCHAR));
    Map<String, Object> outVlaues = call.execute("test");
    Assert.assertEquals(4, outVlaues.get("result"));
}

 

 

调用hsqldb数据库自定义函数与调用mysql自定义函数完全不同,详见StoredProcedure中的解释。

 

java代码:
@Test
public void testSimpleJdbcCall3() {
  SimpleJdbcCall call = new SimpleJdbcCall(jdbcTemplate);
  call.withProcedureName("PROCEDURE_TEST");
  call.declareParameters(new SqlInOutParameter("inOutName", Types.VARCHAR));
  call.declareParameters(new SqlOutParameter("outId", Types.INTEGER));
  SqlParameterSource params =
  new MapSqlParameterSource().addValue("inOutName", "test");
  Map<String, Object> outVlaues = call.execute(params);
  Assert.assertEquals("Hello,test", outVlaues.get("inOutName"));
  Assert.assertEquals(0, outVlaues.get("outId"));
}

 

与自定义函数调用不同的是使用withProcedureName来指定存储过程名字;其他参数描述等完全一样。

 

7.4.2  控制数据库连接

       Spring JDBC通过DataSource控制数据库连接,即通过DataSource实现获取数据库连接。

       Spring JDBC提供了一下DataSource实现:

  • DriverManagerDataSource:简单封装了DriverManager获取数据库连接;通过DriverManager的getConnection方法获取数据库连接;
  • SingleConnectionDataSource:内部封装了一个连接,该连接使用后不会关闭,且不能在多线程环境中使用,一般用于测试;
  • LazyConnectionDataSourceProxy:包装一个DataSource,用于延迟获取数据库连接,只有在真正创建Statement等时才获取连接,因此再说实际项目中最后使用该代理包装原始DataSource从而使得只有在真正需要连接时才去获取。

第三方提供的DataSource实现主要有C3P0、Proxool、DBCP等,这些实现都具有数据库连接池能力。

 

DataSourceUtils:Spring JDBC抽象框架内部都是通过它的getConnection(DataSource dataSource)方法获取数据库连接,releaseConnection(Connection con, DataSource dataSource) 用于释放数据库连接,DataSourceUtils用于支持Spring管理事务,只有使用DataSourceUtils获取的连接才具有Spring管理事务。

 

7.4.3  获取自动生成的主键

       有许多数据库提供自动生成主键的能力,因此我们可能需要获取这些自动生成的主键,JDBC 3.0标准支持获取自动生成的主键,且必须数据库支持自动生成键获取。

1)JdbcTemplate获取自动生成主键方式:

 

java代码:
@Test
public void testFetchKey1() throws SQLException {
    final String insertSql = "insert into test(name) values('name5')";
    KeyHolder generatedKeyHolder = new GeneratedKeyHolder();
    jdbcTemplate.update(new PreparedStatementCreator() {
        @Override
       public PreparedStatement createPreparedStatement(Connection conn)
            throws SQLException {
            return conn.prepareStatement(insertSql, new String[]{"ID"});
      }}, generatedKeyHolder);
    Assert.assertEquals(0, generatedKeyHolder.getKey());
}

 

使用JdbcTemplate的update(final PreparedStatementCreator psc, final KeyHolder generatedKeyHolder)方法执行需要返回自动生成主键的插入语句,其中psc用于创建PreparedStatement并指定自动生成键,如“prepareStatement(insertSql, new String[]{"ID"})”;generatedKeyHolder是KeyHolder类型,用于获取自动生成的主键或复合主键;如使用getKey方法获取自动生成的主键。

 

2)SqlUpdate获取自动生成主键方式:

 

java代码:
@Test
public void testFetchKey2() {
    final String insertSql = "insert into test(name) values('name5')";
    KeyHolder generatedKeyHolder = new GeneratedKeyHolder();
    SqlUpdate update = new SqlUpdate();
    update.setJdbcTemplate(jdbcTemplate);
    update.setReturnGeneratedKeys(true);
    //update.setGeneratedKeysColumnNames(new String[]{"ID"});
    update.setSql(insertSql);
    update.update(null, generatedKeyHolder);
    Assert.assertEquals(0, generatedKeyHolder.getKey());
}
 

 

SqlUpdate获取自动生成主键方式和JdbcTemplate完全一样,可以使用setReturnGeneratedKeys(true)表示要获取自动生成键;也可以使用setGeneratedKeysColumnNames指定自动生成键列名。

 

3)SimpleJdbcInsert前边示例已介绍,此处就不演示了。

 

7.4.4  JDBC批量操作

       JDBC批处理用于减少与数据库交互的次数来提升性能,Spring JDBC抽象框架通过封装批处理操作来简化批处理操作

1)JdbcTemplate批处理:支持普通的批处理及占位符批处理;

 

java代码:
@Test
public void testBatchUpdate1() {
    String insertSql = "insert into test(name) values('name5')";
    String[] batchSql = new String[] {insertSql, insertSql};
    jdbcTemplate.batchUpdate(batchSql);
    Assert.assertEquals(2, jdbcTemplate.queryForInt("select count(*) from test"));
}

 

       直接调用batchUpdate方法执行需要批处理的语句即可。

 

java代码:
@Test
public void testBatchUpdate2() {
    String insertSql = "insert into test(name) values(?)";
    final String[] batchValues = new String[] {"name5", "name6"};
    jdbcTemplate.batchUpdate(insertSql, new BatchPreparedStatementSetter() {
        @Override
        public void setValues(PreparedStatement ps, int i) throws SQLException {
            ps.setString(1, batchValues[i]);
        }
        @Override
        public int getBatchSize() {
            return batchValues.length;
        }
    });
    Assert.assertEquals(2, jdbcTemplate.queryForInt("select count(*) from test"));
}

 

       JdbcTemplate还可以通过batchUpdate(String sql, final BatchPreparedStatementSetter pss)方法进行批处理,该方式使用预编译语句,然后通过BatchPreparedStatementSetter实现进行设值(setValues)及指定批处理大小(getBatchSize)。

 

2)NamedParameterJdbcTemplate批处理:支持命名参数批处理;

 

java代码:
@Test
public void testBatchUpdate3() {
    NamedParameterJdbcTemplate namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(jdbcTemplate);
    String insertSql = "insert into test(name) values(:myName)";
    UserModel model = new UserModel();
    model.setMyName("name5");
    SqlParameterSource[] params = SqlParameterSourceUtils.createBatch(new Object[] {model, model});
    namedParameterJdbcTemplate.batchUpdate(insertSql, params);
    Assert.assertEquals(2, jdbcTemplate.queryForInt("select count(*) from test"));
}

 

 

通过batchUpdate(String sql, SqlParameterSource[] batchArgs)方法进行命名参数批处理,batchArgs指定批处理数据集。SqlParameterSourceUtils.createBatch用于根据JavaBean对象或者Map创建相应的BeanPropertySqlParameterSource或MapSqlParameterSource。

 

3) SimpleJdbcTemplate批处理:已更简单的方式进行批处理;

 

 

java代码:
@Test
public void testBatchUpdate4() {
    SimpleJdbcTemplate simpleJdbcTemplate = new SimpleJdbcTemplate(jdbcTemplate);
    String insertSql = "insert into test(name) values(?)";
    List<Object[]> params = new ArrayList<Object[]>();
    params.add(new Object[]{"name5"});
    params.add(new Object[]{"name5"});
    simpleJdbcTemplate.batchUpdate(insertSql, params);
    Assert.assertEquals(2, jdbcTemplate.queryForInt("select count(*) from test"));
}

       本示例使用batchUpdate(String sql, List<Object[]> batchArgs)方法完成占位符批处理,当然也支持命名参数批处理等。

 

 

4)SimpleJdbcInsert批处理:

 

 

java代码:
@Test
public void testBatchUpdate5() {
    SimpleJdbcInsert insert = new SimpleJdbcInsert(jdbcTemplate);
    insert.withTableName("test");
    Map<String, Object> valueMap = new HashMap<String, Object>();
    valueMap.put("name", "name5");
    insert.executeBatch(new Map[] {valueMap, valueMap});
   Assert.assertEquals(2, jdbcTemplate.queryForInt("select count(*) from test"));
}

 

       如代码所示,使用executeBatch(Map<String, Object>[] batch)方法执行批处理。       

 

 

原创内容,转载请注明出处【http://sishuok.com/forum/blogPost/list/0/2492.html

精品视频课程推荐

透彻理解JavaBean视频教程
深入浅出的讲解JavaBen的写法、JavaBean的用法、JavaBean的实现机制、JavaBean对应翻译的代码理解。

研磨设计模式——跟着cc学设计系列视频教程
本视频课程是北京Java私塾原创精品书籍《研磨设计模式》一书的配套学习视频,由《研磨设计模式》的第一作者CC录制 课程目标:全面、系统的掌握GoF设计模式的知识,达到可以在实际项目开发中运用的能力 技术要点:如何实现可配置、如何实现缓存以及缓存的管理、如何实现用缓存来控制多实例的创建、如何实现参数化工厂、 如何实现可扩展工厂、如何实现原型管理器、如何实现Java的静态代理和动态代理、如何实现多线程处理队列请求、 如何实现命令的参数化配置、可撤销的操作、宏命令、队列请求和日志请求、如何实现翻页迭代、如何检测环状结构、 如何实现通用的增删改查、如何模拟工作流来处理流程、如何实现简单又通用的XML读取、如何实现模拟AOP的功能......

ssh+jbpm项目(某集团OA)视频教程
达到能综合使用Struts2+Spring3+Hibernate3+Jbpm4来进行实际项目开发的能力。 包括:ssh和jbpm的整合;数据字典;通用DAO(Spring+Hibernate+泛型+反射+SpEL+模板方法模式);自动生成UUID的加强版;分层开发、SSH联合的基本开发;翻页的taglib;示范真实值和表现值,数据参照的实现;文件上传下载;主子表操;登录验证码;登录控制的拦截器

Ajax+JSON基础实战视频教程
数据校验、Javascript模拟多线程、下拉列表联动、操作XML、AJAX结合JSON的操作、Json-lib的使用

XML基础视频教程
创建规范的XML文档,DTD的作用,并且可以根据要求创建私用的DTD,通过JavaScript解析XML DOM

浏览(28190)|评论(1)   交流分类:Java|笔记分类: 跟我学spring3

评论(1)
1楼 UncleRayRay  2012-12-27 引用

请问一下老师在

1)JdbcTemplate批处理 

中,如果我的batchValues比较大,几千或者几万条数据一起传过来执行此函数,Spring会一次性把所有的值都commit还是边处理边commit?假如一次性commit的话,会造成性能下降,请问有什么办法可以解决?

请登录后评论 登录

关于我们 | 联系我们 | 用户协议 | 私塾在线服务协议 | 版权声明 | 隐私保护

版权所有 Copyright(C)2009-2012 私塾在线学习网