`

第九章 Spring配置数据连接池

阅读更多
Spring的JDBC模板技术
首先,我们回顾一下我们以前的JDBC操作需要的几个步骤:
 DbManager:
getConnection():负责获取数据库连接对象
closeConnection:负责关闭数据库的连接对象
 Dao层
我们以insert操作为例子
public int insertNews(News news) {
Connection conn = null;
CallableStatement proc = null;
int backVal = 0;
conn = DbManager.getConnection();
try {
proc = conn.prepareCall("{ call insertNewsPROC(?,?,?) }");
proc.setString(1, news.getTitle());
proc.setString(2, news.getContext());
proc.setInt(3, news.getNewsType().getId());
backVal = proc.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
DbManager.closeConnection(conn, proc, null);
}
return backVal;
}
这是我们以前的代码,可以看到insert 操作需要做的事情有
1. 获取连接,
2. 执行SQL
3. 关闭连接

如果我们用到Spring的JDBC模板技术以后,我们可以只需要关心的一个步骤就行了, 就是执行SQL

 接下来,我们首先利用Spring的IOC技术, 配合使用c3p0连接池, 将我们的DbManager类干掉
c3p0连接池在使用Hibernate的时候我们使用过,不过那时只配置了必要的连接数据库的属性值,其它的都交给Hibernate去完成了.
请看下面的Hibernate中的配置信息
<!-- 设置 c3p0连接池的属性-->
<property name="connection.useUnicode">true</property>
<property name="hibernate.c3p0.max_statements">100</property>
<property name="hibernate.c3p0.idle_test_period">3000</property>
<property name="hibernate.c3p0.acquire_increment">2</property>
<property name="hibernate.c3p0.timeout">5000</property>
<property name="hibernate.connection.provider_class">
org.hibernate.connection.C3P0ConnectionProvider
</property>
<property name="hibernate.c3p0.validate">true</property>
<property name="hibernate.c3p0.max_size">3</property>
<property name="hibernate.c3p0.min_size">1</property>
最主要的是看这里: org.hibernate.connection. C3P0ConnectionProvider
这里说明了在Hibernate中和c3p0打交道的是: C3P0ConnectionProvider,这个类是hibernate提供的.

但是现在我们并没有使用到Hibernate, 而是直接和C3P0打交道,所以我们要找出C3P0中能够提供getConnection的类,然后将此类交给Spring管理即可, 此类是com.mchange.v2.c3p0.ComboPooledDataSource,请看下面的配置:
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass" value="com.mysql.jdbc.Driver" />
<property name="jdbcUrl"
value="jdbc:mysql://localhost:3306/test?useUnicode=true&amp;characterEncoding=utf-8" />
<property name="user" value="root" />
<property name="password" value="wdpc" />

<!--连接池中保留的最小连接数。-->
<property name="minPoolSize" value="1" />

<!--连接池中保留的最大连接数。Default: 15 -->
<property name="maxPoolSize" value="5" />

<!--初始化时获取的连接数,取值应在minPoolSize与maxPoolSize之间。Default: 3 -->
<property name="initialPoolSize" value="1" />

<!--最大空闲时间,60秒内未使用则连接被丢弃。若为0则永不丢弃。Default: 0 -->
<property name="maxIdleTime" value="60" />

<!--当连接池中的连接耗尽的时候c3p0 一次同时获取的连接数。Default: 3 -->
<property name="acquireIncrement" value="1" />
</bean>
通过配置此bean,就相当于有了我们以前DbManager类中的getConnection方法, getConnection方法能够返回一个Connection,
只不过我们这里可以获取到一个dataSource 数据源对象

接下来,我们实现一个Dao层,以insert操作为例子:
Dao接口:
public interface UserDao {
public void create(User user) throws Exception;

public void update(User user) throws Exception;

public void delete(int userId) throws Exception;

public User findUserById(int userId) throws Exception;

public List<User> findUserAll() throws Exception;
}


Dao实现类:
public class UserDaoImpl implements UserDao {
private DataSource dataSource;

@Override
public void create(User user) throws Exception {
Connection conn = dataSource.getConnection();
PreparedStatement pst = null;
try {
pst = conn.prepareStatement("insert into users(name) values(?)");
pst.setString(1, user.getName());
pst.executeUpdate();
} catch (Exception e) {
throw e;
} finally {
closeConnection(conn, pst, null);
}
}

@Override
public void delete(int userId) throws Exception {
}

@Override
public List<User> findUserAll() throws Exception {
return null;
}

@Override
public User findUserById(int userId) throws Exception {
return null;
}

@Override
public void update(User user) throws Exception {
}

public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}

private void closeConnection(Connection conn, Statement st, ResultSet rs) {
try {
if (rs != null) {
rs.close();
}
if (st != null) {
st.close();
}
if (conn != null) {
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
Dao层需要提供一个dataSource属性,用来接收注入进来的dataSource,
通过dataSource的dataSource.getConnection()可以获取到Connection对象,然后可以像我们以前一样进行操作
可以看到closeConnection方法还是得我们自己提供,
不过后面如果用到Spring提供的JDBC模板技术的话,这些都可以干掉.

XML配置,将Dao层纳入Spring管理,并且将配置的c3p0数据源对象注入到Dao层对象
<bean id="userDao" class="com.wdpc.sj.dao.impl.UserDaoImpl">
<property name="dataSource" ref="dataSource" />
</bean>

Test类:
public class Test {
public static void main(String[] args) throws Exception {
ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
UserDao userDao = (UserDao)ctx.getBean("userDao");
userDao.create(new User("张三"));
}
}
这时可以看到能够达到插入数据的目的.

Spring的JDBC模板
Spring中提供了一个类: JdbcTemplate类,它能够简化我们的JDBC操作,它封闭了获取连接对象,关闭对象等等一些底层的重复性操作代码.
首先,我们创建JdbcTemplate类,并将其纳入Spring的管理,此类支持构造器注入,不支持set注入
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd          
           http://www.springframework.org/schema/aop
           http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass" value="com.mysql.jdbc.Driver" />
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test?useUnicode=true&amp;characterEncoding=utf-8" />
<property name="user" value="root" />
<property name="password" value="wdpc" />

<!--连接池中保留的最小连接数。-->
<property name="minPoolSize" value="1" />

<!--连接池中保留的最大连接数。Default: 15 -->
<property name="maxPoolSize" value="5" />

<!--初始化时获取的连接数,取值应在minPoolSize与maxPoolSize之间。Default: 3 -->
<property name="initialPoolSize" value="1" />

<!--最大空闲时间,60秒内未使用则连接被丢弃。若为0则永不丢弃。Default: 0 -->
<property name="maxIdleTime" value="60" />

<!--当连接池中的连接耗尽的时候c3p0 一次同时获取的连接数。Default: 3 -->
<property name="acquireIncrement" value="1" />
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<constructor-arg index="0" ref="dataSource" />
</bean>
<bean id="userDao" class="com.wdpc.sj.dao.impl.UserDaoImpl">
<property name="jdbcTemplate" ref="jdbcTemplate" />
</bean>
</beans>

接着我们修改Dao层的代码:
public class UserDaoImpl implements UserDao {
private JdbcTemplate jdbcTemplate;

@Override
public void create(User user) throws Exception {
jdbcTemplate.update("insert into users(name) values(?)",
new Object[] { user.getName() }, new int[] { Types.VARCHAR });
}

@Override
public void update(User user) throws Exception {
}

@Override
public void delete(int userId) throws Exception {
}

@Override
public List<User> findUserAll() throws Exception {
return null;
}

@Override
public User findUserById(int userId) throws Exception {
return null;
}

public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
}
Test :
public class Test {
public static void main(String[] args) throws Exception {
ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
UserDao userDao = (UserDao)ctx.getBean("userDao");
userDao.create(new User("武大鹏程"));
}
}
可以看到同样达到了insert操作的效果,但是可以看到Dao层的实现,现在只需要一句话就OK了,这就是jdbcTemplate带来的好处.

接下来,我们补全其它方法的实现.
public class UserDaoImpl implements UserDao {
private JdbcTemplate jdbcTemplate;

@Override
public void create(User user) throws Exception {
jdbcTemplate.update("insert into users(name) values(?)",
new Object[] { user.getName() }, new int[] { Types.VARCHAR });
}

@Override
public void update(User user) throws Exception {
jdbcTemplate.update("update users set name=? where id=?", new Object[] {
user.getName(), user.getId() }, new int[] { Types.VARCHAR,
Types.INTEGER });
}

@Override
public void delete(int userId) throws Exception {
jdbcTemplate.update("delete from users where id=?",
new Object[] { userId }, new int[] { Types.INTEGER });
}

@Override
public List<User> findUserAll() throws Exception {
return jdbcTemplate.query("select * from users", new UserRowMapper());
}

@Override
public User findUserById(int userId) throws Exception {
return (User) jdbcTemplate.queryForObject(
"select * from users where id=?", new Object[] { userId },
new int[] { Types.INTEGER }, new UserRowMapper());
}

public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
}
先看看更新操作
jdbcTemplate.update("insert into users(name) values(?)",
new Object[] { user.getName() }, new int[] { Types.VARCHAR });
可以看到执行更新操作的update方法需要四个参数
1. 要执行的SQL语句
2. 打问号的参数
3. 告诉SQL语句参数对应的SQL类型

注意后两个参数是用数组传给jdbcTemplate的

执行查询的方法
queryForObject: 返回单个对象
参数:
1. 要执行的SQL语句
2. 打问题的参数
3. 告诉SQL语句参数对应的SQL类型
4. 结果集的处理方式

query:返回List
用于执行无问号的SQL语句
jdbcTemplate.query(sql, rowMapper);

用于执行有问号的SQL语句
jdbcTemplate.query(sql, args, argTypes, rowMapper)

参数意义和上面的一样
RowMapper是一个接口,这里需要提供一个实现了RowMapper接口的类,它的功能是告诉jdbcTemplate结果集是怎么处理, jdbcTemplate会自己调用此接口中的mapRow方法来处理结果集
代码如下:
public class UserRowMapper implements RowMapper {
@Override
public Object mapRow(ResultSet rs, int index) throws SQLException {
return new User(rs.getInt(1),rs.getString(2));
}
}

引申出事务
模拟一个业务层,批量增加User
业务层接口:
public interface UserService {
public void batchCreateUser(String[] names) throws Exception;
}
业务层实现类:
public void batchCreateUser(String[] names) throws Exception {
for(String name : names){
userDao.create(new User(name));
}
throw new Exception();
}
XML配置:
<bean id="userService" class="com.wdpc.sj.service.impl.UserServiceImpl">
<property name="userDao" ref="userDao" />
</bean>
Test:
public class Test {
public static void main(String[] args) throws Exception {
ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
UserService userService = (UserService) ctx.getBean("userService");
userService.batchCreateUser(new String[]{"李四3","李四4"});
}
}
可以看到业务层实现类发生了异常,但是数据还是添加到数据库中去了,这时可以得知jdbcTemplate并未集成事务,怎么给服务层加入事务的支持呢,请看下一章节.

分享到:
评论
2 楼 武大鹏程加内特 2012-11-24  
zzy90718 写道

1 楼 zzy90718 2010-11-18  

相关推荐

    spring.net中文手册在线版

    第九章. Spring.NET杂记 9.1.简介 9.2.PathMatcher 9.2.1.通用规则 9.2.2.匹配文件名 9.2.3.匹配子目录 9.2.4.大小写需要考虑,斜线可以任意 第十章. 表达式求值 10.1.简介 10.2.表达式求值 10.3.语言参考 10.3.1....

    Spring in Action(第2版)中文版

    第9章在spring中建立契约优先web服务 9.1介绍spring-ws 9.2定义契约(首先!) 9.3使用服务端点处理消息 9.3.1建立基于jdom消息的端点 9.3.2序列化消息载荷 9.4合并在一起 9.4.1spring-ws:全景视图 9.4.2将...

    Spring in Action(第二版 中文高清版).part2

    第9章 在Spring中建立契约优先Web服务 9.1 介绍Spring-WS 9.2 定义契约(首先!) 9.3 使用服务端点处理消息 9.3.1 建立基于JDOM消息的端点 9.3.2 序列化消息载荷 9.4 合并在一起 9.4.1 Spring-WS:全景视图 ...

    Spring in Action(第二版 中文高清版).part1

    第9章 在Spring中建立契约优先Web服务 9.1 介绍Spring-WS 9.2 定义契约(首先!) 9.3 使用服务端点处理消息 9.3.1 建立基于JDOM消息的端点 9.3.2 序列化消息载荷 9.4 合并在一起 9.4.1 Spring-WS:全景视图 ...

    搞定J2EE:STRUTS+SPRING+HIBERNATE整合详解与典型案例 (1)

    12.4.2 配置数据库连接池 12.4.3 使用JNDI 12.5 使用Hibernate的工具快速生成映射文件和POJO 12.5.1 使用MiddleGen根据数据库产生映射文件 12.5.2 使用hbm2java根据映射文件产生POJO 12.6 整合Struts、Spring和...

    搞定J2EE:STRUTS+SPRING+HIBERNATE整合详解与典型案例 (3)

    12.4.2 配置数据库连接池 12.4.3 使用JNDI 12.5 使用Hibernate的工具快速生成映射文件和POJO 12.5.1 使用MiddleGen根据数据库产生映射文件 12.5.2 使用hbm2java根据映射文件产生POJO 12.6 整合Struts、Spring和...

    搞定J2EE:STRUTS+SPRING+HIBERNATE整合详解与典型案例 (2)

    12.4.2 配置数据库连接池 12.4.3 使用JNDI 12.5 使用Hibernate的工具快速生成映射文件和POJO 12.5.1 使用MiddleGen根据数据库产生映射文件 12.5.2 使用hbm2java根据映射文件产生POJO 12.6 整合Struts、Spring和...

    springmybatis

    恭喜你,环境搭建配置成功,接下来第二章,将讲述基于接口的操作方式,增删改查。 整个工程目录结构如下: 除非申明,文章均为一号门原创,转载请注明本文地址,谢谢! mybatis实战教程(mybatis in action)之二:以...

    J2EE spring mvc mybatis bootstrap HTML5 后台框架 控制台 mysql版本_spring3.0

    数据库连接池 阿里的 druid。Druid在监控、可扩展性、稳定性和性能方面都有明显的优势,支持并发 10.加入安全框架 shiro (登录授权)(session管理) 11.根据汉字 解析汉字的全拼(拼音)和首字母(导入excel到用户表,...

    Java Web应用详解.张丽(带详细书签).pdf

    第9章 JSP及其应用 9.1 JSP基础知识 9.2 JSP 语法 9.3 JSP 范例 9.4 网络留言板V4.0 第10章 JavaBean及其应用 10.1 JavaBean 基础知识 10.2 JavaBean 在 JSP 中的调用 10.3 JavaBean 的作用域 10.4 JSP+...

    java web技术开发大全(最全最新)

    第9章 Struts 2的* 第10章 Struts 2的类型转换 第11章 Struts 2的输入校验 第12章 文件的上传和下载 第13章 国际化 第14章 Struts 2的标签库 第15章 Struts 2对AJAX的支持 第16章 用Struts 2实现注册登录系统...

    java web开发技术大全

    第9章 Struts 2的* 第10章 Struts 2的类型转换 第11章 Struts 2的输入校验 第12章 文件的上传和下载 第13章 国际化 第14章 Struts 2的标签库 第15章 Struts 2对AJAX的支持 第16章 用Struts 2实现注册...

    ssh(structs,spring,hibernate)框架中的上传下载

     第3~9行定义了一个数据源,其实现类是apache的BasicDataSource,第11~25行定义了Hibernate的会话工厂,会话工厂类用Spring提供的LocalSessionFactoryBean维护,它注入了数据源和资源映射文件,此外还通过一些键值...

    Hbase+Spring boot实战分布式文件存储

    8-2 文件存储设计方案一 8-3 文件存储设计方案二 第9章 子模块-数据库操作模块 hos服务基础数据库选用mysql,本章实现基于SpringBoot+Mybatis的mysql数据库的操作模块,采用c3p0连接池,完成数据库链接的相关配置工作...

    J2EE spring mvc mybatis bootstrap HTML5 后台框架 控制台 oracle版本_spring3.0

    数据库连接池 阿里的 druid。Druid在监控、可扩展性、稳定性和性能方面都有明显的优势,支持并发 10.加入安全框架 shiro (登录授权)(session管理) 11.根据汉字 解析汉字的全拼(拼音)和首字母(导入excel到用户表,...

    《程序天下:J2EE整合详解与典型案例》光盘源码

    12.4.2 配置数据库连接池 12.4.3 使用JNDI 12.5 使用Hibernate的工具快速生成映射文件和POJO 12.5.1 使用MiddleGen根据数据库产生映射文件 12.5.2 使用hbm2java根据映射文件产生POJO 12.6 整合Struts、Spring和...

    JAVA WEB典型模块与项目实战大全

    第9章 搜索引擎(lucene+web spider)  9.1 关于搜索引擎的基本概念  9.2 网络蜘蛛(web spider)  9.3 下载和分析lucene全文搜索组件  9.4 初步使用lucene全文搜索组件  9.5 新闻搜索引擎具体实现  9.6 ...

Global site tag (gtag.js) - Google Analytics