Cook JDBC with SpringFramework

2008-02-23 09:31:12来源:互联网 阅读 ()

新老客户大回馈,云服务器低至5折

我们的目标是希望在任何使用JDBC的场合都能够利用SpringFramework的JDBC Support Module,同时尽可能少地引入不必要的元素。因此,我们假定不使用J2EE环境提供的任何服务,也不使用SpringFramework的IoC容器和AOP两大特性。

首先,我们需要的自然是一个DataSource。在非J2EE环境下,可以使用Jakarta的commons-dbcp来得到一个DataSource的实例。我们选择使用SharedPoolDataSource,它提供了一个close()方法,在程序结束前调用它可以关闭所有的Connection,释放相关的资源。

接着,将spring-core.jar和spring-dao.jar置入CLASSPATH。事实上,我们将要用到的class几乎全部都在spring-dao.jar中,之所以需要spring-core.jar是因为NestedRuntimeException,所有JDBC Support Module中的异常都直接或间接继承自这个Runtime Exception。由此也可以看出,我们只是在受控制的情况下引入了SpringFramework的一小部分而已。

下面,我们就可以开始逐步设置和组装我们的基础设施。

org.springframework.jdbc.core.JdbcTemplate

JdbcTemplate是整个package的核心,所有的JDBC调用流程都通过它来完成,开发者只需要实现对应的callback接口即可。JdbcTemplate是无状态且线程安全的,也就是说在整个系统中只需要创建一个实例就够了。创建它的时候需要提供DataSource作为参数。

JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
jdbcTemplate.aftERPropertiesSet();

afterPropertiesSet()方法是对InitializingBean接口的实现,如果实例是由IoC容器管理的,则容器会自动调用。由于我们并没有使用IoC容器,所以需要在创建实例后主动调用该方法。

org.springframework.transaction.support.TransactionTemplate

TransactionTemplate帮助我们以编程的方式实现事务控制。同样的,开发者也是通过实现callback接口来使用它。TransactionTemplate也是无状态且线程安全的。创建TransactionTemplate的实例需要提供一个PlatformTransactionManager的实例,在SpringFramework中有多种PlatformTransactionManager的实现类,提供多种事务控制的途径。基于前面设定的限制,我们选择DataSourceTransactionManager。


    PlatformTransactionManager platformTransactionManager = 
new DataSourceTransactionManager(dataSource);
TransactionTemplate transactionTemplate =
new TransactionTemplate(platformTransactionManager);
transactionTemplate.afterPropertiesSet();

org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer

在数据库中插入数据的时候,需要获得唯一的Long或Integer类型的值做为主键。DataFieldMaxValueIncrementer提供了这样一个途径,而具体的实现方法则因各种数据库系统而异。简单地说,如果数据库系统本身提供了Sequences(例如Oracle),则直接从sequences取得所需的序列值,如果数据库系统不支持Sequences(例如MySQL),则通过一个单独的Table来保存和产生新的序列值。每个DataFieldMaxValueIncrementer的实例都需要有一个对应的Sequences或者Table,换句话说,开发者要选择是整个系统共用同一个Incrementer实例,还是对应每个Table使用各自专有的Incrementer实例。目前SpringFramework已经提供了针对Oracle、DB2、PostgreSQL、MySQL,HSQL五种数据库的实现,支持从超重量级直到超轻量级的常见数据库系统,而且,要自己编写针对其它数据库系统的实现也并非难事。在例子中我们选择使用HSQL数据库,创建一个HsqlMaxValueIncrementer的实例需要提供DataSource、table name、column name。

HsqlMaxValueIncrementer incrementer = new HsqlMaxValueIncrementer(dataSource,
"id_sequence", "value");
incrementer.afterPropertiesSet();

基础设施准备好了之后,就可以在上面进行DAO的实现了,前面已经提到了开发者是通过实现callback接口来使用JdbcTemplate的,现在让我们来逐个尝试。

Insert、Update、Delete三种情况都不需要返回结果给调用者,因此可以使用JdbcTemplate的update()方法,该方法有多个重载的版本,可以根据实际情况选择一个合适的。由于数据库系统的原因,我无法测试对BLOB和CLOB的操作,但是从文档来看,相关的支持应该是满足需要的。

long id = incrementer.nextLongValue();
user.setId(id);
String sql = "INSERT INTO users VALUES (?,?,?,?);";
Object[] params = new Object[] { new Long(id), user.getUsername(),
user.getPassword(), new Boolean(user.isEnabled()) };
jdbcTemplate.update(sql, params);

对于Query,则是使用JdbcTemplate的query()方法,同样提供了多个重载的版本。通常要先实现一个RowMapper,能够将ResultSet中的一条记录取出来,填充到一个对象中。我们可以将它设计为一个内部类,同时它的实例也是线程安全的。

private class UserRowMapper implements RowMapper
{
public Object mapRow(ResultSet resultSet, int row) throws SQLException
{
User user = new User();
user.setId(resultSet.getLong("id"));
user.setUsername(resultSet.getString("username"));
user.setPassword(resultSet.getString("password"));
user.setEnabled(resultSet.getBoolean("enabled"));
return user;
}
}

String sql = "SELECT * FROM users;";
RowMapper mapper = new UserRowMapper();
RowMapperResultReader reader = new RowMapperResultReader(mapper);
List users = jdbcTemplate.query(sql, reader);
return users;

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇:The Alloy Look And Feel 1.4.4破解手记

下一篇:Thinking in Java第三版读书笔记-第九章:异常带来处理错误