zoukankan      html  css  js  c++  java
  • 开涛spring3(7.4)

     7.4  Spring提供的其它帮助

    7.4.1  SimpleJdbc方式

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

     

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

        @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: 用于调用存储过程及自定义函数,本类用于简化存储过程及自定义函数调用。

        @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方法执行自定义函数;
        @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中的解释。

        @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 获取自动生成主键方式:

        @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 获取自动生成主键方式:

    @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 批处理: 支持普通的批处理及占位符批处理;

        @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方法执行需要批处理的语句即可。

        @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 批处理: 支持命名参数批处理;

        @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 批处理: 已更简单的方式进行批处理;

        @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 批处理:

        @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)方法执行批处理。  

  • 相关阅读:
    Linux下编译安装redis
    docker搭建swoole的简易的聊天室
    Linux下面安装swoole
    laravel命令
    史上最污技术解读,60 个 IT 术语我竟然秒懂了.....
    redis集群搭建
    Windows安装MongoDB
    十大经典排序算法(动图演示)
    消息中间件基础
    laravel邮件发送
  • 原文地址:https://www.cnblogs.com/crazylqy/p/4315330.html
Copyright © 2011-2022 走看看