Spring JDBC是Spring框架用来处理关系型数据库的模块,对JDBC的API进行了封装。
Spring JDBC的核心类为JdbcTemplate,提供数据CRUD方法
Spring JDBC使用步骤
- Maven工程引入依赖spring-jdbc
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.6.RELEASE</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.27</version>
</dependency>
- xml中配置DataSource数据源
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/test"></property>
<property name="username" value="root"></property>
<property name="password" value="root"></property>
</bean>
- xml中定义JdbcTemplate Bean,让IoC容器初始化时自动实例化
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
- 在需要增删改查的Dao中,持有JdbcTemplate属性,并设置getter和setter方法,然后在对应的业务处理方法中,调用JdbcTemplate的指定方法。
public class EmployeeDao {
private JdbcTemplate jdbcTemplate;
//数据查询方法
public Employee findById(Integer eno){
String sql="select * from employee where eno = ?";
Employee employee = jdbcTemplate.queryForObject(sql,new Object[]{eno},new BeanPropertyRowMapper<>(Employee.class));
return employee;
}
public JdbcTemplate getJdbcTemplate() {
return jdbcTemplate;
}
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
}
- 在xml中为Dao类注入JdbcTemplate对象
<bean id="employeeDao" class="spring.jdbc.dao.EmployeeDao">
<property name="jdbcTemplate" ref="jdbcTemplate"></property>
</bean>
JdbcTemplate数据查询方法:
例:
public List<Employee> findByDname(String dname){
String sql = "select * from employee where dname = ?";
List<Employee> list = jdbcTemplate.query(sql,new Object[]{dname},new BeanPropertyRowMapper<>(Employee.class));
return list;
}
public List<Map<String, Object>> findMapByDname(String dname){
String sql = "select eno as empno,salary as s from employee where dname = ?";
List<Map<String, Object>> maps = jdbcTemplate.queryForList(sql, new Object[]{dname});
return maps;
}
JdbcTemplate数据写入方法:
例:
public void insert(Employee employee){
String sql = "insert into employee(eno,ename,salary,dname) values(?,?,?,?)";
//利用update方法实现数据写入操作
jdbcTemplate.update(sql,new Object[]{
employee.getEno(),employee.getEname(),employee.getSalary(), employee.getDname()
});
}
public int update(Employee employee){
String sql = "update employee set ename=?,salary=?,dname=? where eno=?";
//利用update方法实现数据更新操作
int count = jdbcTemplate.update(sql,new Object[]{
employee.getEname(),employee.getSalary(), employee.getDname(),employee.getEno()
});
return count;
}
public int delete(Integer eno){
String sql = "delete from employee where eno = ?";
//利用update方法实现数据删除操作
return jdbcTemplate.update(sql,new Object[]{eno});
}
Spring事务管理
事务是一种可靠、一致的方式,是访问操作数据库的程序单元,事务要么把事情做完,要么不做,不会做一半停止。
事务依赖数据库实现,MySQL通过事务区
作为数据缓冲地带。
编程式事务
通过代码手动提交回滚事务的事务控制方式。
SpringJDBC通过TransactionManager事务管理器实现事务控制。
TransactionManager事务管理器提供commit、rollback方法进行事务提交和回滚。
编程式事务使用步骤:
- 配置事务管理器
<!-- 事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
- 在需要开启事务的业务类中,持有事务管理器属性,并设置getter和setter方法
private DataSourceTransactionManager transactionManager;
public DataSourceTransactionManager getTransactionManager() {
return transactionManager;
}
public void setTransactionManager(DataSourceTransactionManager transactionManager) {
this.transactionManager = transactionManager;
}
- 配置事务管理器对象注入
<bean id="employeeService" class="spring.jdbc.service.EmployeeService">
<property name="employeeDao" ref="employeeDao"></property>
<property name="transactionManager" ref="transactionManager"></property>
</bean>
- 定义事务默认的标准配置,开启事务,进行事务管理
声明式事务
在不修改代码的情况下通过配置的形式实现事务控制,本质就是AOP环绕通知。
声明式事务的触发时机:
- 当目标方法执行成功时,自动提交事务
- 当目标方法抛出
运行时异常
时,自动事务回滚
声明式事务配置过程:
- 需要添加AOP依赖
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.5</version>
</dependency>
- 添加tx和aop命名空间
- 配置TransactionManager事务管理器
<!-- 事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
- 配置事务通知与事务属性
<!--事务通知配置,决定哪些方法使用事务,哪些方法不使用事务-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!--propagation事务传播行为-->
<!--当目标方法名为batchImport时,启用声明式事务,运行成功提交事务,运行时异常回滚-->
<!--目标方法允许使用通配符*-->
<tx:method name="batchImport" propagation="REQUIRED"/>
<!--设置所有findXXX方法不启用事务-->
<tx:method name="find*" propagation="NOT_SUPPORTED" read-only="true"/>
<tx:method name="get*" propagation="NOT_SUPPORTED" read-only="true"/>
<!--设置其他方法不启用事务-->
<tx:method name="*" propagation="NOT_SUPPORTED" read-only="true"/>
</tx:attributes>
</tx:advice>
- 为事务通知绑定PointCut切点
<!--定义声明式事务的作用范围-->
<aop:config>
<aop:pointcut id="pointcut" expression="execution(* spring.jdbc..*Service.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut"/>
</aop:config>
事务传播行为propagation
多个拥有事务的方法在嵌套调用时的事务控制方式。
注解配置声明式事务
- xml配置
<context:component-scan base-package="spring.jdbc"/>
<!--数据源-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/test"></property>
<property name="username" value="root"></property>
<property name="password" value="root"></property>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--启用注解形式声明式事务-->
<tx:annotation-driven transaction-manager="transactionManager"/>
- 分层添加组件注解,实例化对象
@Repository
public class EmployeeDao {
@Resource
private JdbcTemplate jdbcTemplate;
...
@Service
public class EmployeeService {
@Resource
private EmployeeDao employeeDao;
...
- 需要开启事务的类添加@Transactional注解,可以设置事务传播行为,如
@Transactional(propagation = Propagation.REQUIRED
或者为方法单独设置事务管理方式,程序执行时优先应用方法上的配置