在POJO中使用ThreadLocal的Java嵌套事务

大多数嵌套事务是使用EJB实现的,现在我们尝试在POJO上实现嵌套事务。 在这里,我们使用了ThreadLocal的功能。

了解嵌套事务

事务可以嵌套在另一个内部。 因此,内部事务或外部事务可以回滚或提交,而不会影响其他事务。

创建新事务后,它将进入外部事务。 一旦内部事务以提交或回滚的方式完成,外部事务就可以执行提交或回滚而与内部事务无关。 首先关闭最里面的事务,然后继续进行最外面的事务。

图片1

使用简单POJO实施

创建界面如下:

importjava.sql.Connection;

publicinterfaceTransactionManager {

	Connection getConnection();
	voidbeginTransaction();
	void commit();
	void rollback();
}

创建事务管理器类,如下所示:

importjava.sql.Connection;
importjava.sql.DriverManager;
importjava.sql.SQLException;
importjava.util.Stack;

publicclassTransactionManagerStackImplimplementsTransactionManager {
	
	private Stack<Connection>connections = new Stack<Connection>();

	@Override
	public Connection getConnection() {

		if (connections.isEmpty()) {
			this.addConn();
		}

		returnconnections.peek();
	}

	@Override
	publicvoidbeginTransaction() {
		this.addConn();
	}

	@Override
	publicvoid commit() {
		try {
			if (connections.peek() != null&& !connections.peek().isClosed()) {
				System.out.println(connections.peek().toString() +"--Commit---");
				connections.peek().commit();
				connections.pop().close();
			}

		} catch (SQLException e) {
			e.printStackTrace();
		}

	}

	@Override
	publicvoid rollback() {
		try {

			if (connections.peek() != null&& !connections.peek().isClosed()) {
				System.out.println(connections.peek().toString() +"--Rollback---");
				connections.peek().rollback();
				connections.pop().close();
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}

	}

	privatevoidaddConn() {
		try {
			Connection con = this.getMysqlConnection();
			con.setAutoCommit(false);
			connections.push(con);
			System.out.println(con.toString() +"--Conection---");
		} catch (SQLException e) {
			e.printStackTrace();
		}
		
	}

	private Connection getMysqlConnection() {
		returngetConnection("com.mysql.jdbc.Driver", "jdbc:mysql://localhost:3306/testdb", "test", "test12345");
	}

	private Connection getConnection(String driver, String connection,
			String user, String password) {

		try {
			Class.forName(driver);
			returnDriverManager.getConnection(connection, user, password);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}

		returnnull;

	}
}

在这里,我们创建了一个堆栈:

private Stack<Connection> connections = new Stack<Connection>();

由于事务创建为LIFO(堆栈),因此我们使用了Java API中的Stack来维护每个事务的连接:

public void beginTransaction()

开始事务以开始新的事务并将连接添加到堆栈。 AutoCommit已设置为false:

public Connection getConnection()

获取当前事务的连接。 如果不存在,它将创建并添加到堆栈中:

public void commit()

提交当前事务并关闭连接,该连接也已从堆栈中删除:

public void rollback()

回滚当前事务并关闭连接,该连接也已从堆栈中删除。

上面的TransactionManagerStackImpl类将为单线程创建嵌套事务。

多线程的嵌套事务

对于多线程应用程序,每个线程都有独立的事务和嵌套事务。

我们提出使用ThreadLocal来管理连接栈。

importjava.sql.Connection;

publicclassTransactionManagerThreadLocalimplementsTransactionManager {
	
	privatestaticfinalThreadLocal<TransactionManager>tranManager = newThreadLocal<TransactionManager>() {
		
	protectedTransactionManagerinitialValue() {
		System.out.println(this.toString() + "--Thread Local Initialize--");
	returnnewTransactionManagerStackImpl();
	    }
	  };

	@Override
	publicvoidbeginTransaction() {
		tranManager.get().beginTransaction();
	}

	@Override
	publicvoid commit() {
		tranManager.get().commit();
	}

	@Override
	publicvoid rollback() {
		tranManager.get().rollback();
	}

	@Override
	public Connection getConnection() {
		returntranManager.get().getConnection();
	}
}

在这里,我们初始化TransactionManagerStackImpl以在线程内部创建嵌套事务。

测试中

为了进行上述测试,请提交内部事务并回滚外部事务。

importjava.sql.Connection;

publicclassNestedMainimplements Runnable {
	
	privateintv = 0;
	private String name;
	
	NestedMain(int v, String name) {
		this.v = v;
		this.name = name;
	}

	publicstaticvoid main(String[] args) throws Exception{
		
		for (inti = 0; i< 3; i++) {
			NestedMain main = newNestedMain(i * 10, "Ravi" + i);
			new Thread(main).start();
		}
	}

	@Override
	publicvoid run() {
		
		try {
			TransactionManagerThreadLocal local = newTransactionManagerThreadLocal();
			
			// Transaction 1 ( outer )
			local.beginTransaction();
			Connection con = local.getConnection();
			String sql = "INSERT INTO test_tran (emp_id, name) VALUES ('1"+v+"', '"+ name+v+"')";
			this.insert(con, sql);
	
				// Transaction 2 ( Inner )
				local.beginTransaction();
				con = local.getConnection();
				sql = "INSERT INTO test_tran (emp_id, name) VALUES ('2"+v+"', '"+ name+v+"')";
				this.insert(con, sql);
				local.commit(); // Committing 2

			local.rollback(); // Rollback 1 Outer

		} catch (Exception e) {
			e.printStackTrace();
		}

结果

com.ttit.TransactionManagerThreadLocal$1@1270b73--Thread Local Initialize--
com.ttit.TransactionManagerThreadLocal$1@1270b73--Thread Local Initialize--
com.ttit.TransactionManagerThreadLocal$1@1270b73--Thread Local Initialize--
com.mysql.jdbc.JDBC4Connection@10dd1f7--Conection---
com.mysql.jdbc.JDBC4Connection@1813fac--Conection---
com.mysql.jdbc.JDBC4Connection@136228--Conection---
com.mysql.jdbc.JDBC4Connection@1855af5--Conection---
com.mysql.jdbc.JDBC4Connection@e39a3e--Conection---
com.mysql.jdbc.JDBC4Connection@1855af5--Commit---
com.mysql.jdbc.JDBC4Connection@e39a3e--Commit---
com.mysql.jdbc.JDBC4Connection@9fbe93--Conection---
com.mysql.jdbc.JDBC4Connection@9fbe93--Commit---
com.mysql.jdbc.JDBC4Connection@10dd1f7--Rollback---
com.mysql.jdbc.JDBC4Connection@1813fac--Rollback---
com.mysql.jdbc.JDBC4Connection@136228--Rollback---
名称 emp_id
拉维220 220
拉维00 20
拉维110 210

回滚内部事务并提交外部事务时:

com.ttit.TransactionManagerThreadLocal$1@1270b73--Thread Local Initialize--
com.ttit.TransactionManagerThreadLocal$1@1270b73--Thread Local Initialize--
com.ttit.TransactionManagerThreadLocal$1@1270b73--Thread Local Initialize--
com.mysql.jdbc.JDBC4Connection@9f2a0b--Conection---
com.mysql.jdbc.JDBC4Connection@136228--Conection---
com.mysql.jdbc.JDBC4Connection@1c672d0--Conection---
com.mysql.jdbc.JDBC4Connection@9fbe93--Conection---
com.mysql.jdbc.JDBC4Connection@1858610--Conection---
com.mysql.jdbc.JDBC4Connection@9fbe93--Rollback---
com.mysql.jdbc.JDBC4Connection@1858610--Rollback---
com.mysql.jdbc.JDBC4Connection@1a5ab41--Conection---
com.mysql.jdbc.JDBC4Connection@1a5ab41--Rollback---
com.mysql.jdbc.JDBC4Connection@9f2a0b--Commit---
com.mysql.jdbc.JDBC4Connection@136228--Commit---
com.mysql.jdbc.JDBC4Connection@1c672d0--Commit---
名称 emp_id
拉维00 10
拉维220 120
拉维110 110

资源:

翻译自: https://www.javacodegeeks.com/2013/12/java-nested-transaction-using-threadlocal-in-pojo.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值