内容简介:Spring c3p0的测试 和 事物管理 xml配置
一,使用c3p0配置连接池的xml配置
c3p0.jar 和mchange-commons-java.jar
a.CombopooledDataSource 连接池底层的原理实现 :java
{
ComboPooledDataSource datesource=
new ComboPooledDataSource();
//其实不需要配置文件也行,只是需要写死就ok
datesource.setDriverClass("com.mysql.jdbc.Driver");
datesource.setJdbcUrl("jdbc:mysql:///message");
datesource.setUser("root");
datesource.setPassword("");
JdbcTemplate jdbcTemplate = new JdbcTemplate(datesource);
String sql = "select count(*) from message";
int i = jdbcTemplate.queryForInt(sql);
System.out.println(i);
}
b.spring中配置c3p0的连接池
<!-- 1.配置c3p0 的连接池 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <!-- 注入属性值 --> <property name="driverClass" value="com.mysql.jdbc.Driver"></property> <property name="jdbcUrl" value="jdbc:mysql:///message"></property> <property name="user" value="root"></property> <property name="password" value=""></property> </bean> <!-- 2.创建jdbcTemplate模板 --> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"></property> </bean> <!-- 3.给userDao中注入jdbcTemplate模板 --> <bean id="userDao" class="com.gog.c3p0.UserDao"> <property name="jdbcTemplate" ref="jdbcTemplate"></property> </bean> <!-- 4. --> <bean id="userService" class="com.gog.c3p0.UserService"> <property name="userDao" ref="userDao"></property> </bean>
c.userDao中实现对数据库的操作
public class UserDao {
private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
public void add(){
System.out.println("--> UserDao");
String sql = " insert into message values(?,?,?,?)";
int rows = jdbcTemplate.update(sql, 72, "GGr", "3", "4");
System.out.println("rows"+rows);
}
}
二,Spring 的事物 的xml配置
tip:
事物是操作数据的一组操作的基本单元,要不然都成功,要不都失败
不考虑隔离性产生读问题 -->多个事物之间不产生影响
(1)编程试事物管理
不常用
(2)声明式事物管理
PlatformTransactionManager 事物管理接口
TransactionDefinition事物定义信息(隔离,传播,超时,只读)
TransactionStatus事物具体运行状态
1)基于xml配置文件实现
2)注解实现
<!-- 开启注解扫描 --> <context:component-scan base-package="com.gog"></context:component-scan> <!-- 开启aop注解操作(自动代理) --> <aop:aspectj-autoproxy></aop:aspectj-autoproxy> <!-- 1.配置c3p0 的连接池 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <!-- 注入属性值 --> <property name="driverClass" value="com.mysql.jdbc.Driver"></property> <property name="jdbcUrl" value="jdbc:mysql:///message?useUnicode=true&characterEncoding=utf8"></property> <property name="user" value="root"></property> <property name="password" value=""></property> </bean> <!-- 2.创建jdbcTemplate模板 --> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"></property> </bean> <!-- 1.xml配置事物管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name = "dataSource" ref="dataSource"></property> </bean> <!-- 2.xml配置事物的增强 --> <tx:advice id="txadvice" transaction-manager="transactionManager"> <!-- 做事物操作 --> <tx:attributes> <!-- 设置进行事物操作的方法匹配规则 --> <tx:method name="account*"></tx:method> <tx:method name="insert*"></tx:method> </tx:attributes> </tx:advice> <!-- 3.xml配置切面 --> <aop:config > <!-- 切入点 --> <aop:pointcut expression="execution(* com.gog.tx.service.OrderService.*(..))" id="pointcut1"></aop:pointcut> <!-- 切面 --> <aop:advisor advice-ref="txadvice" pointcut-ref="pointcut1" ></aop:advisor> </aop:config> <bean id="orderUser" class="com.gog.tx.dao.OrderUser"> <property name="jdbcTemplate" ref="jdbcTemplate"></property> </bean> <bean id="orderService" class="com.gog.tx.service.OrderService"> <property name="orderUser" ref="orderUser"></property> </bean>
三: 事务的嵌套
通过上面的理论知识的铺垫,我们大致知道了数据库事务和spring事务的一些属性和特点,接下来我们通过分析一些嵌套事务的场景,来深入理解spring事务传播的机制。
假设外层事务 Service A 的 Method A() 调用 内层Service B 的 Method B()
PROPAGATION_REQUIRED(spring 默认)
如果ServiceB.methodB() 的事务级别定义为 PROPAGATION_REQUIRED,那么执行 ServiceA.methodA() 的时候spring已经起了事务,这时调用 ServiceB.methodB(),ServiceB.methodB() 看到自己已经运行在 ServiceA.methodA() 的事务内部,就不再起新的事务。
假如 ServiceB.methodB() 运行的时候发现自己没有在事务中,他就会为自己分配一个事务。
这样,在 ServiceA.methodA() 或者在 ServiceB.methodB() 内的任何地方出现异常,事务都会被回滚。
PROPAGATION_REQUIRES_NEW
比如我们设计 ServiceA.methodA() 的事务级别为 PROPAGATION_REQUIRED,ServiceB.methodB() 的事务级别为 PROPAGATION_REQUIRES_NEW。
那么当执行到 ServiceB.methodB() 的时候,ServiceA.methodA() 所在的事务就会挂起,ServiceB.methodB() 会起一个新的事务,等待 ServiceB.methodB() 的事务完成以后,它才继续执行。
他与 PROPAGATION_REQUIRED 的事务区别在于事务的回滚程度了。因为 ServiceB.methodB() 是新起一个事务,那么就是存在两个不同的事务。如果 ServiceB.methodB() 已经提交,那么 ServiceA.methodA() 失败回滚,ServiceB.methodB() 是不会回滚的。如果 ServiceB.methodB() 失败回滚,如果他抛出的异常被 ServiceA.methodA() 捕获,ServiceA.methodA() 事务仍然可能提交(主要看B抛出的异常是不是A会回滚的异常)。
PROPAGATION_SUPPORTS
假设ServiceB.methodB() 的事务级别为 PROPAGATION_SUPPORTS,那么当执行到ServiceB.methodB()时,如果发现ServiceA.methodA()已经开启了一个事务,则加入当前的事务,如果发现ServiceA.methodA()没有开启事务,则自己也不开启事务。这种时候,内部方法的事务性完全依赖于最外层的事务。
PROPAGATION_NESTED
现在的情况就变得比较复杂了, ServiceB.methodB() 的事务属性被配置为 PROPAGATION_NESTED, 此时两者之间又将如何协作呢? ServiceB#methodB 如果 rollback, 那么内部事务(即 ServiceB#methodB) 将回滚到它执行前的 SavePoint 而外部事务(即 ServiceA#methodA) 可以有以下两种处理方式:
a、捕获异常,执行异常分支逻辑
void methodA() {
try {
ServiceB.methodB();
} catch (SomeException) {
// 执行其他业务, 如 ServiceC.methodC();
}
}
这种方式也是嵌套事务最有价值的地方, 它起到了分支执行的效果, 如果 ServiceB.methodB 失败, 那么执行 ServiceC.methodC(), 而 ServiceB.methodB 已经回滚到它执行之前的 SavePoint, 所以不会产生脏数据(相当于此方法从未执行过), 这种特性可以用在某些特殊的业务中, 而 PROPAGATION_REQUIRED 和 PROPAGATION_REQUIRES_NEW 都没有办法做到这一点。
b、 外部事务回滚/提交 代码不做任何修改, 那么如果内部事务(ServiceB#methodB) rollback, 那么首先 ServiceB.methodB 回滚到它执行之前的 SavePoint(在任何情况下都会如此), 外部事务(即 ServiceA#methodA) 将根据具体的配置决定自己是 commit 还是 rollback
//少钱的方法
public void lessMoney(){
String sql =" update account set salary=salary-? where id=?";
int update = jdbcTemplate.update(sql,100,1);
System.out.println(update);
String sql2 = "SELECT * FROM account where ID = ?";
Account account = jdbcTemplate.queryForObject(sql2, new MyAccount(),1);
System.out.println(account);
}
//多钱方法
public void moreMoney(){
String sql =" update account set salary=salary+? where id=?";
int update = jdbcTemplate.update(sql,100,2);
System.out.println(update);
String sql2 = "SELECT * FROM account where ID = ?";
Account account = jdbcTemplate.queryForObject(sql2, new MyAccount(),2);
System.out.println(account);
}
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 数据库事物的四大特性(ACID)及事物隔离级别
- SpringBoot事物管理
- 事物分析和问题解决(200421)
- MySql 事物及隔离级别
- Redis 事物源码阅读:watch
- 你了解Spring事物控制特性吗
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
产品经理的20堂必修课
徐建极 / 人民邮电出版社 / 2013-9-1 / 59.00元
《产品经理的20堂必修课》以作者八年的产品经理工作实践为基础,通过系统的理论结合丰富的实例的方法,全面地总结了作为一名互联网产品经理所应掌握的知识。 《产品经理的20堂必修课》分为三大部分。 讲产品:深入剖析互联网产品成功的要素,分别从需求导向、简单原则、产品运营、战略布局等维度,分析如何让产品在残酷的互联网竞争中脱颖而出。 讲方法:着重分析优秀的产品团队运作的工作方法和程序,详......一起来看看 《产品经理的20堂必修课》 这本书的介绍吧!