文章目录
Spring JDBC
- Spring JDBC是Spring框架用于处理关系型数据库的模块
- Spring JDBC对JDBC API进行封装, 极大简化开发工作量
- JdbcTemplate是Spring JDBC核心类, 提供数据CRUD方法
有MyBatis为什么还需要Spring JDBC?
Mybatis对数据库操作有着严格和全面的封装, 但不够轻量, 性能上会差一下.
Spring JDBC只是对JDBC进行轻量的封装, 性能较好.
第一个Spring JDBC程序
引入依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.6.RELEASE</version>
</dependency>
<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.16</version>
</dependency>
配置数据源
<bean id="dataSource" class="org.springframework,jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/imooc?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true"/>
<property name="username" value="root" />
<property name="password" value="root" />
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource" />
</bean>
注入JdbcTemplate到DAO对象里
<bean id="employee" class="com.imooc.spring.jdbc.dao.employeeDao" >
<!-- 为Dao注入JdbcTemplate对象 -->
<property name="jdbcTemplate" ref="jdbcTemplate" />
</bean>
使用
publc class SpringApplication{
public static void main(String[] args){
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
context.getBean("employeeDao", EmployeeDao.class);
Employee employee = employeeDao.findById(3308);
System.out.println(employee);
}
}
其他增删改查操作
查询多条数据
//查询多条数据
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>(Employee.class));
}
//查询多条数据, 结果用Map包裹
public List findMapByDname(String dname){
String sql="select * from employee where dname=?";
List<Map<String, Object>> maps = jdbcTemplate.queryForList(sql, new Object[]{dname})
return maps;
}
插入数据
public void insert(Employee employee){
String sql="insert into employee(eno,ename,salary,dname,hiredate) values (?,?,?,?,?)"
jdbcTemplate.update(sql,new Object[]{employee.getEno()employee.getEname(),employee.getSalary(),Employee.getDname(),employee.getHiredate()});
}
更新数据
public void update(Employee employee){
String sql="update employee set ename=? , salary=? , hiredate=? where eno=?";
int count= jdbcTemplate.update(sql, new Object[]{employee.getEno()employee.getEname(),employee.getSalary(),employee.getHiredate(),employee.getEno()});
}
删除数据
public int delete(Integer eno){
String sql="delete from employee where eno=?";
int count=jdbcTemplate.update(sql,new Object[]{eno});
return count;
}
事务管理
编程式事务
- 编程式事务是指通过代码手动提交回滚事务的事务控制方法
- SpringJDBC通过TransactionManager事务管理器实现事务控制
- 事务管理器提供commit/rollback方法进行事务提交与回滚
配置事务管理器
<!-- 事务管理器 -->
<bean id="transactionManager" class="com.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
将事务管理器注入到需要使用事务的bean对象中
<bean id="employeeService" class="com.spring.jdbc.service.EmployeeService">
<property name="employeeDao" ref="employeeDao" />
<property name="transactionManager" ref="transactionManager" />
</bean>
使用事务批量插入
public void batchImport(){
//定义了事务默认的标准配置
TransactionDefinition definition = new DefaultTransactionDefinition();
//开始一个事务, 返回事务状态, 事务状态说明当前事务的执行阶段
TransactionStatus status= transactionManager.getTransactions(definition);
try{
for(...){
...
}
//提交事务
transactionManager.commit(status);
}catch(Exception e){
transactionManager.rollback(status);
e.printStackTrace();
}
}
声明式事务
- 声明式事务指在不修改源码情况下通过配置形式自动实现事务控制, 声明式事务本质就是AOP环绕通知
- 当目标方法执行成功时, 自动提交事务
- 当目标方法抛出运行时异常时, 自动事务回滚
配置过程
- 配置TransactionManager事务管理器
- 配置事务通知与事务属性
- 为事务通知绑定PointCut切点
EmployeeService.java
public class EmployeeService{
private EmployeeDao employeeDao;
public void batchImport(){
for(int i=1;i<=10;i++){
Employee employee =new Employee();
employee.setEno(8000+i);
employee.setEname("员工"+i);
employee.setSalary(4000f);
employee.setDname("市场部");
employee.setHiredate(new Date());
employeeDao.insert(employee);
}
}
}
在xml文件中增加事务的命名空间
xmlns:tx=“http://www.spring.framework.org/schema/beans”
http://www.spring.framework.org/schema/tx
https://www.springframework.org/schema/tx/spring-tx.xsd
在xml文件中增加AOP的命名空间
xmlns:aop=“http://www.springframework.org/schema/aop”
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd
在xml文件中配置
<bean id="dataSource" class="org.springframework,jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/imooc?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true"/>
<property name="username" value="root" />
<property name="password" value="root" />
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="employeeDao" class="com.imooc.spring.jdbc.dao.EmployeeDao">
<property name="jdbcTemplate" ref="jdbcTemplate" />
</bean>
<bean id="employeeService" class="com.imooc.spring.jdbc.Service.EmployeeService" >
<property name="employeeDao" ref="" />
</bean>
<!-- 事务管理器, 用于创建事务/提交/回滚 -->
<bean id="transactionManager" class="org.spring.framework.jdbc.dataSource.DataSourceTransactionManager" >
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 事务通知配置, 决定哪些方法使用事务, 哪些方法不使用事务 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager" >
<tx:attributes>
<!-- 目标方法名为batchImport时, 启用声明式事务, 成功提交, 运行时异常回滚 -->
<tx:method name="batchImport" propagation="REQUIRED" />
<!--支持通配符匹配-->
<tx:method name="batch*" propagation="REQUIRED" />
<!--设置所有findXXX方法不需要使用事务-->
<tx:method name="find*" propagation="NOT_SUPPORTED" read_only="true" />
<!--设置除上面几种情况外, 都需要使用事务-->
<tx:method name="*" propagation="REQUIREAD" />
</tx:attributes>
</tx:advice>
<!-- 定义声明式事务的作用范围 -->
<aop:config>
<aop:pointcut id="pointcut" expression="execution(* com.imooc..*Service.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut" />
</aop:config>
事务传播行为
- 事务传播行为是指多个拥有事务的方法在嵌套调用时的事务控制方式
事务传播行为的其中类型
事务传播类型 | 说明 |
---|---|
REQUIRED | 如果当前没有事务, 就新建一个事务, 如果已经存在一个事务中, 加入到这个事务中. 这是最常见的选择 |
SUPPORTS | 支持当前事务, 如果当前没有事务, 就以非事务方式执行 |
MANDATORY | 使用当前的事务, 如果当前没有事务, 就抛出异常 |
REQUIRES_NEW | 新建事务, 如果当前存在事务, 把当前事务挂起 |
NOT_SUPPORTED | 以非事务方式执行操作, 如果当前存在事务, 就把当前事务挂起 |
NEVER | 以非事务方式执行, 如果当前存在事务, 则抛出异常 |
NESTED | 如果当前存在事务, 则在嵌套事务内执行. 如果当前没有事务, 则执行与REQUIRED类似的操作 |
注解方式配置声明式事务
xml
<context:component-scan base-package="com.imooc" />
<bean id="dataSource" class="org.springframework,jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/imooc?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true"/>
<property name="username" value="root" />
<property name="password" value="root" />
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate" >
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager" >
<property name="dataSource" ref="dataSource" />
</bean>
<!--启用注解形式声明事务-->
<tx:annotation-driven transaction-manager="transactionManager" />
@Repository
public class EmployeeDao{
@Resource
private JdbcTemplate jdbcTemplate;
}
@Service
// 声明式事务核心注解
// 放在类上, 将声明式事务配置应用于当前类的所有方法, 默认事务传播为REQUIRED
@Transactional
public class EmployeeService{
@Resource
private EmployeeDao employeeDao;
@Resource
private BatchService batchService;
@Transactional(propagation=Propagation.NOT_SUPPORTED,readOnly=true)
public Employee findById(Integer eno){
return employeeDao.findById(eno);
}
}
@Service
public class BatchService{
private EmployeeDao employeeDao;
}