1.Spring JDBC
1.1applicationContext.xml内配置好数据库相关信息
1.2创建实体类MyUser
public class MyUser {
private Integer uid;
private String uname;
private String usex;
public Integer getUid() {
return uid;
}
public void setUid(Integer uid) {
this.uid = uid;
}
public String getUname() {
return uname;
}
public void setUname(String uname) {
this.uname = uname;
}
public String getUsex() {
return usex;
}
public void setUsex(String usex) {
this.usex = usex;
}
public String toString() {
return "myUser [uid=" + uid +", uname=" + uname + ", usex=" + usex + "]";
}
}
1.3创建数据库访问层TestDao
接口类:
package ch5;
import java.util.List;
public interface TestDao {
public int update(String sql, Object[] param);
public List query(String sql, Object[] param);
}
实现类:
@Repository("testDao")
public class TestDaoImpl implements TestDao{
//自动装配
@Autowired
//使用配置文件中的JDBC(相当于依赖注入了)
private JdbcTemplate jdbcTemplate;
//更新方法
@Override
public int update(String sql, Object[] param) {
return jdbcTemplate.update(sql, param);
}
//查询方法
@Override
public List query(String sql, Object[] param) {
RowMapper rowMapper = new BeanPropertyRowMapper(MyUser.class);
return jdbcTemplate.query(sql, rowMapper, param);
}
}
1.4测试:
public static void main(String[] args) {
@SuppressWarnings("resource")
ApplicationContext appCon = new ClassPathXmlApplicationContext("applicationContext.xml");
//从容器中获取增强后的目标对象
TestDao td = (TestDao)appCon.getBean("testDao");
//插入的sql
//暂时没有在这里发现问题:
//UID为主键,这里设置为空,不会出现问题,原因是:mysql数据库里面可以勾选主键自动增长
String insertSql = "insert into user values(null,?,?)";
//数组param的值与insertSql语句一一对应
//此处我的mysql不支持中文字符,改成了英文字符,不影响
Object param1[] = {"chenheng1", "nan"};
Object param2[] = {"chenheng2", "nv"};
Object param3[] = {"chenheng3", "nan"};
Object param4[] = {"chenheng4", "nv"};
//添加用户
td.update(insertSql, param1);
td.update(insertSql, param2);
td.update(insertSql, param3);
td.update(insertSql, param4);
//查询用户的sql
String selectSql ="select * from user";
List list = td.query(selectSql, null);
for(MyUser mu : list) {
System.out.println(mu);
}
}
}
2.编程式事务管理
(1)基于底层API的编程式事务管理
2.1.1 applicationContext.xml内配置事务管理器
2.1.2 创建数据访问类
//数据访问类
@Repository("codeTransaction")
public class CodeTransaction {
@Autowired
// 使用配置文件中的JDBC模板
private JdbcTemplate jdbcTemplate;
//DataSourceTransactionManager是PlatformTransactionManager接口的实现类
@Autowired
private DataSourceTransactionManager txManager;
//定义test方法
public String test() {
// 默认事务定义,例如隔离级别、传播行为
TransactionDefinition tf = new DefaultTransactionDefinition();
//开启事务ts
TransactionStatus ts = txManager.getTransaction(tf);
String message = "ִ执行成功,没有事务回滚";
try {
// 删除表中数据
String sql = " delete from user ";
//添加表中数据
String sql1 = " insert into user values(?,?,?) ";
Object param[] = { 1, "topus", "nan" };
// 先删除数据
jdbcTemplate.update(sql);
//添加一条数据
jdbcTemplate.update(sql1, param);
// 添加相同的一条数据
jdbcTemplate.update(sql1, param);
//提交事务
txManager.commit(ts);
} catch (Exception e) {
// 出现异常,事务回滚
txManager.rollback(ts);
message = "主键重复,事务回滚";
e.printStackTrace();
}
//返回的是执行成功与否的消息
return message;
}
}
2.2.3测试
public class TestCodeTransaction {
public static void main(String[] args) {
@SuppressWarnings("resource")
ApplicationContext appCon = new ClassPathXmlApplicationContext("applicationContext.xml");
CodeTransaction ct = (CodeTransaction)appCon.getBean("codeTransaction");
String result = ct.test();
System.out.println(result);
}
}
(2)基于TranesactionTemplate的编程式事务管理
2.2.1为事务管理器添加事务模板
2.2.2 创建数据访问类
@Repository("transactionTemplateDao")
public class TransactionTemplateDao {
@Autowired
//使用配置文件中的jdbc
private JdbcTemplate jdbcTemplate;
@Autowired
private TransactionTemplate transactionTemplate;
String message = "";
public String test() {
//匿名内部类
transactionTemplate.execute(new TransactionCallback
2.2.3 创建测试类
public class TransactionTemplateTest {
public static void main(String[] args) {
@SuppressWarnings("resource")
ApplicationContext appCon = new ClassPathXmlApplicationContext("applicationContext.xml");
TransactionTemplateDao ct = (TransactionTemplateDao)appCon.getBean("transactionTemplateDao");
String result = ct.test();
System.out.println(result);
}
}
3.声明式事务管理
(基于AOP技术实现的事务管理,其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务)
(1)xml
3.1.1创建Dao层
public interface TestDao {
public int save(String sql, Object param[]);
public int delete(String sql, Object param[]);
}
@Repository("TestDao")
public class TestDaoImpl implements TestDao{
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public int save(String sql, Object[] param) {
return jdbcTemplate.update(sql,param);
}
@Override
public int delete(String sql, Object[] param) {
return jdbcTemplate.update(sql,param);
}
}
3.1.2创建service层
public class TestServiceImpl implements TestService{
@Autowired
private TestDao testDao;
@Override
// 这里调用Dao层的save和delete方法,参数为sql和param,等控制层在传入sql语句
public int save(String sql, Object[] param) {
return testDao.save(sql, param);
}
@Override
public int delete(String sql, Object[] param) {
return testDao.delete(sql, param);
}
}
3.1.3创建controller层
private TestService testService;
public String test() {
// 此处在加入sql语句
String message = "";
String deleteSql ="delete from user";
String saveSql = "insert into user values(?,?,?)";
Object param[] = {1,"topus","nan"};
try{
testService.delete(deleteSql, null);
testService.save(saveSql, param);
//重复插入相同主键的数据
testService.save(saveSql, param);
}catch(Exception e){
message = "主键重复,回滚";
e.printStackTrace();
}
return message;
}
}
3.1.4创建配置文件
在xml里面使用
使用
3.1.6测试
public static void main(String[] args) {
@SuppressWarnings("resource")
ApplicationContext appCon = new ClassPathXmlApplicationContext("/com/statement/xml/XMLstatementapplicationContext.xml");
StatementController ct = (StatementController)appCon.getBean("statementController");
String result = ct.test();
System.out.println(result);
}
(2)基于transactional注解的声明式事务管理
3.2.1创建配置文件
3.2.2在service层添加注解@Transactional
//加上注解@Transactional,就可以指定这个类需要受Spring的事务管理
//注意@Transactional智能针对pulic属性范围内的方法添加
@Transactional
public class TestServiceImpl implements TestService{
@Autowired
private TestDao testDao;
@Override
// 这里调用Dao层的save和delete方法,参数为sql和param,等控制层在传入sql语句
public int save(String sql, Object[] param) {
return testDao.save(sql, param);
}
@Override
public int delete(String sql, Object[] param) {
return testDao.delete(sql, param);
}
}
3.2.3在事务处理中捕获异常
修改注解
@Transactional(rollbackFor = (Exception.class))
//指定回滚生效的异常类
其实本质上问题在于书内的try catch的异常捕获写在的service层,但是在默认情况下,Spring只在(发生未被捕获的RuntimeException时)才回滚事务,此时如果想在事务处理中捕获异常就必须指定回滚生效的异常类.