TeaFramework - implementation of transactions

    The essence of a transaction: let the program execute as we see it.

    A database transaction is a set of database operations defined as the same transaction, either succeeding or failing at the same time, and an intermediate state of partial success is impossible.

    For JDBC native transactions, first set the auto-commit to false: connection.setAutoCommit(false), if there is no exception in the entire execution process, submit the transaction commit, otherwise rollback rollback. For the original jdbc transaction, the coding is very cumbersome, and for the common business of the whole system, it is especially suitable to use the AOP method.

    Let's talk about the key points below, TeaFramework transaction implementation.

    1. The use of transactions should be as simple as possible. You can add an annotation to the method or class. If there is a transaction annotation for a class, then all methods of the class have transaction control.

@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface Transcation {
}

    2. The dissemination of affairs

    Transaction propagation describes the problem of nesting multiple transactions. For most scenarios, if the top-level method has a transaction, the sub-transaction is included in the current transaction. This scenario accounts for 80%, so TeaFramework only implements this transaction propagation.

    Please see the specific code

public class TranscationProxy extends AbstractProxy {
	private Logger logger = LoggerFactory.getLogger(getClass());

	@Override
	public void invoke(Proxy proxy) throws Throwable {
		BeanProxy beanProxy = (BeanProxy) proxy;
		boolean classHasTranscationAnnotation = beanProxy.getObj().getClass().getSuperclass()
				.isAnnotationPresent(Transcation.class);
		boolean methodHasTranscationAnnotation = beanProxy.getMethod().isAnnotationPresent(Transcation.class);
		if (TranscationThreadVariable.get() == null
				&& (classHasTranscationAnnotation || methodHasTranscationAnnotation)) {// 如果类或者方法有Transcation注解则进入
			try {
				before(proxy);
				proxy.invoke(proxy);
				after(proxy);
			} catch (Throwable e) {
				exception(proxy);
				throw e;
			} finally {
				end(beanProxy);
			}
		} else {
			proxy.invoke(proxy);
		}

	}

	@Override
	public void before(Proxy proxy) {
		try {
			TranscationThreadVariable.set(true);
			logger.debug("开启事务");
			if (ConnectionThreadVariable.getConnetion() == null) {
				Connection connection = DataSourceHelp.getConnection();
				connection.setAutoCommit(false);
				ConnectionThreadVariable.setConnetion(connection);
			}
		} catch (Exception e) {
			throw new TranscationException(e);
		}
	}

	@Override
	public void after(Proxy proxy) {
		try {
			logger.debug("提交事务");
			ConnectionThreadVariable.getConnetion().commit();
		} catch (Exception e) {
			throw new TranscationException(e);
		}
	}

	@Override
	public void exception(Proxy proxy) {
		try {
			logger.debug("回滚事务");
			ConnectionThreadVariable.getConnetion().rollback();
		} catch (Exception e) {
			throw new TranscationException(e);
		}
	}

	@Override
	public void end(Proxy proxy) {
		try {
			logger.debug("关闭连接");
			ConnectionThreadVariable.getConnetion().close();
		} catch (Exception e) {
			throw new TranscationException(e);
		} finally {
			ConnectionThreadVariable.clearThreadVariable();
			TranscationThreadVariable.clearThreadVariable();
		}
	}

}

    This is essentially the realization of a proxy class, which is implemented with the idea of ​​AOP.

    1. Before: Before the transaction is opened, get the database connection and set auto-commit to false

    2. After: If there is no exception in the execution process, submit the transaction

    3. exception: If an exception occurs during the execution process, the transaction is rolled back

    4. end: end of execution, close the database connection, and return it to the connection pool

    So where is the propagation of the transaction implemented? There is only one line of code TranscationThreadVariable.set(true), this line of code indicates the status of the transaction in the current thread. If the transaction has been opened by the upper-level method, all the following database operations and the method of opening the transaction share a database connection connection, then is included in a transaction.

    Let's look at an example, add the @Transcation annotation to the insert method

@TeaDao("testDao")
public interface TestDao {

	@Transcation
	@GetPrimaryKey(sql = "select s_users.nextval from dual", primaryKeyProperty = "id")
	@SQL("insert into users(id,name,password,createdate) values(#id#,#name#,#password#,#createdate#)")
	public int add(Map<String, Object> map);

	@DynamicSQL
	public int update();

	@SQL("delete from users")
	public int deleteUserById();

	@SQL("select * from users")
	public List<User> getAllUser();

	@DynamicSQL
	public List<User> findUser();

}

    Results of the:

    This is how the TeaFramework transaction is implemented.

     Project address: https://git.oschina.net/lxkm/teaframework
     Blog: https://my.oschina.net/u/1778239/blog 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325437749&siteId=291194637