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;
}