SpringJDBC使用
Spring框架对JDBC的简单封装。提供了一个JDBCTemplate
对象简化JDBC的开发 , 使用非常简单, .
1.2JdbcTemplate开发步骤
①导入spring-jdbc和spring-tx坐标
②创建数据库表和实体
③创建JdbcTemplate对象
④执行数据库操作
- update():执行DML语句。增、删、改语句
- queryForMap():查询结果将结果集封装为map集合,将列名作为key,将值作为value 将这条记录封装为一个map集合
- 注意:这个方法查询的结果集长度只能是1
- queryForList():查询结果将结果集封装为list集合
- 注意:将每一条记录封装为一个Map集合,再将Map集合装载到List集合中
- query():查询结果,将结果封装为JavaBean对象
- query的参数:RowMapper
- 一般我们使用BeanPropertyRowMapper实现类。可以完成数据到JavaBean的自动封装
- new BeanPropertyRowMapper<类型>(类型.class)
- queryForObject:查询结果,将结果封装为对象
- 一般用于聚合函数的查询
入门代码
@Test
public void test1(){
//1. 创建JdbcTemplate对象
JdbcTemplate jt = new JdbcTemplate(JdbcUtils3.getDataSource());
//2. 编写sql语句
String sql = "insert into `student` values (null ,'马小云',25,'女','北京',100,100)";
int row = jt.update(sql);
if(row>0){
System.out.println("插入成功....");
}else{
System.out.println("插入失败....");
}
}
案例练习
public class JdbcTemplateDemo2 {
//1. 获取JDBCTemplate对象
private JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
/**
* 1. 修改1号数据的 salary 为 10000
*/
@Test
public void test1(){
//2. 定义sql
String sql = "update emp set salary = 10000 where id = 1001";
//3. 执行sql
int count = template.update(sql);
System.out.println(count);
}
/**
* 2. 添加一条记录
*/
@Test
public void test2(){
String sql = "insert into emp(id,ename,dept_id) values(?,?,?)";
int count = template.update(sql, 1015, "郭靖", 10);
System.out.println(count);
}
/**
* 3.删除刚才添加的记录
*/
@Test
public void test3(){
String sql = "delete from emp where id = ?";
int count = template.update(sql, 1015);
System.out.println(count);
}
/**
* 4.查询id为1001的记录,将其封装为Map集合
* 注意:这个方法查询的结果集长度只能是1
*/
@Test
public void test4(){
String sql = "select * from emp where id = ? or id = ?";
Map map = template.queryForMap(sql, 1001,1002);
System.out.println(map);
//{id=1001, ename=孙悟空, job_id=4, mgr=1004, joindate=2000-12-17, salary=10000.00, bonus=null, dept_id=20}
}
/**
* 5. 查询所有记录,将其封装为List
*/
@Test
public void test5(){
String sql = "select * from emp";
List
Spring声明式事物控制
1.事务隔离级别
设置隔离级别,可以解决事务并发产生的问题,如脏读、不可重复读和虚读。
ISOLATION_DEFAULT
ISOLATION_READ_UNCOMMITTED
ISOLATION_READ_COMMITTED
ISOLATION_REPEATABLE_READ
ISOLATION_SERIALIZABLE
2.事务传播行为
REQUIRED:如果当前没有事务, 就新建一个事务, 如果已经存在一个事务中, 加入到这个事务中。一般的选择(默认值)
SUPPORTS:支持当前事务, 如果当前没有事务, 就以非事务方式执行(没有事务)
MANDATORY:使用当前的事务, 如果当前没有事务, 就抛出异常
REQUERS_NEW:新建事务, 如果当前在事务中, 把当前事务挂起。
NOT_SUPPORTED:以非事务方式执行操作, 如果当前存在事务, 就把当前事务挂起
NEVER:以非事务方式运行, 如果当前存在事务, 抛出异常
NESTED:如果当前存在事务, 则在嵌套事务内执行。如果当前没有事务, 则执行R EQUIRED类似的操作
超时时间:默认值是-1,没有超时限制。如果有,以秒为单位进行设置
是否只读:建议查询时设置为只读
声明式事物控制概述
JavaEE体系进行分层开发,事务处理位于业务层,Spring提供了分层设计业务层的事务处理解决方案。
spring框架为我们提供了一组事务控制的接口。具体在后面的第二小节介绍。这组接口是在spring-tx-5.0.2.RELEASE.jar中。
spring的事务控制都是基于AOP的,它既可以使用编程的方式实现,也可以使用配置的方式实现。我们学习的重点是使用配置的方式实现。
事务控制的API介绍
PlatformTransactionManager
此接口是spring的事务管理器,它里面提供了我们常用的操作事务的方法,如下图:
我们在开发中都是使用它的实现类
常用的实现类:
org.springframework.jdbc.datasource.DataSourceTransactionManager
使用Spring JDBC或iBatis 进行持久化数据时使用
org.springframework.orm.hibernate5.HibernateTransactionManager
使用Hibernate版本进行持久化数据时使用
TransactionDefinition
描述的是事务的定义信息对象,里面有如下方法:
事物的隔离级别
事物的传播行为
事务的传播行为:它解决的是两个被事务管理的方法互相调用问题。它与数据库没关系,是程序内部维护的问题。
REQUIRED:如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。一般的选择(默认值)
SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行(没有事务)
MANDATORY:使用当前的事务,如果当前没有事务,就抛出异常 REQUERS_NEW:新建事务,如果当前在事务中,把当前事务挂起。
NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起
NEVER:以非事务方式运行,如果当前存在事务,抛出异常 NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行REQUIRED类似的操作。
TransactionStatus
此接口提供的是事务具体的运行状态,方法介绍如下图:
转账案例环境准备
创建maven项目
导入依赖jar包
junit
junit
4.12
mysql
mysql-connector-java
5.1.38
org.springframework
spring-context
5.0.2.RELEASE
org.springframework
spring-jdbc
5.0.2.RELEASE
org.springframework
spring-test
5.0.2.RELEASE
c3p0
c3p0
0.9.1.2
cglib
cglib
3.2.2
org.aspectj
aspectjweaver
1.8.7
org.apache.maven.plugins
maven-compiler-plugin
3.7.0
1.8
编写实体类
public class Account {
private int id ;
private String username ;
private double money ;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public double getMoney() {
return money;
}
public void setMoney(double money) {
this.money = money;
}
}
编写数据访问层
接口AccountDao
public interface AccountDao {
/**
* 根据用户名称查询用户信息
* @param name
* @return
*/
Account findByName(String name) throws SQLException;
/**
* 更新账户信息
* @param source
*/
void update(Account source) throws SQLException;
}
实现类AccountDaoImpl
@Repository
public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao {
@Override
public Account findByName(String name) throws SQLException {
String sql = "select * from account where username = ? ";
try {
return getJdbcTemplate().queryForObject(sql, new BeanPropertyRowMapper(Account.class), name);
} catch (DataAccessException e) {
e.printStackTrace();
}
return null ;
}
@Override
public void update(Account account) throws SQLException {
String sql = "update account set money = ? where username = ? ";
getJdbcTemplate().update(sql,account.getMoney(),account.getUsername());
}
}
创建业务层
接口AccountService
public interface AccountService {
/**
* 转账业务功能
* @param sourceName 转出账户
* @param targetName 转入账户
* @param money 转账金额
* @throws SQLException
*/
public void transfer(String sourceName, String targetName, double money) throws SQLException;
}
实现类AccountServiceImpl
public class AccountServiceImpl implements AccountService {
private AccountDao accountDao ;
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
@Override
public void transfer(String sourceName, String targetName, double money) throws SQLException {
//1.根据名称查询转出账户
Account source = accountDao.findByName(sourceName);
//2.根据名称查询转入账户
Account target = accountDao.findByName(targetName);
//3.转出账户减钱
source.setMoney(source.getMoney()-money);
//4.转入账户加钱
target.setMoney(target.getMoney()+money);
//5.更新转出账户余额
accountDao.update(source);
//int i = 10 / 0 ; //特意添加的异常代码,让程序执行异常
//6.更新转入账户余额
accountDao.update(target);
}
}
编写核心配置文件
编写Spring核心配置文件
beans.xml
编写测试类
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:beans.xml")
public class AccountServiceTest {
@Autowired
private AccountService accountService ;
@Test
public void transfer() throws SQLException {
//zhangsan给lisi转账1000元
accountService.transfer("zhangsan","lisi",1000);
}
}
声明式事务控制实现
配置事务步骤
1. 配置事务管理器
2. 配置事务的通知:此时我们需要导入事务的约束 tx名称空间和约束,同时也需要aop的名称空间和约束
tx:advice标签配置事务通知:
属性:
id:给事务通知起一个唯一标识
transaction-manager:给事务通知提供一个事务管理器引用
3. 配置AOP中的通用切入点表达式
4. 建立事务通知和切入点表达式的对应关系
5. 配置事务的属性:在事务的通知tx:advice标签的内部
配置声明式事务控制
Spring注解事务控制
修改数据访问层
修改业务层
修改配置文件
修改配置文件
beans.xml
开启事物支持
①使用@Transactional在需要进行事务控制的类或是方法上修饰, 注解可用的属性同xml配置方式, 例如:隔离级别、传播行为等。
②注解使用在类上,那么该类下的所有方法都使用同一套注解参数配置。
③使用在方法上,不同的方法可以采用不同的事务参数配置.
④Xml配置文件中要开启事务的注解驱动