zoukankan      html  css  js  c++  java
  • Spring JDBC最佳实践(3)

    pring jdbc包提供了JdbcTemplate和它的两个兄弟SimpleJdbcTemplate和NamedParameterJdbcTemplate,我们可以先从JdbcTemplate入手,领略一下这个类的便利和优雅。 
    1、使用JdbcTemplate进行数据访问: 
    初始化JdbcTemplate 
    初始化JdbcTemplate很容易,只需要向它的构造方法传入它所使用的DataSource便可以。如果使用Jakarta Commons DBCP,那么初始化代码如下所示: 
    1BasicDataSource dataSource = new BasicDataSource();
    2dataSource.setDriverClassName("com.mysql.jdbc.Driver");
    3dataSource.setUrl("jdbc:mysql://localhost/mysql?characterEncoding=gb2312");
    4dataSource.setUsername("***");
    5dataSource.setPassword("***");
    6JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);

    也可以通过无参的构造方法构造JdbcTemplate,然后通过setDataSource(DataSource dataSource)来设置其dataSource。
    上述这种方法是通过编码的方式构造JdbcTemplate,如果应用程序使用spring的IOC容器,其初始化工作便可移植到容器的配置文件当中:

    01<!-- dataSource -->
    02<bean id="dataSource"
    03    class="org.apache.commons.dbcp.BasicDataSource"
    04    destroy-method="close">
    05     
    06    <property name="driverClassName">
    07        <value>com.mysql.jdbc.Driver</value>
    08    </property>
    09    <property name="url" value="jdbc:mysql://localhost:3306/oa?characterEncoding=gb2312" />
    10    <property name="username" value="root" />
    11    <property name="password" value="root" />
    12    <property name="maxActive" value="100" />
    13    <property name="maxIdle" value="30" />
    14    <property name="maxWait" value="1000" />
    15    <property name="defaultAutoCommit" value="true" />
    16    <property name="removeAbandoned" value="true" />
    17</bean>
    18<!-- jdbcTemplate -->
    19<bean id="jdbc"
    20    class="org.springframework.jdbc.core.JdbcTemplate">
    21    <property name="dataSource">
    22        <ref bean="dataSource" />
    23    </property>
    24</bean>

    之后,想把jdbcTemplate注入到哪个bean都可以,初始化好了JdbcTemplate以后,便可以大施拳脚了!

    使用JdbcTemplate查询数据:
    JdbcTemplate针对数据查询提供了多个重载的模板方法,我们可以根据需要选用不同的模板方法。如果查询很简单,仅仅是传入相应的SQL或者是相关的参数,然后取得一个结果,那么我们可以用如下的一组便利的模板方法:

    1public int queryForInt(String sql)

    1public int queryForInt(String sql, Object[] args)

    1public int queryForInt(String sql, Object[] args)

    1public long queryForLong(String sql)

    1public long queryForLong(String sql, Object[] args)

    1public long queryForLong(String sql, Object[] args, int[] argTypes)

    1public Object queryForObject(String sql, Class requiredType)

    1public Object queryForObject(String sql, Object[] args, int[] argTypes, Class requiredType)

    1public Object queryForObject(String sql, Object[] args, int[] argTypes, RowMapper rowMapper)

    1public Object queryForObject(String sql, Object[] args, Class requiredType)

    1public Object queryForObject(String sql, Object[] args, RowMapper rowMapper)

    1public Object queryForObject(String sql, RowMapper rowMapper)

    注意:这些针对的resultset返回的必须是一行记录,否则会出错! 
     如果查询的结果包含一列数字型的结果,或者使用了SQL函数,或者其它的单列的结果,那么便可以直接通过这组便利的模板方法进行查询: 
    1int postId = jdbcTemplate.queryForInt("SELECT POSTID FROM USERS WHERE USERNAME=?",new String[]{"jason"});
    2System.out.println(postId);
    3long userCount = jdbcTemplate.queryForLong("SELECT COUNT(*) FROM USERS");
    4System.out.println(userCount);
    5String nickname = (String)jdbcTemplate.queryForObject("SELECT USERNAME1 FROM USERS WHERE USERNAME='jason'", String.class);
    6System.out.println(nickname);
    7Map singleUser = jdbcTemplate.queryForMap("SELECT * FROM USERS WHERE USERNAME = 'jason'");
    8System.out.println(singleUser);

    queryForMap与其它的方法的不同之处在于它的查询的结果以java.util.Map的形式返回,Map的键对应查询的表的列的名字,Map的值对应键所在的列的值。

    如果查询的结果返回多行,而我们又不在乎他们是否拥有较强的约束类型,那么可以用以下的模板方法:

    1public List queryForList(String sql)

    1public List queryForList(String sql, Object[] args)
    1public List queryForList(String sql, Object[] args, int[] argTypes)

    queryForList()方法根据传入的sql以及相应的参数执行查询,将查询的结果以java.util.List的形式返回,返回的java.util.List中的每个元素都是java.lang.Map类型,分别对应结果集中的一行,Map的键对应每列的列名,Map的值对应当前列名对应的值.

    如果这些还不足以满足我们的需要,那么我们可以自己定义回调接口
    用于查询的回调接口有以下三种:
    org.springframework.jdbc.core.ResultSetExtractor,它是属于JdbcTemplate内部使用的Callback接口,相对于下面的两个接口,这个接口拥有更多的控制权,因为在使用它的时候,我们需要自行的处理ResultSet,该接口的定义如下:

    01package org.springframework.jdbc.core;
    02 
    03import java.sql.ResultSet;
    04import java.sql.SQLException;
    05 
    06import org.springframework.dao.DataAccessException;
    07 
    08public interface ResultSetExtractor {
    09 
    10     
    11    Object extractData(ResultSet rs) throws SQLException, DataAccessException;
    12 
    13}

    我们可以将处理的结果以任意的形式包装后返回

    org.springframework.jdbc.core.RowCallbackHandler 相对于ResultSetExtractor,它只关注单行结果的处理,处理的结果可以根据需要存放在当前的RowCallbackHandler,或者使用JdbcTemplate中,当然,这完全看个人喜好,接口定义如下:

    01package org.springframework.jdbc.core;
    02 
    03import java.sql.ResultSet;
    04import java.sql.SQLException;
    05 
    06public interface RowCallbackHandler {
    07 
    08    void processRow(ResultSet rs) throws SQLException;
    09 
    10}<span style="font-family:''sans serif', tahoma, verdana, helvetica';font-size:x-small;"><span style="line-height:19px;white-space:normal;"> </span></span>

    org.springframework.jdbc.core.RowMapper  它是 ResultSetExtractor的精简版,功能类似于 RowCallbackHandler,也是只关注当行结果的处理。不过它的返回的结果会有 ResultSetExtractor实现类进行组合。RowMapper的接口定义如下:
    01package org.springframework.jdbc.core;
    02 
    03import java.sql.ResultSet;
    04import java.sql.SQLException;
    05 
    06public interface RowMapper {
    07 
    08     Object mapRow(ResultSet rs, int rowNum) throws SQLException;
    09 
    10}

    为了说明这三种回调接口的使用方法,我们暂时设置如下的场景: 假设我们有一表users,里面有userid,username,userpwd三个字段,我们为此建立了一个JavaBean:

    01package com.google.spring.jdbc;
    02 
    03public class UserBean
    04{
    05    private Integer userId;
    06    private String username;
    07    private String userpwd;
    08    public Integer getUserId()
    09    {
    10        return userId;
    11    }
    12    public void setUserId(Integer userId)
    13    {
    14        this.userId = userId;
    15    }
    16    public String getUsername()
    17    {
    18        return username;
    19    }
    20    public void setUsername(String username)
    21    {
    22        this.username = username;
    23    }
    24    public String getUserpwd()
    25    {
    26        return userpwd;
    27    }
    28    public void setUserpwd(String userpwd)
    29    {
    30        this.userpwd = userpwd;
    31    }
    32     
    33}

    使用自定义的ResultSetExtractor,可以如下进行处理:

    01List users = (List)jdbcTemplate.query("SELECT * FROM USERS WHERE USERNAME LIKE '%n%'", new ResultSetExtractor()
    02{
    03     
    04    @Override
    05    public Object extractData(ResultSet rs) throws SQLException,
    06            DataAccessException
    07    {
    08        List users = new ArrayList();
    09        while(rs.next())
    10        {
    11            UserBean userBean = new UserBean();
    12            userBean.setUserId(rs.getInt("userId"));
    13            userBean.setUsername(rs.getString("username"));
    14            userBean.setUserpwd(rs.getString("userpwd"));
    15            users.add(userBean);
    16        }
    17        return users;
    18    }
    19});
    20System.out.println(users);

    使用RowMapper,可进行如下的处理:

    01List users = jdbcTemplate.query("SELECT * FROM USERS WHERE USERNAME LIKE '%n%'", new RowMapper()
    02{
    03     
    04    @Override
    05    public Object mapRow(ResultSet rs, int rowNum) throws SQLException
    06    {
    07        UserBean userBean = new UserBean();
    08        userBean.setUserId(rs.getInt("userId"));
    09        userBean.setUsername(rs.getString("username"));
    10        userBean.setUserpwd(rs.getString("userpwd"));
    11        return userBean;
    12    }
    13});
    14System.out.println(users.size());

    使用RowCallbackHandler可进行如下的处理:

    01final List users = new ArrayList();
    02jdbcTemplate.query("SELECT * FROM USERS WHERE USERNAME LIKE '%n%'", new RowCallbackHandler()
    03{
    04     
    05    @Override
    06    public void processRow(ResultSet rs) throws SQLException
    07    {
    08        UserBean userBean = new UserBean();
    09        userBean.setUserId(rs.getInt("userId"));
    10        userBean.setUsername(rs.getString("username"));
    11        userBean.setUserpwd(rs.getString("userpwd"));
    12        users.add(userBean);
    13    }
    14});
    15System.out.println(users.size());

    使用这三种接口的差别如下:

  • 相关阅读:
    【YBTOJ】【Luogu P2605】[ZJOI2010]基站选址
    【CodeForces 261D】Maxim and Increasing Subsequence
    【Luogu P4140】奇数国
    【YBTOJ】【Luogu P6474】[NOI Online #2 入门组] 荆轲刺秦王
    【YBTOJ】【Luogu P4667】[BalticOI 2011 Day1]Switch the Lamp On
    Tools分类随笔链接整理贴(不定期更新)
    Vs2012安装介绍
    VC 修改对话框默认类名
    扫雷小游戏_通过爆破手段强制胜利
    C++ STL(十)算法
  • 原文地址:https://www.cnblogs.com/chenying99/p/2625932.html
Copyright © 2011-2022 走看看