转自:

http://www.cnblogs.com/windlaughing/p/3287750.html

Spring JDBC提供了一套JDBC抽象框架,用于简化JDBC开发。

Spring主要提供JDBC模板方式、关系数据库对象化方式、SimpleJdbc方式、事务管理来简化JDBC编程

Spring提供了3个模板类:

  • JdbcTemplate:Spring里最基本的JDBC模板,利用JDBC和简单的索引参数查询提供对数据库的简单访问。
  • NamedParameterJdbcTemplate:能够在执行查询时把值绑定到SQL里的命名参数,而不是使用索引参数。
  • SimpleJdbcTemplate:利用Java 5的特性,比如自动装箱、通用(generic)和可变参数列表来简化JDBC模板的使用。

JdbcTemplate主要提供以下4类方法:

  • execute方法:可以用于执行任何SQL语句,一般用于执行DDL语句;
  • update方法及batchUpdate方法:update方法用于执行新增、修改、删除等语句;batchUpdate方法用于执行批处理相关语句;
  • query方法及queryForXXX方法:用于执行查询相关语句;
  • call方法:用于执行存储过程、函数相关语句。

示例项目

接下来,通过一个示例项目来展示如何使用Spring的JDBC框架访问数据库。假设该项目的功能有:保存用户信息、查询用户信息。

1、首先创建数据库及用户表:

CREATE TABLE `user` (
`id` int(10) NOT NULL auto_increment,
`name` varchar(30) default NULL,
`age` int(3) default NULL,
PRIMARY KEY (`id`)
)

2、创建工程(Maven工程),添加依赖

依赖配置:

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.26</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>0.2.25</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>3.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>3.2.4.RELEASE</version>
</dependency>

依赖的包有:Junit、mysql驱动器、druid(阿里巴巴开发的高性能的数据库连接池)、spring-context、spring-jdbc

3、实体类User

public class User implements Serializable{
private Long id;
private String name;
private Integer age; //setter getter 略 public String toString() {
return "User [id=" + id + ", name=" + name + ", age=" + age + "]";
}
}

4、Dao接口及实现

package edu.shao.springJdbc.dao;

import java.util.List;
import edu.shao.springJdbc.po.User; public interface IUserDao {
public void save(User user);
public List<User> query(String sql,Object[] args);
}
package edu.shao.springJdbc.dao.impl;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import edu.shao.springJdbc.dao.IUserDao;
import edu.shao.springJdbc.po.User; public class UserDaoImpl extends JdbcDaoSupport implements IUserDao { class UserRowMapper implements RowMapper<User> {
//实现ResultSet到User实体的转换
public User mapRow(ResultSet rs, int rowNum) throws SQLException {
User m = new User();
m.setId(rs.getLong("id"));
m.setName(rs.getString("name"));
m.setAge(rs.getInt("age"));
return m;
}
}; public void save(User model) {
getJdbcTemplate().update("insert into user(name,age) values(?,?)",
model.getName(), model.getAge());
} public List<User> query(String sql, Object[] args) {
return getJdbcTemplate().query(sql, args, new UserRowMapper());
}
}

5、Service接口及实现:

package edu.shao.springJdbc.service;

public interface IUserService {
void saveUser();
void saveUserThrowException() throws Exception;
void findUsers();
}
package edu.shao.springJdbc.service.impl;

import java.util.List;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import edu.shao.springJdbc.dao.IUserDao;
import edu.shao.springJdbc.po.User;
import edu.shao.springJdbc.service.IUserService; @Transactional
public class UserServiceImpl implements IUserService {
private IUserDao userDao; public void saveUser() {
User u1=new User();
u1.setName("邵");
u1.setAge(24);
userDao.save(u1); if(1+1>1){
throw new RuntimeException("Runtime error...");//抛出运行时异常:RuntimeException
} User u2=new User();
u2.setName("陈");
u2.setAge(20);
userDao.save(u2);
} public void saveUserThrowException() throws Exception {
User u1=new User();
u1.setName("邵");
u1.setAge(24);
userDao.save(u1); if(1+1>1){
throw new Exception("Runtime error...");//抛出一般的异常:Exception
} User u2=new User();
u2.setName("陈");
u2.setAge(20);
userDao.save(u2);
} @Transactional(propagation=Propagation.NOT_SUPPORTED,readOnly=true)
public void findUsers() {
List<User> users=userDao.query("select * from user where age>?", new Object[]{17});
for (User user : users) {
System.out.println(user);
} } //setter getter略
}

Spring对事务的管理有丰富的支持,Spring提供了编程式配置事务和声明式配置事务,其中,声明式事务有以下两种方式 :

  1. 一种是使用Annotation注解的方式(官方推荐)
  2. 一种是基于Xml的方式

(编程式的事务处理有些侵入性。通常我们的事务需求并没有要求在事务的边界上进行如此精确的控制,我们一般采用"声明式事务"。)

上面我们采用了基于注解的方式来配置事务。

6、配置数据库连接池、配置bean的依赖关系、配置事务处理器

applicationContext-dataSource.xml

<?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"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
init-method="init" destroy-method="close">
<property name="url" value="jdbc:mysql://localhost:3306/test" />
<property name="username" value="root" />
<property name="password" value="123456" />
<property name="initialSize" value="1" />
<property name="maxActive" value="20" />
</bean> </beans>

applicationContext-jdbc.xml

<?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" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> <import resource="applicationContext-dataSource.xml" /> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource" />
</bean> <!-- 首先定义抽象的abstractDao,其有一个jdbcTemplate属性,从而可以让继承的子类自动继承jdbcTemplate属性注入; -->
<bean id="abstractDao" abstract="true">
<property name="jdbcTemplate" ref="jdbcTemplate" />
</bean> <bean id="userDao" class="edu.shao.springJdbc.dao.impl.UserDaoImpl"
parent="abstractDao" /> <bean id="userService" class="edu.shao.springJdbc.service.impl.UserServiceImpl">
<property name="userDao" ref="userDao"></property>
</bean> <bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean> <tx:annotation-driven transaction-manager="txManager" />
</beans>

上面<tx:annotation-driven transaction-manager="txManager" /> 这句话的作用是注册事务处理器。

我们只需要在类上加上注解@Transactional,就可以指定这个类需要受Spring的事务管理。默认Spring为每个方法开启一个事务,如果方法发生运行期异常(RuntimeException),事务会进行回滚;如果发生一般的异常(Exception),事务不进行回滚。

7、测试

package edu.shao.springJdbc;

import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; import edu.shao.springJdbc.service.IUserService; public class SpringJdbcTest {
private static ApplicationContext ctx = null; @BeforeClass //表示在所以测试方法之前执行,且只执行一次。
public static void onlyOnce() {
ctx = new ClassPathXmlApplicationContext("db/applicationContext-jdbc.xml");
} @Test
public void testSave(){
IUserService service=ctx.getBean("userService",IUserService.class);
service.saveUser();
} @Test
public void testSaveThrowException() throws Exception{
IUserService service=ctx.getBean("userService",IUserService.class);
service.saveUserThrowException();
} @Test
public void testJDBCDaoQuery(){
IUserService service=ctx.getBean("userService",IUserService.class);
service.findUsers();
}
}

运行测试类,

第一个测试方法,后台输出异常:java.lang.RuntimeException,查看数据库发现数据没有插入,说明事务进行了回滚。

第二个测试方法,后台输出异常:java.lang.Exception ,查看数据库发现第一条数据插入,而第二条数据没有插入,说明事务没有进行了回滚。

说明了Spring的事务支持默认只对运行期异常(RuntimeException)进行回滚,如果执行sql操作的时候会发生sql异常,不属于运行期异常,那Spring是怎么进行事务回滚的呢 ?

Spring把SQLException等异常转化为了DataAccessException,后者是一种RuntimeException,所以只对RuntimeException异常进行回滚是很合理的。

其他注解方式:

  1. 修改Spring的默认配置,当发生RuntimeException时,可以不让它进行事务回滚 ,只需要加上一个@Transactional(noRollbackFor=RuntimeException.class)
  2. 配置对Exception进行回滚,在方法上添加@Transactional(rollbackFor=Exception.class)
  3. 对于一些查询工作,因为不需要配置事务支持,我们给其添加注解: @Transactional(propagation=Propagation.NOT_SUPPORTED,readOnly=true)。readOnly=true表示事务中不允许存在更新操作.

关于事务的传播属性有下面几种配置:

  • REQUIRED:业务方法需要在一个事务中运行,如果方法运行时,已经处于一个事务中,那么加入到该事务中。否则自己创建一个新的事务。(Spring默认的事务传播属性)
  • NOT_SUPPORTED:声明方法不需要事务,如果方法没有关联到一个事务,容器不会为它开启事务。如果方法在一个事务中被调用,该事务被挂起,在方法调用结束后,原先的事务便会恢复执行
  • REQUIRESNEW:不管是否存在事务,业务方法总会为自己发起一个新的事务。如果方法运行时已经存在一个事务,则该事务会被挂起,新的事务被创建,直到方法执行结束,新事务才结束,原先的事务才恢复执行.
  • MANDATORY:指定业务方法只能在一个已经存在的事务中执行,业务方法不能自己发起事务,如果业务方法没有在事务的环境下调用,则容器会抛出异常
  • SUPPORTS:如果业务方法在事务中被调用,则成为事务中的一部分,如果没有在事务中调用,则在没有事务的环境下执行
  • NEVER:指定业务方法绝对不能在事务范围内运行,否则会抛出异常.
  • NESTED:如果业务方法运行时已经存在一个事务,则新建一个嵌套的事务,该事务可以有多个回滚点,如果没有事务,则按REQUIRED属性执行。 注意:业务方法内部事务的回滚不会对外部事务造成影响,但是外部事务的回滚会影响内部事务

总结:
事务是企业应用开发的重要组成部分,它使软件更加可靠。它们确保一种要么全有 要么全无的行为,防止数据不一致而导致的不可预测的错误发生。 事务同时也支持并发,防止并发应用线程在操作同一数据时互相影响。

以前我们写Jdbc代码的时候,可能需要自己手动去开启事务,然后方法执行结束之后再去提交事务,全部都嵌套在我们的业务代码之中,具有很强的侵入性....
使用Spring提供事务管理机制,我们只需要配置XML或使用Annotion进行注解就可以实现事务的管理和配置,减少了代码之间的耦合,配置也很方便,很大程度上提升了我们的开发效率。

==============================================

接口实现类:UserDAOImpl.java

按照以往Spring的依赖注入,我们需要在接口实现类中利用构造器去获取JdbcTemplate

Spring早就帮我们想到了这点,它为我们提供了JdbcDaoSupport支持类,所有DAO继承这个类,就会自动获得JdbcTemplate(前提是注入DataSource)。

<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean> <bean id="userDao" class="com.curd.spring.impl.UserDAOImpl">
<property name="jdbcTemplate" ref="jdbcTemplate"></property>
</bean>

业务DAO如果想通过注解方式, 可以使用@PostConstruct:

@Component("workerStatisJdbcDaoImpl")
public class WorkerStatisJdbcDaoImpl extends JdbcDaoSupport {
...... @Autowired
JdbcTemplate jdbcTemplate; @PostConstruct
public void injectJdbcTemplate() {
super.setJdbcTemplate(jdbcTemplate);
}
......
}

附:

1、Spring 为每种持久化技术 提供一个支持类,在DAO 中注入 模板工具类
    (1)JDBC : org.springframework.jdbc.core.support.JdbcDaoSupport
    (2)Hibernate 3.0 :org.springframework.orm.hibernate3.support.HibernateDaoSupport
    (3)iBatis :org.springframework.orm.ibatis.support.SqlMapClientDaoSupport

用户自己编写DAO 只需要继承 JdbcDaoSupport, 就可以注入 JdbcTemplate

2、 通过jdbcTemplate 提供 int update(String sql, Object... args) 实现增加 、修改 、删除

3、简单查询,返回原始数据类型, String类型

String sql = "select count(*) from user"; // int queryForInt(String sql)
String sql = "select name from user where id = ? "; // <T> T queryForObject(String sql, Class<T> requiredType, Object... args)

4、 复杂查询
JdbcTemplate 没有handler, 手动完成对象封装

编写实体类 RowMapper

class UserRowMapper implements RowMapper<User> {
  @Override
  public User mapRow(ResultSet rs, int rowNum) throws SQLException {
    // rs 已经指向每一条数据,不需要自己调用 next,将rs指向数据 转换 User对象
    User user = new User();
    user.setId(rs.getInt("id"));
    user.setName(rs.getString("name"));
    return user;
  }
}

查询单个对象:

<T> T queryForObject(String sql, RowMapper<T> rowMapper, Object... args)
return this.getJdbcTemplate().queryForObject(sql, new UserRowMapper(),id);

查询所有对象List集合:

<T> List<T> query(String sql, RowMapper<T> rowMapper, Object... args)
return this.getJdbcTemplate().query(sql, new UserRowMapper());

Spring的JDBC框架的更多相关文章

  1. Spring的JDBC框架概述

    以下内容引用自http://wiki.jikexueyuan.com/project/spring/jdbc-framework.html: 在使用普通的JDBC操作数据库时,就会很麻烦的写很多不必要 ...

  2. Spring框架学习笔记(9)——Spring对JDBC的支持

    一.使用JdbcTemplate和JdbcDaoSupport 1.配置并连接数据库 ①创建项目并添加jar包,要比之前Spring项目多添加两个jar包c3p0-0.9.1.2.jar和mysql- ...

  3. Spring Jdbc 框架整合的第一天

    Spring  Jdbc的概述 它是Spring框架的持久层子框架.用于对数据库的操作 什么是数据库的操作? 答:对数据库的增删改查 在使用Spring  Jdbc框架,要用到一个类---->J ...

  4. ref:Spring JDBC框架

    ref:https://blog.csdn.net/u011054333/article/details/54772491 Spring JDBC简介 先来看看一个JDBC的例子.我们可以看到为了执行 ...

  5. 11.Spring——JDBC框架

    1.DBC 框架概述 2.Spring JDBC 示例 3.Spring 中 SQL 的存储过程 1.DBC 框架概述 在使用普通的 JDBC 数据库时,就会很麻烦的写不必要的代码来处理异常,打开和关 ...

  6. Spring(十二)之JDBC框架

    JDBC 框架概述 在使用普通的 JDBC 数据库时,就会很麻烦的写不必要的代码来处理异常,打开和关闭数据库连接等.但 Spring JDBC 框架负责所有的低层细节,从开始打开连接,准备和执行 SQ ...

  7. jdbc框架有很多,包括spring jdbc

    1.由于jdbc连接的繁琐性,故很多公司封装了jdbc框架,比如spring jdbc 2.比如spring jdbc框架中,用jdbctemplate, 通过jdbcTemplate 提供 int ...

  8. Spring JDBC 框架使用JdbcTemplate 类的一个实例

    JDBC 框架概述 在使用普通的 JDBC 数据库时,就会很麻烦的写不必要的代码来处理异常,打开和关闭数据库连接等.但 Spring JDBC 框架负责所有的低层细节,从开始打开连接,准备和执行 SQ ...

  9. Spring JDBC 框架 简介

    在使用普通的 JDBC 数据库时,就会很麻烦的写不必要的代码来处理异常,打开和关闭数据库连接等. 但 Spring JDBC 框架负责所有的低层细节,从开始打开连接,准备和执行 SQL 语句,处理异常 ...

随机推荐

  1. js脚本语言

    alert(): 输出 字符串 转成整数 parseint(字符串):运算符与表达式% 取余 aler(10%2)余0 逻辑运算符&&并 ||或 !非 判断条件比较运算符== 等于 ! ...

  2. iOS 编码转换

    - (NSString *)SaveFileToDocuments:(NSString *)url { // NSString *url = @"http://172.28.250.70/a ...

  3. oracle数据库安装完要做的事情。

    安装数据库客户端.这个在oracle官网可以下载安装(下载链接) 安装PL/SQL PL在下载 配置环境变量(这个比较重要,不配置PLSQL链接不到数据库) 配置的相关环境变量有: 变量名:oracl ...

  4. 最大公约数和最小公倍数--java实现

    代码: //最大公约数 public int gcd(int p,int q){ if(q == 0) return p; return gcd(q, p % q); } //最小公倍数 public ...

  5. php多文件上传

    多文件上传<input type="file" name="file[]" multiple /> <?php function reArra ...

  6. EXT.NET 使用总结(1)

    前言 从系统改版到现在,将近半年的时间,原本陌生的Ext.NET的UI框架,也慢慢的熟悉了.总的来说,这个UI框架还是很优秀的,但是也没有100%完美的产品(老系统使用easy ui其实也挺好的).趁 ...

  7. html学习第一天笔记——第六章节

    <input type="reset" value="重置"> 使用重置按钮,重置表单信息<input type="submit&q ...

  8. [工作中的设计模式]解释器模式模式Interpreter

    一.模式解析 解释器模式是类的行为模式.给定一个语言之后,解释器模式可以定义出其文法的一种表示,并同时提供一个解释器.客户端可以使用这个解释器来解释这个语言中的句子. 以上是解释器模式的类图,事实上我 ...

  9. Scrum项目8.0

    目标:我们开始做每个需要细致的界面,比方说登陆,注册,游戏界面,难度选择 内容:登陆界面:登陆名,登陆密码,登陆按钮,以及优美的底图. 注册页面:名称,密码,登陆按钮,以及优美的底图. 游戏界面:难度 ...

  10. hibernate模糊查询

    hibernate模糊查询-Restrictions.ilike & Expression.like Criteria criteria = session.createCriteria(Ta ...