没有配置事务的传播特性之前默认使用jdbc事务
spring.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:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
">
<!-- 扫描 -->
<context:component-scan base-package="lesson04.jdbc"></context:component-scan>
<context:property-placeholder location="classpath:/lesson04/jdbc/jdbcoracle.properties"/>
<!-- ${username}是个关键字 默认获取操作系统用户 -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="url" value="${url}"></property>
<property name="username" value="${username1}"></property>
<property name="password" value="${password}"></property>
<property name="driverClassName" value="${driverClass}"></property>
</bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 定义通知 通知的代码 spring已经实现 -->
<!-- 上面的id名为 id="transactionManager" 下面的 transaction-manager="transactionManager"可以不写-->
<tx:advice id="myAdvise" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="Update*"/>
<tx:method name="save*"/>
<tx:method name="delete*"/>
<tx:method name="*" read-only="true"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut expression="execution(* lesson04.jdbc.dao.*.*(..))" id="myPoint"/>
<aop:advisor advice-ref="myAdvise" pointcut-ref="myPoint"/>
</aop:config>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSouce"></property>
</bean>
</beans>
dao层的实现类
package lesson04.jdbc.dao.imp;
import java.sql.SQLException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
import lesson04.jdbc.dao.MyMoneyDao;
@Repository
public class MyMoneyDaoImpl implements MyMoneyDao {
@Autowired
JdbcTemplate jdbc;
/* (non-Javadoc)
* @see lesson04.jdbc.dao.imp.MyMoneyDao#aminus(int)
* 减钱
*/
public void UpdateAminus(int money) throws SQLException{
String sql="update mymoney set lostedmoney=lostedmoney-"+money+" where userName='A'";
jdbc.execute(sql);
}
/* (non-Javadoc)
* @see lesson04.jdbc.dao.imp.MyMoneyDao#badd(int)
* 加钱
*/
public void UpdateBadd(int money) throws SQLException{
String sql="update mymoney set lostedmoney=lostedmoney+"+money+" where userName='B'";
jdbc.execute(sql);
}
}
测试
package lesson04.jdbc;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import javax.sql.DataSource;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
import lesson04.jdbc.dao.MyMoneyDao;
public class TestTa {
static MyMoneyDao d;
static Connection conn;
static{
ApplicationContext context=new ClassPathXmlApplicationContext("lesson04/jdbc/spring.xml");
d=(MyMoneyDao)context.getBean("myMoneyDaoImpl");
}
public static void main(String[] args) throws SQLException {
d.UpdateAminus(10); //执行完提交事务(减钱成功)
int i=5/0; //出现异常整个方法结束
d.UpdateBadd(10); //此方法不会执行(加钱失败) 这样就会导致 减钱成功加钱不成功 钱无缘无故消失了
}
}
解决以上问题可以设置手动提交事务
spring.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:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
">
<context:component-scan base-package="lesson04.jdbc"></context:component-scan>
<context:property-placeholder location="classpath:/lesson04/jdbc/jdbcoracle.properties"/>
<!-- ${username}是个关键字 默认获取操作系统用户 -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="url" value="${url}"></property>
<property name="username" value="${username1}"></property>
<property name="password" value="${password}"></property>
<property name="driverClassName" value="${driverClass}"></property>
</bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 定义通知 通知的代码 spring已经实现 -->
<!-- 上面的id名为 id="transactionManager" 下面的 transaction-manager="transactionManager"可以不写-->
<tx:advice id="myAdvise" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="Update*"/>
<tx:method name="save*"/>
<tx:method name="delete*"/>
<tx:method name="*" read-only="true"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut expression="execution(* lesson04.jdbc.dao.*.*(..))" id="myPoint"/>
<aop:advisor advice-ref="myAdvise" pointcut-ref="myPoint"/>
</aop:config>
</beans>
测试
package lesson04.jdbc;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import javax.sql.DataSource;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
public class TestCotiner {
static DataSource d;
static Connection conn;
static{
ApplicationContext context=new ClassPathXmlApplicationContext("lesson04/jdbc/spring.xml");
d=(DataSource)context.getBean("dataSource");
}
public static void main(String[] args) throws SQLException {
conn= d.getConnection(); 这里要使用try{}catch(){ conn.rollback();}
//jdbc是自动提交 设置成手动提交
conn.setAutoCommit(false);
aminus(10);
int i=5/0;
badd(10);
conn.commit();
/*System.out.println(d.getConnection());
JdbcTemplate jt = (JdbcTemplate)context.getBean("jdbcTemplate");
List<Map<String, Object>> list = jt.queryForList("select * from cc");
System.out.println(list);*/
}
public static void aminus(int money) throws SQLException{
String sql="update mymoney set lostedmoney=lostedmoney-"+money+" where userName='A'";
conn.prepareStatement(sql).executeUpdate();
}
public static void badd(int money) throws SQLException{
String sql="update mymoney set lostedmoney=lostedmoney+"+money+" where userName='B'";
conn.prepareStatement(sql).executeUpdate();
}
}
下面我们使用声明式设置事务
配置了传播事务
在spring.xml中配置 有事务的地方必然又AOP
<!-- 事务管理类 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 定义通知 通知的代码 spring已经实现 -->
<!-- 上面的id名为 id="transactionManager" 下面的 transaction-manager="transactionManager"可以不写-->
<tx:advice id="myAdvise" transaction-manager="transactionManager">
<tx:attributes>
<!--
propagation="REQUIRED" 方法和方法之间存在父子关系
REQUIRED 默认 父方法没有事务创建一个事务 有事务使用父方法当前事务
REQUIRES_NEW 不管父方法是否存在事务 都会新建事务
SUPPORTS 父方法存在事务 使用当前事务 没有事务 使用jdbc的事务(自动提交)
NOT_SUPPORTED 不管父方法中是否存在事务 都不会使用父方法中的事务(挂起事务)
MANDATORY 必须在事务环境中运行 父方法没有事务 抛出异常
No existing transaction found for transaction marked with propagation 'mandatory'
NEVER 父方法中不能存在事务 有事务就抛出异常
-->
<!-- 定义什么特点的方法会开启事务 例如:update* update开头的方法会开启一个事务 -->
<tx:method name="update*" propagation="SUPPORTS"/>
<tx:method name="save*" propagation="MANDATORY"/>
<tx:method name="delete*"/>
<tx:method name="*" read-only="true"/>
<!-- *不是代表全部 而是代表除了上面定义以外的方法不开启事务 只读 -->
</tx:attributes>
</tx:advice>
<!-- 定义切点 前置通知后置通知 transactionManager已经定义好
执行lesson04.testm.dao包下的所有类、所有方法前都会开启一个事务 结束时提交事务
出现异常时 根据事务的传播性致决定
-->
<aop:config>
<!-- 任意返回值 lesson04.testm.dao包下的所有类、所有方法拦截 -->
<aop:pointcut expression="execution(* lesson04.testm.dao.*.*(..))" id="myPoint"/>
<!-- 把切点和通知绑定 <tx:attributes>该标签定义那些方法会被拦截开启一个事务</tx:attributes> -->
<aop:advisor advice-ref="myAdvise" pointcut-ref="myPoint"/>
</aop:config>