转自:

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. 解决NSData转NSString返回nil的问题

    // 字符串转Data NSString *str =@"jesfds"; NSData *data =[str dataUsingEncoding:NSUTF8StringEnc ...

  2. vim使用技巧

    1.vim 编辑下内容复制.剪切到windows下 "+y 或 "+d 2.从win 复制到 vim CTRL+Shift+v 3.选择文字 v+方向键

  3. CSS3选择器介绍

    1.css3属性选择器 <!DOCTYPE html> <html lang="en"> <head> <meta charset=&qu ...

  4. SignalR 2.1 简单入门项目

    概述 SignalR是通讯框架,前台Web页面与后台服务实现数据的交互.ASP.NET SignalR 是一个为 ASP.NET 开发人员的库,简化了将实时 web 功能添加到应用程序的过程.实时We ...

  5. 【Mybatis高级映射】一对一映射、一对多映射、多对多映射

    前言 当我们学习heribnate的时候,也就是SSH框架的网上商城的时候,我们就学习过它对应的高级映射,一对一映射,一对多映射,多对多映射.对于SSM的Mybatis来说,肯定也是差不多的.既然开了 ...

  6. poj 3253 Fence Repair

    Fence Repair Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 42979   Accepted: 13999 De ...

  7. jq switch case

    switch (cnt) {                    case ("string1"):                        ...             ...

  8. BZOJ 1260&UVa 4394 区间DP

    题意: 给一段字符串成段染色,问染成目标串最少次数. SOL: 区间DP... DP[i][j]表示从i染到j最小代价 转移:dp[i][j]=min(dp[i][j],dp[i+1][k]+dp[k ...

  9. SSH三大框架的JAR包下载地址

    官网的英文网站读起来有点费劲,把下载地址直接放到这儿,以后免得到处找了 Struts 2 : http://struts.apache.org/download.cgi#struts216 sprin ...

  10. chart.js 里添加图表的清单:

    chart.js 里添加图表的清单: var legend = myDoughnut.generateLegend(); $("#chart_legend").html(legen ...