1 spring中的JdbcTemplate
2 spring基于AOP的事务控制
3 spring中的事务控制
- 基于XML
- 基于注解
1 JdbcTemplate的概述和入门
持久层总图
JdbcTemplate的作用
它就是用于和数据库交互的,实现对表的CURD操作
如何创建该对象
对象中常用的方法
导入以下依赖
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
</dependencies>
建立账户的实体类
/**
* 账户的实体类
*/
public class Account implements Serializable {
private Integer id;
private String name;
private Float money;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Float getMoney() {
return money;
}
public void setMoney(Float money) {
this.money = money;
}
@Override
public String toString() {
return "Account{" +
"id=" + id +
", name='" + name + '\'' +
", money=" + money +
'}';
}
}
JdbcTemplate的最基本用法
public class demo1 {
public static void main(String[] args) {
//准备数据源 spring的内置数据源
DriverManagerDataSource ds = new DriverManagerDataSource();
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/springtest");
ds.setUsername("root");
ds.setPassword("xgh961120");
//1 创建JdbcTemplate对象
JdbcTemplate jt = new JdbcTemplate();
//给jt设置数据源
jt.setDataSource(ds);
//2执行工作
jt.execute("insert into account(name,money)VALUES ('ccc',1000)");
}
}
但代码中存在的问题
解决JdbcTemplate在spring的IOC使用
配置bean.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.xsd">
<!--配置JdbcTemplate-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--配置数据源-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/springtest"></property>
<property name="username" value="root"></property>
<property name="password" value="xgh961120"></property>
</bean>
</beans>
测试
public class demo2 {
public static void main(String[] args) {
//1获取容器
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
//2获取对象
JdbcTemplate jt = ac.getBean("jdbcTemplate",JdbcTemplate.class);
//3执行操作
jt.execute("insert into account(name,money)VALUES ('ddd',1000)");
}
}
解决了在配置中写死的问题
JdbcTemlate的CRUD操作
/**
* JdbcTemplate的CRUD操作
*/
public class demo3 {
public static void main(String[] args) {
//1获取容器
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
//2获取对象
JdbcTemplate jt = ac.getBean("jdbcTemplate",JdbcTemplate.class);
//3执行操作
//保存
jt.update("insert into account(name,money) values(?,?)","eeee",3333f);
//更新
jt.update("update account set name =?,money=? where id=?","test",4567f,4);
//删除
jt.update("delete from account where id=?",4);
- 有很多重载的query方法,如何去定位呢
- 1我们有什么:1sql语句,2语句的参数
- 2我们要什么: 返回一个List集合,根据返回值类型筛选函数
- 筛选结果
//查询所有
List<Account> accounts = jt.query("select * from account where money > ?", new AccountRowMapper(), 1000f);
for (Account account : accounts) {
System.out.println(account);
}
}
}
定义Account的封装策略
class AccountRowMapper implements RowMapper<Account>{
/**
* 把结果集的数据封装到Account中,然后由spring把每个Account加到集合中
* @param rs
* @param rowNum
* @return
* @throws SQLException
*/
@Nullable
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;
}
}
对比JdbcTemplate中的query方法和dbutils中的query方法
jdbctemplate和queryrunner的区别
sql语句和参数是一样的,唯一不同的是中间的参数,对结果集的封装
从封装的角度是一样的RowMappe的实现类和ResultMapper都是对类的封装
也可以用sring提供的实现类BeanPropertyRowMapper(不用自己实现RowMapper<Account>
)
List<Account> accounts = jt.query("select * from account where money > ?", new BeanPropertyRowMapper<Account>(Account.class), 1000f);
查询一个
List<Account> accounts = jt.query("select * from account where id= ?", new BeanPropertyRowMapper<Account>(Account.class), 1);
System.out.println(accounts.isEmpty()?"no":accounts.get(0));
查询返回一行一列(使用聚合函数,但不加group by子句)
第二个参数是要返回的类型
Integer count = jt.queryForObject("select count(*) from account where money > ?", Integer.class, 1000f);
System.out.println(count);
JdbcTemplate在Dao中的使用
账户的持久层接口
public interface IAccountDao {
/**
* 根据Id查询账户
* @param accountId
* @return
*/
Account findAccountById(Integer accountId);
/**
* 根据名称查询账户
* @param accountName
* @return
*/
Account findAccountByName(String accountName);
/**
* 更新账户
* @param account
*/
void updateAccount(Account account);
}
账户的持久层实现类
/**
* 账户的持久层实现类
*/
public class AccountDaoImpl implements IAccountDao{
private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
public Account findAccountById(Integer accountId) {
List<Account> accounts=jdbcTemplate.query("select * from account where id =?",new BeanPropertyRowMapper<Account>(Account.class),accountId);
return accounts.isEmpty()?null:accounts.get(0);
}
public Account findAccountByName(String accountName) {
List<Account> accounts=jdbcTemplate.query("select * from account where name =?",new BeanPropertyRowMapper<Account>(Account.class),accountName);
if (accounts.isEmpty()){
return null;
}
if (accounts.size()>1){
throw new RuntimeException("结果集不唯一");
}
return accounts.get(0);
}
public void updateAccount(Account account) {
jdbcTemplate.update("update account set name =? ,money =? where id=?",account.getName(),account.getMoney(),account.getId());
}
}
在bean.xml中配置账户的持久层
<!--配置账户的持久层-->
<bean id="accountDao" class="cn.tju.dao.impl.AccountDaoImpl">
<property name="jdbcTemplate" ref="jdbcTemplate"></property>
</bean>
<!--配置JdbcTemplate-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
测试
public class demo4 {
public static void main(String[] args) {
//1获取容器
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
//2获取对象
IAccountDao accountDao =ac.getBean("accountDao",IAccountDao.class);
Account account = accountDao.findAccountById(1);
System.out.println(account);
account.setMoney(10000f);
//更新
accountDao.updateAccount(account);
}
}
JdbcDaoSupport的使用以及Dao的两种编写方式
在不同Dao中的重复代码
抽取公共代码
/**
* 此类抽取Dao中的重复代码
*/
public class JdbcDaoSupport {
//抽取的公共代码
private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
//添加get方法,抽取公共代码中原来代码的变量通过get方法获取
public JdbcTemplate getJdbcTemplate() {
return jdbcTemplate;
}
}
改造原来的Dao继承公共代码类,并通过调用父类的getgetJdbcTemplate()方法获取变量
public class AccountDaoImpl extends JdbcDaoSupport implements IAccountDao{
public Account findAccountById(Integer accountId) {
List<Account> accounts=super.getJdbcTemplate().query("select * from account where id =?",new BeanPropertyRowMapper<Account>(Account.class),accountId);
return accounts.isEmpty()?null:accounts.get(0);
}
public Account findAccountByName(String accountName) {
List<Account> accounts=super.getJdbcTemplate().query("select * from account where name =?",new BeanPropertyRowMapper<Account>(Account.class),accountName);
if (accounts.isEmpty()){
return null;
}
if (accounts.size()>1){
throw new RuntimeException("结果集不唯一");
}
return accounts.get(0);
}
public void updateAccount(Account account) {
super.getJdbcTemplate().update("update account set name =? ,money =? where id=?",account.getName(),account.getMoney(),account.getId());
}
}
接着改造抽取出来的公共代码类
public class JdbcDaoSupport {
private DataSource dataSource;
public void setDataSource(DataSource dataSource) {
this.dataSource=dataSource;
if(jdbcTemplate == null){
jdbcTemplate = createjdbcTemplate(dataSource);
}
}
private JdbcTemplate createjdbcTemplate(DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
这么写之后可以通过配置dataSource来创建jdbcTemplate,可以不注入 jdbcTemplate
只注入dataSource触发公共类中的setDataSource方法,从而创建一个jdbcTemplate 对象
<!--配置账户的持久层-->
<bean id="accountDao" class="cn.tju.dao.impl.AccountDaoImpl">
<!--不再注入<property name="jdbcTemplate" ref="jdbcTemplate"></property>-->
<property name="dataSource" ref="dataSource"></property>
</bean>
其实spring中已经实现了JdbcDaoSupport
spring中的JdbcDaoSupport
作用:Dao实现类继承JdbcDaoSupport 去除掉注入和定义的重复代码
一旦继承spring的JdbcDaoSupport 的话,无法加注解,没法改jar包