spring-JDBC

Spring JDBC 抽象了JDBC API,下表标注X的表示在操作序列中,Spring和开发人员需要关注的操作

操作Spring开发人员
定义连接串 X
Open连接X 
指定SQL语句 X
定义参数和参数值 X
prepare和执行语句X 
循环处理结果集X 
每行结果记录怎么处理 X
处理异常X 
处理事务X 
关闭连接,statement,结果集X 

不同的JDBC 访问方式

Spring JDBC 提供了几种方法,以运用不同类与数据库的接口。除了JdbcTemplate之外,新的SimpleJdbcinsert SimpleJdbcCall两个类通过利用JDBC驱动提供的数据库元数据来简化JDBC操作,而RDBMS Object 样式采用了更类似于JDO Query 设计的面向对象的方法。

  • JdbcTemplate

JdbcTemplate是最经典的Spring JDBC 方法。这是一种底层的方法,其他方法内部都借助于JdbcTemplate 来完成

  • NamedParameterJdbcTemplate

NamedParameterJdbcTemplate 封装了JdbcTemplate以提供命名参数,而不是使用传统的JDBC "?"占位符。当一个SQL 语句有多个参数时,这种方法则呈现出了更好的可良性和易用性。

  • SimpleJdbclnsert SimpleJdbcCall

SimpleJdbcinsert 和SimpleJdbcCa ll 优化数据库元数据,以限制必要配置的数量。这种方法简化了编码,只需要提供表或存储过程的名称及与列名匹配的参数映射。这仅在数据库提供足够的元数据时有效。如果数据库不提供此元数据, 则必须提供参数的显式配置。

  • RDBMS Object

RDBMS Object 包括MappingSqlQuery 、SqlUpdate 和StoredProcedure ,需要在数据访问层初始化期间建立可重用的且是线程安全的对象。此方法在JDO Query之后建模,可以在其中定义查询字符串、声明参数并编译查询。一旦这样做,执行方法可以多次调用传人的各种参数值。

JDBC包层次结构

Spring JDBC 由4个不同的包构成,分别为core 、datasource、object和support 。

  • core:

org.springframework.jdbc.core 包包含JdbcTemplate和大量callback 接口以及相关类。org.springframework.jdbc.core.simple 包含 SimpleJdbcInsert SimpleJdbcCall classesorg.springframework.jdbc.core.namedparam 包含NamedParameterJdbcTemplate 以及相关支持类

  • datasource:

 org.springframework.jdbc.datasource包数据访问的实用工具类和多种DataSource的实现类,可以在Java EE 容器外测试JDBC代码。 org.springfamework.jdbc.datasource.embedded子包提供了使用Java 数据库引擎( 如HSQL 、H2 和Derby )创建嵌入式数据库的支持

  • object:

org.springframework.jdbc.object 为对象包,以面向对象的方式访问数据库。它允许执行查询并返回结果作为业务对象,可以在数据表的列和业务对象的属性之间映射查询结果。.

  • support:

 org.springframework.jdbc.support为支持包,提供了SQLException 转换功能和一些实用工具类,均是core包和object包的支持类。.

JDBC Core类

JdbcTemplate

JdbcTemplate类是线程安全的。

JdbcTemplate它用于处理资源的创建和释放,可以避免开发人员常见的JDBC使用错误,如忘记关闭连接。它执行核心JDBC工作流的基本任务,如语句创建和执行,使应用程序代码提供SQL并提取结果。JdbcTemplate可以

  • 执行Sql查询
  • update语句以及存储过程调用
  • 迭代ResultSet返回结果。
  • 捕获异常并转换为DAO异常。

使用JdbcTemplate 时,只需要实现回调接口即可PreparedStatementCreator 回调接口根据该类提供的Connection创建一个准备好的语句,提供SQL和任何必需的参数。CallableStatementCreator接口也是如此,该接口创建可调用语句。RowCallbackHandler接口从ResultSet的每一行提取值。
JdbcTemplate可以通过直接实例化DataSource引用在DAO实现中使用,或者在Spring IoC容器中配置并作为bean引用提供给DAO 。
DataSource 应始终在Spring IoC 容器中配置为一个bean 。在上述的第一种情况下,bean 直接提供给服务;在第二种情况下,它被提供给准备好的模板。

查询(Select)

 

int rowCount = this.jdbcTemplate.queryForObject("select count(*) from t_actor", Integer.class);

//绑定变量

int countOfActorsNamedJoe = this.jdbcTemplate.queryForObject(
        "select count(*) from t_actor where first_name = ?", Integer.class, "Joe");

//

String lastName = this.jdbcTemplate.queryForObject( "select last_name from t_actor where id = ?",        new Object[]{1212L}, String.class);

//查询和填充单个域对象,实现RowMapper类

Actor actor = this.jdbcTemplate.queryForObject(
        "select first_name, last_name from t_actor where id = ?",
        new Object[]{1212L},
        new RowMapper<Actor>() {
            public Actor mapRow(ResultSet rs, int rowNum) throws SQLException {
                Actor actor = new Actor();
                actor.setFirstName(rs.getString("first_name"));
                actor.setLastName(rs.getString("last_name"));
                return actor;
            }
        });       

//查询和填充多个域对象实现RowMapper类

List<Actor> actors = this.jdbcTemplate.query(
        "select first_name, last_name from t_actor",
        new RowMapper<Actor>() {
            public Actor mapRow(ResultSet rs, int rowNum) throws SQLException {
                Actor actor = new Actor();
                actor.setFirstName(rs.getString("first_name"));
                actor.setLastName(rs.getString("last_name"));
                return actor;
            }
        });   

Updating (INSERT, UPDATE, and DELETE)

//insert

this.jdbcTemplate.update(
        "insert into t_actor (first_name, last_name) values (?, ?)",
        "Leonor", "Watling");

//update

        this.jdbcTemplate.update(
        "update t_actor set last_name = ? where id = ?",
        "Banjo", 5276L);

其他操作

可以使用execute(..)方法来执行任意SQL ,因此该方法通常用于DDL 语句。

        this.jdbcTemplate.execute("create table mytable (id integer, name varchar(100))");
       

this.jdbcTemplate.update(
        "call SUPPORT.REFRESH_ACTORS_SUMMARY(?)",
        Long.valueOf(unionId));

NamedParameterJdbcTemplate

在经典的JDBC用法中,SQL参数是用占位轮“?”来表示的,这会受到位置的限制。这种方式的问题在于,一旦参数的顺序发生变化,就必须改变参数绑定。在Spring JDBC框架中,绑定SQL 参数的另一种选择是使用命名参数( named parameter ) 。

public int countOfActorsByFirstName(String firstName) {

    String sql = "select count(*) from T_ACTOR where first_name = :first_name";

    SqlParameterSource namedParameters = new MapSqlParameterSource("first_name", firstName);

    return this.namedParameterJdbcTemplate.queryForObject(sql, namedParameters, Integer.class);
}

// 基于Map的方式

public int countOfActorsByFirstName(String firstName) {

    String sql = "select count(*) from T_ACTOR where first_name = :first_name";

    Map<String, String> namedParameters = Collections.singletonMap("first_name", firstName);

    return this.namedParameterJdbcTemplate.queryForObject(sql, namedParameters,  Integer.class);
}

与NamedParameterJdbcTemplate相关的一个很好的功能是SqlParameterSource接口,SqlParameterSource是NamedParameterJdbcTemplate 的命名参数值的来源。

MapSqlParameterSource类是一个非常简单的实现,它只是一个围绕java.util.Map的适配器,其中键是参数名称,值是参数值。
另一个SqlParameterSource 实现是BeanPropertySqlParameterSource类。这个类包装了一个任意的JavaBean ,并使用包装的JavaBean的属性作为命名参数值的来源

public class Actor {
    private Long id;
    private String firstName;
    private String lastName;
    public String getFirstName() {
        return this.firstName;
    }
    public String getLastName() {
        return this.lastName;
    }
    public Long getId() {
        return this.id;
    }
}

//属性作为参数源

public int countOfActors(Actor exampleActor) {
    String sql = "select count(*) from T_ACTOR where first_name = :firstName and last_name = :lastName";
    SqlParameterSource namedParameters = new BeanPropertySqlParameterSource(exampleActor);
    return this.namedParameterJdbcTemplate.queryForObject(sql, namedParameters, Integer.class);
}

SQLExceptionTranslator

SQLExceptionTranslator是一个接口,其实现类可以用于SQLExceptions和Spring 自己的org.springframework.dao.DataAccessException 之间进行转换。

SQLErrorCodeSQLExceptionTranslator是SQLExceptionTranslator的默认实现。该实现使用特定的供应商代码,它比SQLState实现更精确。错误代码转换基于JavaBean 类型类SQLErrorCodes中保存的代码。该类由SQLErrorCodesFactory 创建和填充,顾名思义,它是一个根据名为sql-error-codes.xml的配置文件内容创建SQLErrorCodes 的工厂。该文件使用供应商代码填充,供应商代码从DatabaseMetaData获取DatabaseProductName。

public class CustomSQLErrorCodesTranslator extends SQLErrorCodeSQLExceptionTranslator {

    protected DataAccessException customTranslate(String task, String sql, SQLException sqlex) {

// 对错误码:-12345特殊处理
        if (sqlex.getErrorCode() == -12345) {
            return new DeadlockLoserDataAccessException(task, sqlex);
        }
        return null;
    }
}

检索自动生成的主键

update()方法支持检索由数据库生成的主键。这种支持是JDBC3.0标准的一部分。该方法将PreparedStatementCreator 作为其第一个参数,需要指定插入语句。另一个参数是KeyHolder,它包含从更新成功返回时生成的主键。

final String INSERT_SQL = "insert into my_test (name) values(?)";
final String name = "Rob";

KeyHolder keyHolder = new GeneratedKeyHolder();
jdbcTemplate.update(
    new PreparedStatementCreator() {
        public PreparedStatement createPreparedStatement(Connection connection) throws SQLException {
            PreparedStatement ps = connection.prepareStatement(INSERT_SQL, new String[] {"id"});
            ps.setString(1, name);
            return ps;
        }
    },
    keyHolder);

// keyHolder.getKey() now contains the generated key

数据库连接

DataSource

Spring通过一个DataSource(数据源)获得与数据库的连接。在使用Spring的JDBC时,可以从JNDI获取数据源,或者使用第三方提供的连接池实现来配置自己的数据源。流行的实现是Apache Jakarta Commons DBCP 和C3P0 。Spring 发行版本中的实现仅用于测试,并未提供连接池方案。所以在使用Spring的DriverManagerDataSource类时,仅用于测试目的,因为它不提供连接池的方案,在执行多个连接请求时性能较差。

  • 代码方式:

DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("org.hsqldb.jdbcDriver");
dataSource.setUrl("jdbc:hsqldb:hsql://localhost:");
dataSource.setUsername("sa");
dataSource.setPassword("");

  • Spring方式:

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="${jdbc.driverClassName}"/>
    <property name="url" value="${jdbc.url}"/>
    <property name="username" value="${jdbc.username}"/>
    <property name="password" value="${jdbc.password}"/>
</bean>

<context:property-placeholder location="jdbc.properties"/>

  • DBCP

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <property name="driverClassName" value="${jdbc.driverClassName}"/>
    <property name="url" value="${jdbc.url}"/>
    <property name="username" value="${jdbc.username}"/>
    <property name="password" value="${jdbc.password}"/>
</bean>

<context:property-placeholder location="jdbc.properties"/>

  • C3P0

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
    <property name="driverClass" value="${jdbc.driverClassName}"/>
    <property name="jdbcUrl" value="${jdbc.url}"/>
    <property name="user" value="${jdbc.username}"/>
    <property name="password" value="${jdbc.password}"/>
</bean>

<context:property-placeholder location="jdbc.properties"/>

 

 

 

更多信息:https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/data-access.html#jdbc

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值