这里列一个小的demo工程,直接利用Spring的jdbcTemplate访问Mysql数据库。
工程结构:
数据库中的tbl_student表结构如下:
数据实体类Student.java代码如下:
package com.mysrc.entity;
import java.sql.Date;
public class Student {
private int id;
private String name;
private Date birth;
private float score;
public Student() {
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getBirth() {
return birth;
}
public void setBirth(Date birth) {
this.birth = birth;
}
public float getScore() {
return score;
}
public void setScore(float score) {
this.score = score;
}
@Override
public String toString() {
return "Student [id=" + id + ", name=" + name + ", birth=" + birth
+ ", score=" + score + "]";
}
}
数据访问类StudentDao.java代码如下:
package com.mysrc.dao;
import java.util.List;
import org.springframework.jdbc.core.JdbcTemplate;
import com.mysrc.entity.Student;
import com.mysrc.entity.StudentRowMapper;
public class StudentDao {
private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
public Student getStudentById(int id) {
return jdbcTemplate.queryForObject(
"select * from tbl_student where id = ?", new Object[] { id },
new StudentRowMapper());
}
public List<Student> getAllStudent() {
return jdbcTemplate.query("select * from tbl_student",
new StudentRowMapper());
}
public int insertStudent(Student student) {
return jdbcTemplate.update(
"insert into tbl_student(name,birth,score) values(?,?,?)",
new Object[] { student.getName(), student.getBirth(),
student.getScore() });
}
public int deleteStudent(int id) {
return jdbcTemplate.update("delete from tbl_student where id = ? ",
new Object[] { id });
}
public int updateStudent(Student student) {
return jdbcTemplate.update(
" update tbl_student set name=?,birth=?,score=? where id=? ",
new Object[] { student.getName(), student.getBirth(),
student.getScore(), student.getId() });
}
}
服务类StudentService.java代码如下:
package com.mysrc.service;
import java.sql.Date;
import java.util.List;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.mysrc.dao.StudentDao;
import com.mysrc.entity.Student;
public class StudentService {
private StudentDao dao;
public void setDao(StudentDao dao) {
this.dao = dao;
}
@Transactional(propagation = Propagation.NESTED, timeout = 1000, isolation = Isolation.READ_COMMITTED, rollbackFor = Exception.class, noRollbackFor = CustomRuntimeException.class)
public void doComplexLogic() {
// select
List<Student> list = dao.getAllStudent();
for (Student student : list) {
System.out.println(student);
}
// update
Student student = list.get(0);
student.setName("zhejiang");
dao.updateStudent(student);
System.out.println("did update temporarily...");
// int a = 9 / 0; // 遇到异常,整个事务回滚
// 如果try catch捕获这个异常,那整个事务会顺利执行,不会回滚
int b = 2;
if (b > 1) {
throw new CustomRuntimeException();
// 事务不会回滚,也就是上面的update操作会提交
}
// insert
student = new Student();
student.setName("hello");
student.setBirth(new Date(354778));
student.setScore(78.9f);
dao.insertStudent(student);
System.out.println("did insert...");
// delete
dao.deleteStudent(3);
System.out.println("did delete...");
}
class CustomRuntimeException extends RuntimeException {
public CustomRuntimeException() {
super();
}
public CustomRuntimeException(String msg) {
super(msg);
}
}
}
doComplexLogic()方法模拟一个复杂的数据库操作过程,方法上加上了@Transactional,其中的各个注解的属性后面再详细研究。网上有人说@Transactional 只能被应用到public方法上, 对于其它非public的方法,如果标记了@Transactional也不会报错,但方法没有事务功能,这个未验证。
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" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd" xmlns:tx="http://www.springframework.org/schema/tx"> <bean id="basicDataSource" class="org.apache.commons.dbcp.BasicDataSource"> <property name="url" value="jdbc:mysql://127.0.0.1:3306/mytestdb?characterEncoding=utf8" /> <property name="driverClassName" value="com.mysql.jdbc.Driver" /> <property name="username" value="root" /> <property name="password" value="123456" /> <property name="maxActive" value="100" /> <property name="maxIdle" value="30" /> <property name="maxWait" value="1000" /> <property name="validationQuery" value="select 1" /> </bean> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <constructor-arg name="dataSource" ref="basicDataSource"> </constructor-arg> </bean> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager "> <property name="dataSource"> <ref bean="basicDataSource" /> </property> </bean> <bean id="studentDao" class="com.mysrc.dao.StudentDao"> <property name="jdbcTemplate"> <ref bean="jdbcTemplate" /> </property> </bean> <bean id="studentService" class="com.mysrc.service.StudentService"> <property name="dao"> <ref bean="studentDao" /> </property> </bean> <tx:annotation-driven transaction-manager="transactionManager" /> <!--这句话的作用是注册事务注解处理器 --> </beans>
测试类MyTester.java代码如下:
package com.mysrc.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.mysrc.service.StudentService;
public class MyTester {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext(
"applicationContext.xml");
StudentService studentService = (StudentService) context
.getBean("studentService");
studentService.doComplexLogic();
}
}
@Transactional 的所有可选属性如下
属性 | 类型 | 默认值 | 说明 |
propagation | Propagation枚举 | REQUIRED | 事务传播属性 |
isolation | isolation枚举 | DEFAULT | 事务隔离级别 |
readOnly | boolean | false | 是否只读 |
timeout | int | -1 | 超时(秒) |
rollbackFor | Class[] | {} | 需要回滚的异常类 |
rollbackForClassName | String[] | {} | 需要回滚的异常类名 |
noRollbackFor | Class[] | {} | 不需要回滚的异常类 |
noRollbackForClassName | String[] | {} | 不需要回滚的异常类名 |
整个eclipse工程代码文件在附件中。。