注意有一点 : service层在调用的时候也就是事物管理的那个方法里不能用try{}catch(){} , 如果用了 ,异常被捕获了 , 事物管理就发现不了异常 ,也就不会进行回滚
还有个spring的动态代理提一下
spring的动态的代理模式有两种
JDK动态代理,基于接口(默认代理模式),CGLIB动态代理(若要使用需要进行配置)
1.使用aop配置:
<aop:config proxy-target-class=“false”> </aop:config>
-
aspectj配置:
<aop:aspectj-autoproxy proxy-target-class=“true”/> -
事务annotation配置:
<tx:annotation-driven transaction-manager=“transactionManager” proxy-target-class=“true”/>
3种配置,只要使用一种即可,设置proxy-target-class为true即使用cglib的方式代理对象。
DK动态代理和CGLIB动态代理的区别?
(1)JDK动态代理只能对实现了接口的类生成代理,而不能针对类
(2)CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法
因为是继承,所以该类或方法最好不要声明成final
简单来说就是 ,spring默认jdk动态代理 , 然后getBean的时候只能取接口 ,和返回接口类型
而cglib动态代理时 ,getBean里可以是实现类 ,也可以是接口 .
数据库的事物呢 , 就是指作为单个逻辑工作单元执行的一系列操作,要么完全地执行,要么完全地不执行。
事务处理可以确保除非事务性单元内的所有操作都成功完成,否则不会永久更新面向数据的资源。
实现事物管理的方式也有xml的配置方式和注解的方式
xml的方式步骤:
写个对应数据库表的javaBean
public class User {
private int id;
private String name;
private int age;
写出数据操作的dao层
public class UserDao {
private JdbcTemplate template;
public void setTemplate(JdbcTemplate template) {
this.template = template;
}
public void add(){
String sql = "insert into user(name,password,age)values(?,?,?)";
int count = template.update(sql , "1112","afjaof",20);
System.out.println("影响的行数:"+count);
}
public void update(){
String sql = "update user set age1=? where id=?";
int count = template.update(sql,33,17);
System.out.println("影响的行数:"+count);
}
public void delete(){
String sql = "delete from user where id = ?";
template.update(sql, 34);
}
public void query1(){
String sql = "select * from user";
List<User> list = template.query(sql, new RowMapper<User>(){
@Override
public User mapRow(ResultSet rs, int rowNum) throws SQLException {
System.out.println(rowNum);
User user = new User();
user.setId(rs.getInt("id"));
user.setName(rs.getString("name"));
user.setAge(rs.getInt("age"));
return user;
}
});
for (User user : list) {
System.out.println(user);
}
}
public void query2(){
String sql = "select * from t_user";
List<User> list = template.query(sql, new BeanPropertyRowMapper(User.class));
for (User user : list) {
System.out.println(user);
}
}
}
然后是service层
@Component
public class UserServiceImpl implements UserService {
@Resource
private UserDao dao;
@Override
public void fun1() {
dao.add();
dao.update();
}
}
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"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
<context:component-scan base-package="com.sxt.*,com.liy.*"></context:component-scan>
<bean class="org.springframework.jdbc.core.JdbcTemplate" id="jdbcTemplate">
<!-- 构造注入关联数据源 -->
<constructor-arg name="dataSource" ref="dataSource"/>
</bean>
<!-- 配置数据源 -->
<bean class="org.springframework.jdbc.datasource.DriverManagerDataSource" id="dataSource">
<!-- 配置数据库的相关信息 -->
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/again?characterEncoding=utf-8"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>
<!-- 配置UserDao -->
<bean class="com.sxt.dao.UserDao">
<property name="template" ref="jdbcTemplate" />
</bean>
<!-- 开启事物管理 -->
<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 开启注解 -->
<!-- <tx:annotation-driven transaction-manager="transactionManager"/> -->
<!-- 配置事物的行为 -->
<tx:advice id="myAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="fun*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!-- 配置aop -->
<aop:config>
<!-- 配置切入点 -->
<aop:pointcut expression="execution(* com.liy.service.impl.*.*(..))" id="myP"/>
<aop:advisor advice-ref="myAdvice" pointcut-ref="myP"/>
</aop:config>
</beans>
测试
public static void main(String[] args) {
ApplicationContext ac =
new ClassPathXmlApplicationContext("applicationContext.xml");
UserService bean = ac.getBean(UserService.class);
bean.fun1();
}
注解的方式就相对简单些
dao层
@Repository
public class UserDao {
@Resource
private JdbcTemplate template;
service层
@Component
public class UserServiceImpl implements UserService {
@Resource
private UserDao dao;
@Transactional
@Override
public void fun1() {
dao.add();
dao.update();
}
配置文件
<!-- 开启spring的注解扫描 -->
<context:component-scan base-package="com.sxt.*,com.liy.*"></context:component-scan>
<bean class="org.springframework.jdbc.core.JdbcTemplate" id="jdbcTemplate">
<!-- 构造注入关联数据源 -->
<constructor-arg name="dataSource" ref="dataSource"/>
</bean>
<!-- 配置数据源 -->
<bean class="org.springframework.jdbc.datasource.DriverManagerDataSource" id="dataSource">
<!-- 配置数据库的相关信息 -->
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/again?characterEncoding=utf-8"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>
<!-- 开启事物管理 -->
<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 开启事物管理的注解 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
测试类与另外一种方式一样
public static void main(String[] args) {
ApplicationContext ac =
new ClassPathXmlApplicationContext("applicationContext.xml");
UserService bean = ac.getBean(UserService.class);
bean.fun1();
}
这样就没有异常就都会执行 , 有异常就会回滚 , 就都不会执行成功