Hi,大家好,我是编程小6,很荣幸遇见你,我把这些年在开发过程中遇到的问题或想法写出来,今天说一说
自定义事务管理器TransactionManager对象,希望能够帮助你!!!。
以aop思想,实现事务管理切面
<?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:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd"> <!--开启包扫描注解--> <context:component-scan base-package="com.hang"/> <!--导入jdbc.properties文件--> <context:property-placeholder location="classpath:jdbc.properties"/> <!--配置druid数据库连接池--> <bean class="com.alibaba.druid.pool.DruidDataSource" id="dataSource"> <property name="url" value="${jdbc.url}"/> <property name="driverClassName" value="${jdbc.driver}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> <property name="initialSize" value="${jdbc.initialSize}"/> </bean> <!--开启aop注解--> <aop:aspectj-autoproxy/> </beans>
定义事务管理器MyTransactionManager对象,注册进spring容器。(依赖Druid连接池,获取连接,开始事务,提交事务,回滚事务,关闭连接)
@Component public class MyTransactionManager {
@Autowired private DataSource dataSource; // 获取连接 public Connection getConnection(){
Connection conn = null; try {
conn = dataSource.getConnection(); ConnUtil.setConn(conn); } catch (SQLException e) {
e.printStackTrace(); } return conn; } // 开始事务 public void openTransaction(){
try {
ConnUtil.getConn().setAutoCommit(false); } catch (SQLException e) {
e.printStackTrace(); } } // 提交事务 public void openCommit(){
try {
ConnUtil.getConn().commit(); } catch (SQLException e) {
e.printStackTrace(); } } // 回滚事务 public void openRollback(){
try {
ConnUtil.getConn().rollback(); } catch (SQLException e) {
e.printStackTrace(); } } // 关闭连接 public void closeConnection(){
Connection conn = ConnUtil.getConn(); try {
if (conn!=null){
conn.close(); } } catch (SQLException e) {
e.printStackTrace(); } } public DataSource getDataSource() {
return dataSource; } public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource; } }
定义dao接口,使用jdbc定义dao实现,不要使用mybatis,把dao实现注册spring容器(curd)
public interface SysUserDao {
SysUser queryById(Integer id) throws Exception; Integer insert(SysUser sysUser) throws Exception; int update(SysUser sysUser); int deleteById(Long id); }
@Repository public class SysUserDaoImpl implements SysUserDao {
private Connection conn = null; private ResultSet rs = null; private PreparedStatement ps = null; @Override public SysUser queryById(Integer id) throws Exception {
SysUser sysUser = null; conn = ConnUtil.getConn(); ps = conn.prepareStatement("select * from db_stage_three.sys_user where id = ?"); ps.setInt(1, id); rs = ps.executeQuery(); if (rs.next()) {
sysUser = new SysUser(); sysUser.setUname("hello"); } return sysUser; } @Override public Integer insert(SysUser sysUser) throws Exception {
Integer result = null; conn = ConnUtil.getConn(); ps = conn.prepareStatement("insert into db_stage_three.sys_user ( uname, uphone, upwd, uwechat, uemail, role_id, dept_id) values (?,?,?,?,?,?,?)"); ps.setString(1, sysUser.getUname()); ps.setString(2, sysUser.getUphone()); ps.setString(3, sysUser.getUpwd()); ps.setString(4, sysUser.getUwechat()); ps.setString(5, sysUser.getUemail()); ps.setInt(6, sysUser.getRoleId()); ps.setInt(7, sysUser.getDeptId()); result = ps.executeUpdate(); return result; } @Override public int update(SysUser sysUser) {
return 0; } @Override public int deleteById(Long id) {
return 0; } }
定义service接口,定义service实现,注册容器(curd)。
public interface SysUserService {
SysUser queryById(Integer id); SysUser insert(SysUser sysUser); }
@Service() public class SysUserServiceImpl implements SysUserService {
@Resource private SysUserDao sysUserDao; @Override public SysUser queryById(Integer id) {
Connection conn = null; // 织入获取连接,开始事务,提交事务,回滚事务,关闭连接 SysUser sysUser = null; try {
sysUser = this.sysUserDao.queryById(id); } catch (Exception e) {
e.printStackTrace(); } return sysUser; } @Transaction // 使用基于自定义注解方式定义切入点表达式 @Override public SysUser insert(SysUser sysUser) {
try {
this.sysUserDao.insert(sysUser); } catch (Exception e) {
e.printStackTrace(); } int i = 1/0; return sysUser; } }
自定义注解代码如下:
@Target({
ElementType.TYPE,ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface Transaction {
}
定义事务切面(依赖MyTransactionManag),定义环绕通知,织入到service层的数据库操作方法,执行方法之前打开事务,异常回滚,方法返回提交事务,最终关闭连接。定义 ServiceTransAspect 类作为切面
@Component @Aspect public class ServiceTransAspect {
@Autowired private MyTransactionManager transactionManager; // 基于 AspectJ 的切入点表达式 @Pointcut("execution(* com.hang.service.impl.SysUserServiceImpl.*(..))") public void servicePointCut() {
} // 后置通知关闭数据库连接对象 @After("servicePointCut()") public void closeConnection(){
Connection conn = ConnUtil.getConn(); if (conn!=null){
try {
conn.close(); ConnUtil.clear(); conn = null; } catch (SQLException e) {
e.printStackTrace(); } } } // 基于自定义注解形式 @Pointcut("@annotation(com.hang.aspect.Transaction)") public void annotationPointCut() {
} // 环绕通知 实现事务的开启、回滚、提交和连接对象的关闭 @Around(value = "annotationPointCut()") public Object serviceManage(ProceedingJoinPoint pjp) {
Object result = null; try {
transactionManager.getConnection(); transactionManager.openTransaction(); result = pjp.proceed(); transactionManager.openCommit(); } catch (Throwable throwable) {
transactionManager.openRollback(); throwable.printStackTrace(); } finally {
transactionManager.closeConnection(); } return result; } }
在并发环境下,如果没使用ThreadLocal类维护线程内部的局部变量Connection(单Connection对象),两个线程共同访问一个公共变量。例如A用户获取数据库连接对象,并将Connection对象占为己有,对数据进行操作时,B用户也获取到数据库连接对象,获取Connection对象,此时A不具有Connection对象,B用户完成事务提交关闭连接,此时Connection对象为null,A用户数据则会提交失败。
ThreadLocal类用来提供线程内部的局部变量。这种变量在多线程环境下访问(通过get和set方法访问)时能保证各个线程的变量相对独立于其他线程内的变量。
对ThreadLocal作用的总结:
@Component public class ConnUtil {
private static ThreadLocal<Connection> threadLocalConn = new ThreadLocal<>(); @Resource private MyTransactionManager tm; private static MyTransactionManager manager; public static void clear() {
threadLocalConn.remove(); } @PostConstruct public void setTransactionManager(){
manager = tm; } public static Connection getConn() {
Connection connection = threadLocalConn.get(); if (connection!=null){
return connection; }else {
return manager.getConnection(); } } public static void setConn(Connection conn) {
threadLocalConn.set(conn); } }
今天的分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。
上一篇
已是最后文章
下一篇
已是最新文章