spring的jdbcTemplate操作(用在dao层)
spring框架是一个一站式框架,在每一层都提供了解决技术:在Dao层是使用了jdbcTemplate。
spring针对不同的持久化技术都提供了不同的模板。
Spring JDBC
Spring的JDBC模板负责提供数据库资源的管理和错误处理,大大简化了开发人员对数据库操作,使得开发人员可以从繁琐的数据库操作中解脱出来。
Spring jdbcTemplate的解析
针对数据库的操作,Spring框架提供了jdbcTemplate类,该类是Spring框架数据层的基础,其他更高层次的抽象类是构建在JdbcTemplate类之上,可以说,JdbcTemplate是Spring JDBC的核心类。
JdbcTemplata类的继承关系十分简单,它继承了JdbcAccessor抽象类,同时实现了JdbcOperations接口。
JdbcAccessor的设计中,对DataSource数据源进行了管理和配置,JdbcOperation接口定义中,定义了通过JDBC操作数据库的基本方法,而核心类JdbcTemplate提供了这些接口方法的实现。
Spring JDBC的配置
Spring JDBC模板主要是有四个包组成,分别是core(核心包),dataSource(数据源包),object(对象包),support(支持包),Spring对数据库的操作都封装在了这几个包中,而想要使用JDBC,就需要对其进行配置,在Spring中,JDBC的配置是在Spring的配置文件applicationContext.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd">
<!-- 配置数据源 -->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<!-- 数据库驱动 -->
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<!-- 连接数据库的Url -->
<property name="url" value="jdbc:mysql://localhost:3306/数据库名"/>
<!-- 连接数据库的用户名 -->
<property name="username" value="root"/>
<!-- 连接数据库的用户名 -->
<property name="password" value="abc"/>
</bean>
<!-- 配置JDBC模板 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<!-- 默认使用数据源 -->
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 配置注入类 -->
<bean id="" >
<property name="jdbcTemplate" ref="jdbcTemplate"/>
</bean>
</beans>
dataSource的四个属性:
属性名 | 含义 |
driverClassName | 所使用的驱动名称,对应驱动JAR包中的Driver类 |
url | 数据源所在的地址 |
username | 访问数据库的用户名 |
password | 访问数据库的密码 |
Spring JdbcTemplate的常用方法
1.execute():execute(String sql)方法能够完成执行SQL语句的功能,
先创建数据库spring
再在配置文件中配置jdbcTemplate
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd">
<!-- 配置数据源 -->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<!-- 数据库驱动 -->
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<!-- 连接数据库的Url -->
<property name="url" value="jdbc:mysql://localhost:3306/spring"/>
<!-- 连接数据库的用户名 -->
<property name="username" value="root"/>
<!-- 连接数据库的用户名 -->
<property name="password" value="abc"/>
</bean>
<!-- 配置JDBC模板 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<!-- 默认使用数据源 -->
<property name="dataSource" ref="dataSource"/>
</bean>
</beans>
在创建一个类用来测试是否成功
package com.itheima.jdbc;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
/**
* 使用execute()方法
* @author 12428
*
*/
public class JdbcTemplateTest {
public static void main(String[] args) {
//获取配置文件
ApplicationContext applicationContext=
new ClassPathXmlApplicationContext("applicationContext.xml");
//获取JdbcTemplate模板
JdbcTemplate jdbcTemplate=(JdbcTemplate) applicationContext.getBean("jdbcTemplate");
//使用execute()方法执行SQL语句,创建用户账号管理表account
jdbcTemplate.execute("create table account("+
"id int primary key auto_increment,"+
"username varchar(50),"+
"balance double)");
System.out.println("账户表account创建成功!");
}
}
测试结果
2.update():update()能完成插入,更新,删除数据的操作。
(1)创建一个类Account类用来对应数据库spring中的表account,如下:
package com.itheima.jdbc;
/**
* 账户类:用来与数据库spring的表account对应
* @author 12428
*
*/
public class Account {
private Integer id; //账户Id
private String username; //用户名
private Double balance; //用户余额
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Double getBalance() {
return balance;
}
public void setBalance(Double balance) {
this.balance = balance;
}
@Override
public String toString() {
return "Account [id=" + id + ", username=" + username + ", balance=" + balance + "]";
}
}
(2)创建一个接口类AccountDao,接口中含有几个抽象方法,如下:
package com.itheima.jdbc;
public interface AccountDao {
//添加
public int addAccount(Account account);
//更新
public int updateAccount(Account account);
//删除
public int deleteAccount(int id);
}
(3)创建一个类AccountDaoImpl,该类实现了AccountDao接口,如下:
package com.itheima.jdbc;
import org.springframework.jdbc.core.JdbcTemplate;
public class AccountDaoImpl implements AccountDao {
// 声明JdbcTemplate属性及其setter方法,使用setter注入属性
private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
/**
* 添加账户 返回一个修改的行数
*/
@Override
public int addAccount(Account account) {
// 定义sql语句
String sql = "insert into account(username,balance) value(?,?)";
// 定义数组来存储sql语句中的参数
Object[] objects = new Object[] { account.getUsername(), account.getBalance() };
// 执行添加操作,返回的是受SQL影响的记录数
int num = this.jdbcTemplate.update(sql, objects);
return num;
}
/**
* 更新账户
*/
@Override
public int updateAccount(Account account) {
// 定义SQL
String sql = "update account set username=?,balance=? where id=?";
// 定义数组来存储sql语句中的参数
Object[] objects = new Object[] { account.getUsername(), account.getBalance(), account.getId() };
// 执行更新操作,返回的是受SQL语句影响的记录条数
int num = this.jdbcTemplate.update(sql, objects);
return num;
}
/**
* 删除用户
*/
@Override
public int deleteAccount(int id) {
// 定义sql
String sql = "delete from account where id=?";
// 执行删除操作,返回的是受sql语句影响的记录条数
int num = this.jdbcTemplate.update(sql, id);
return num;
}
}
(4)设置配置文件applicationContext.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd">
<!-- 配置数据源 -->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<!-- 数据库驱动 -->
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<!-- 连接数据库的Url -->
<property name="url" value="jdbc:mysql://localhost:3306/spring"/>
<!-- 连接数据库的用户名 -->
<property name="username" value="root"/>
<!-- 连接数据库的用户名 -->
<property name="password" value="abc"/>
</bean>
<!-- 配置JDBC模板 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<!-- 默认使用数据源 -->
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 配置一个AccountDao的Bean,把jdbcTemplate注入到accountDao里面 -->
<bean id="accountDao" class="com.itheima.jdbc.AccountDaoImpl">
<property name="jdbcTemplate" ref="jdbcTemplate"/>
</bean>
</beans>
(5)创建一个测试类JdbcTemplateTest,使用单元测试,如下:
package com.itheima.jdbc;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
public class JdbcTemplateTest {
/*
* public static void main(String[] args) { //获取配置文件 ApplicationContext
* applicationContext= new
* ClassPathXmlApplicationContext("applicationContext.xml"); //获取JdbcTemplate模板
* JdbcTemplate jdbcTemplate=(JdbcTemplate)
* applicationContext.getBean("jdbcTemplate");
* //使用execute()方法执行SQL语句,创建用户账号管理表account
* jdbcTemplate.execute("create table account("+
* "id int primary key auto_increment,"+ "username varchar(50),"+
* "balance double)"); System.out.println("账户表account创建成功!"); }
*/
/**
* 添加一个用户
*/
@Test
public void addAccount() {
// 加载配置文件
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
// 获取bean
AccountDao accountDao = (AccountDao) applicationContext.getBean("accountDao");
// 创建一个用户
Account account = new Account();
account.setUsername("张三");
account.setBalance(2000.0);
// 调用方法
int num = accountDao.addAccount(account);
// 返回一个结果
if (num > 0) {
System.out.println("你已成功添加了" + num + "条数据");
} else {
System.out.println("添加数据失败!");
}
}
/**
* 更新一个用户
*/
@Test
public void updateAccount() {
// 加载配置文件
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
// 获取bean
AccountDao accountDao = (AccountDao) applicationContext.getBean("accountDao");
// 创建一个用户
Account account = new Account();
account.setId(1);
account.setUsername("李四");
account.setBalance(2000.0);
// 执行更新方法
int num = accountDao.updateAccount(account);
// 返回一个结果
if (num > 0) {
System.out.println("你已成功修改了" + num + "条数据");
} else {
System.out.println("添加数据失败!");
}
}
/**
* 删除一个用户
*/
@Test
public void deleteAccount() {
// 加载配置文件
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
// 获取bean
AccountDao accountDao = (AccountDao) applicationContext.getBean("accountDao");
// 执行删除方法
int num = accountDao.deleteAccount(1);
// 输出结果
if (num > 0) {
System.out.println("你成功删除了" + num + "条数据");
} else {
System.out.println("删除数据失败!");
}
}
}
(6)运行添加方法的结果如下:
(7)运行了更新方法的结果如下:
(8)运行了删除方法后的结果如下:
3.query():query()方法可以执行查询操作
jdbcTemplate中提供了大量的查询方法,如下是几个常用的查询方法:
方法名 | 说明 |
List query(String sql,RowMapper rowMapper) | 执行string类型参数提供的的sql语句,并通过RowMapper返回一个List类型的结果 |
List query(String sql,PreparedStatementSetter pss,RowMapper rowMapper) | 根据String类型的参数提供的Sql语句创建的PreparedStatements对象通过RowMapper将结果返回到List中。 |
List query(String sql,Object[] args,RowMapper rowMapper) | 使用Object[]的值来设置sql语句中的参数值,采用RowMapper回调方法直接返回List类型的数据 |
queryForObject(String sql,RowMapper rowMapper,Object...args) | 将args参数绑定到SQL语句中,并通过RowMapper返回一个Object类型的单行记录 |
queryForList(String sql,Object[] args,class<T> elementType) | 该方法可以返回多行数据的结果,但必须是返回列表,elementsType参数返回的是List元素类型 |
(1)先给数据库中添加几条数据,如下:
(2)在AccountDao接口中添加两个查询方法:
//通过id查询
public Account queryAccountById(int id);
//查询所有的用户
public List<Account> queryAllAcount();
(3)在AccounDaoImpl中实现两个查询方法
/**
* 根据id来查询账户
*/
@Override
public Account queryAccountById(int id) {
//声明sql语句
String sql="select * from account where id=?";
//创建一个新的BeanPropertyRowMapper对象,返回一个需要返回的对象类型,不用再手动转换类型
RowMapper<Account> rowMapper=new BeanPropertyRowMapper<Account>(Account.class);
//执行查询语句
return this.jdbcTemplate.queryForObject(sql, rowMapper, id);
}
/**
* 查询所有的账户
*/
@Override
public List<Account> queryAllAcount() {
//声明sql语句
String sql="select * from account";
//创建一个新的BeanPropertyRowMapper对象,返回一个需要返回的对象类型,不用再
//手动转换类型
RowMapper<Account> rowMapper=new BeanPropertyRowMapper<Account>(Account.class);
//执行方法
return this.jdbcTemplate.query(sql, rowMapper);
}
(4)在jdbcTemplateTest中添加两个测试方法,如下:
/**
* 根据id来查询用户
*/
@Test
public void queryAccountById() {
// 加载配置文件
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
// 获取bean
AccountDao accountDao = (AccountDao) applicationContext.getBean("accountDao");
//执行方法
Account account=accountDao.queryAccountById(1);
System.out.println(account);
}
/**
* 查询所有的账户
*/
@Test
public void queryAllAccount() {
//获取容器对象
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
//获取对象AccountDao
AccountDao accountDao=(AccountDao) applicationContext.getBean("accountDao");
//执行方法
List<Account> accounts=accountDao.queryAllAcount();
//输出结果
for(Account account:accounts) {
System.out.println(account);}
}
(5)执行第一个查询方法:根据Id来进行查询,结果如下:
(6)执行第二个插叙方法:查询所有的账户,结果如下:
注意:在执行jdbcTemplate查询操作时,如果查询的结果为空,则会抛出一个错误emptyResultDataAccessException异常,这样做的目的是为了防止程序员不对空值进行判断,保证了查程序的健壮性,如果想要查询结果为空时返回一个null而不是异常,则可以在jdbcTemplate返回查询结果的时候捕获异常,然尔返回null,例:
try{
Object obj=jdbcTemplate.queryForObject();
}catch(EmptyResultDataAccessException e){
return null;
}