Spring(9)Spring和数据库编程
一、JdbcTemplate 概述
在前面我们连接数据库通过传统的JDBC代码方式实现数据连接,可以参看Spring(2) IoC 的概念和作用中的例子,在JDBC中可能存在滥用try .. catch ... finally .. 语句,导致代码可读性和维护性下降,那么Spring提出了自己的解决方案,那就是 jdbcTemplte模板。
它是 spring 框架中提供的一个对象,是对原始 Jdbc API 对象的简单封装。spring 框架为我们提供了很多的操作模板类。
操作关系型数据的:JdbcTemplate;HibernateTemplate操作 nosql 数据库的:RedisTemplate。操作消息队列的:JmsTemplate等。
二、数据库资源配置
在实际工作中我们大部分会配置为数据库连接池,我们可以使用Spring内部提供的类,也可以使用第三方数据库连接池或者WEB服务器中的JNDI获取数据源。如果使用第三方类,一般配置工程偏向于采用XML方式进行配置。这里我比较喜欢XML配置方式。
1.使用简单数据库配置
我们通过Spring提供的一个类:org.springframework.jdbc.datasource.SimpleDriverDataSource,来完成数据库简单的配置,它不支持数据库连接池。
<bean id="dataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource"> <property name="username" value="root"/> <property name="password" value="root"/> <property name="dirverClass" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/spring"/> </bean>
2.使用第三方数据库连接池
使用第三方数据库连接池,比如DBCP数据库连接池,我们引入相应的依赖包后就可以使用它了。
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"> <property name="driverClassName" value="com.mysal.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/spring"/> <property name="username" value="root"/> <property name="password" value="root"/> <property name="maxActive" value="255"/> <property name="maxIdle" value="5"/> <property name="maxWait" value="10000"/> </bean>
3.使用JNDI数据库连接池
在Tomcat和WebLogic等服务器上配置数据源,这时它存在一个JNDI的名称。通常可以通过Spring提供的JNDI机制获取对于的数据源。假设我们已经在Tomcat上配置了JNDI为jdbc/spring的数据源,这样我们可以在Web工程中获取这个JNDi数据源。
<bean id="dataSource" class="org.springframeworj.jndi.JndiObjectFactoryBean"> <property name="jndiName" value="java:comp/env/jdbc/spring"/> </bean>
三、JdbcTemplate 实现增删改查操作
1.环境搭建
我们还是以之前账户的例子进行举例。
(1)数据库建表(略)
(2)引入依赖文件
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.xhbjava</groupId> <artifactId>Spring02</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.0.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>5.0.2.RELEASE</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.0.2.RELEASE</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-tx --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>5.0.2.RELEASE</version> </dependency> <dependency> <groupId>commons-dbutils</groupId> <artifactId>commons-dbutils</artifactId> <version>1.4</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.19</version> </dependency> <dependency> <groupId>c3p0</groupId> <artifactId>c3p0</artifactId> <version>0.9.1.2</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.4</version> </dependency> </dependencies> </project>
(3)配置数据源
<!-- 配置数据源 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="com.mysql.jdbc.Driver"></property> <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/ssm?useSSL=true&serverTimezone=UTC&characterEncoding=UTF-8" /> <property name="user" value="root"></property> <property name="password" value="root"></property> </bean>
(4)配置 JdbcTemplate
<!-- 数据库模板配置 --> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"></property> </bean>
2.JdbcTemplate简单操作
(1)保存
@Test public void testJdbcTemplateAdd() { //1.获取Spring容器 ctx = new ClassPathXmlApplicationContext("bean.xml"); //2.根据id获取bean对象 JdbcTemplate jt =(JdbcTemplate)ctx.getBean("jdbcTemplate"); //3.执行操作 jt.execute("insert into account(name,money)values('jdbcTemplate',500)"); }
(2)更新
@Test public void testJdbcTemplateUpdate() { //1.获取Spring容器 ctx = new ClassPathXmlApplicationContext("bean.xml"); //2.根据id获取bean对象 JdbcTemplate jt =(JdbcTemplate)ctx.getBean("jdbcTemplate"); //3.执行操作 jt.update("update account set money = ? where id = ?",6000,6); }
(3)删除
@Test public void testJdbcTemplateDelete() { //1.获取Spring容器 ctx = new ClassPathXmlApplicationContext("bean.xml"); //2.根据id获取bean对象 JdbcTemplate jt =(JdbcTemplate)ctx.getBean("jdbcTemplate"); //3.执行操作 jt.update("delete from account where id = ? ",6); }
(4)查询所有
package com.xhbjava.pojo; import java.sql.ResultSet; import java.sql.SQLException; import org.springframework.jdbc.core.RowMapper; public class AccountRowMapper implements RowMapper<Account>{ public Account mapRow(ResultSet rs, int rowNum) throws SQLException { Account account = new Account(); account.setId(rs.getInt("id")); account.setName(rs.getString("name")); account.setMoney(rs.getFloat("money")); return account; } }
@Test public void testJdbcTemplateQueryAll() { //1.获取Spring容器 ctx = new ClassPathXmlApplicationContext("bean.xml"); //2.根据id获取bean对象 JdbcTemplate jt =(JdbcTemplate)ctx.getBean("jdbcTemplate"); //3.执行操作 List<Account> accounts = jt.query("select * from account where money > ? ", new AccountRowMapper(), 500); for(Account o : accounts){ System.out.println(o); } }
(5)单个查询
@Test public void testJdbcTemplateQueryOne() { //1.获取Spring容器 ctx = new ClassPathXmlApplicationContext("bean.xml"); //2.根据id获取bean对象 JdbcTemplate jt =(JdbcTemplate)ctx.getBean("jdbcTemplate"); //3.执行操作 List<Account> as = jt.query("select * from account where id = ? ", new AccountRowMapper(), 55); System.out.println(as.isEmpty()?"没有结果":as.get(0)); }
(6)查询返回一行一列
@Test public void testJdbcTemplateQueryOneByOne() { //1.获取Spring容器 ctx = new ClassPathXmlApplicationContext("bean.xml"); //2.根据id获取bean对象 JdbcTemplate jt =(JdbcTemplate)ctx.getBean("jdbcTemplate"); //3.执行操作 Integer total = jt.queryForObject("select count(*) from account where money > ? ",Integer.class,500); System.out.println(total); }
3.数据持久层Dao中使用JdbcTemplate
(1)准备实体类(略)
我们在原有基础上进行即可。
(2)编写接口类和实现类
package com.xhbjava.service; import java.util.List; import com.xhbjava.pojo.Account; /** * 账户的业务层接口 * * @author mr.wang * */ public interface IAccountService { /** * 保存账户 */ void saveAccount(Account account); /** * 更新账户 * @param account */ void updateAccount(Account account); /** * 删除账户 * @param accountId */ void deleteAccount(Integer accountId); /** * 根据id查询账户 * * @param accountId * @return */ Account findById(Integer accountId); /** * 查询所有账户 * @return */ List<Account> findAll(); }
package com.xhbjava.service.impl; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import com.xhbjava.dao.IAccountDao; import com.xhbjava.pojo.Account; import com.xhbjava.service.IAccountService; /** * 账户业务层接口实现类 * * @author mr.wang * */ @Component("accountService") public class AccountServiceImpl implements IAccountService { @Autowired private IAccountDao accountDao; public void saveAccount(Account account) { accountDao.saveAccount(account); } public void updateAccount(Account account) { accountDao.updateAccount(account); } public void deleteAccount(Integer accountId) { accountDao.deleteAccount(accountId); } public Account findById(Integer accountId) { return accountDao.findById(accountId); } public List<Account> findAll() { return accountDao.findAll(); } }
package com.xhbjava.dao; import java.util.List; import com.xhbjava.pojo.Account; /** * 账户持久层接口 * * @author mr.wang * */ public interface IAccountDao { /** * 保存账户 */ void saveAccount(Account account); /** * 更新账户 * @param account */ void updateAccount(Account account); /** * 删除账户 * @param accountId */ void deleteAccount(Integer accountId); /** * 根据id查询账户 * * @param accountId * @return */ Account findById(Integer accountId); /** * 查询所有账户 * @return */ List<Account> findAll(); /** * 更加用户名成查找账户 * @param sourceName * @return */ Account findByName(String sourceName); }
package com.xhbjava.dao.impl; import java.util.List; import org.apache.commons.dbutils.QueryRunner; import org.apache.commons.dbutils.handlers.BeanHandler; import org.apache.commons.dbutils.handlers.BeanListHandler; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Component; import com.xhbjava.dao.IAccountDao; import com.xhbjava.pojo.Account; import com.xhbjava.pojo.AccountRowMapper; /** * 用户持久层接口实现类 * * @author mr.wang * */ @Component("accountDao") public class AccountDaoImpl implements IAccountDao { @Autowired private JdbcTemplate jdbcTemplate; public void saveAccount(Account account) { jdbcTemplate.update("insert into account(name,money) values(?,?)", account.getName(), account.getMoney()); } public void updateAccount(Account account) { jdbcTemplate.update("update account set money = ? where id = ? ", account.getMoney(), account.getId()); } public void deleteAccount(Integer accountId) { jdbcTemplate.update("delete from account where id = ? ", accountId); } public Account findById(Integer accountId) { List<Account> list = jdbcTemplate.query("select * from account where id = ? ", new AccountRowMapper(), accountId); return list.isEmpty() ? null : list.get(0); } public List<Account> findAll() { List<Account> list = jdbcTemplate.query("select * from account ", new AccountRowMapper()); if (list.isEmpty()) { return null; } return list; } public Account findByName(String sourceName) { List<Account> list = jdbcTemplate.query("select * from account where name = ? ", new AccountRowMapper(), sourceName); if (list.isEmpty()) { return null; } if (list.size() > 1) { throw new RuntimeException("结果集不唯一,不是只有一个账户对象"); } return list.get(0); } }
(3)bean.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xmlns:util="http://www.springframework.org/schema/util" xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <bean id="accountService" class="com.xhbjava.service.impl.AccountServiceImpl"> </bean> <!-- 配置dao --> <bean id="accountDao" class="com.xhbjava.dao.impl.AccountDaoImpl"> </bean> <!-- 数据库模板配置 --> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"></property> </bean> <!-- 数据库配置 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="com.mysql.jdbc.Driver"></property> <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/ssm?useSSL=true&serverTimezone=UTC&characterEncoding=UTF-8"></property> <property name="user" value="root"></property> <property name="password" value="root"></property> </bean> </beans>
(4)测试
package com.xhbjava.test; import java.util.List; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import com.xhbjava.pojo.Account; import com.xhbjava.pojo.AccountRowMapper; import com.xhbjava.service.IAccountService; import com.xhbjava.service.impl.AccountServiceImpl; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath:bean.xml") public class testSpring { private ApplicationContext ctx; @Autowired @Qualifier("accountService") private IAccountService as; @Test public void testJdbcTemplateByDao() { Account account = new Account(); account.setId(4); account.setMoney(19000f); as.updateAccount(account); } }