Spring Service study notes

Foreword

Why slag slag will suddenly learn this Spring transaction isolation level and spread it?
Tucao said a colleague yesterday, after an update query to the old data, so this decision to put forward a clear slag slag.

Crime scene

Here Insert Picture Description

Then I tried it save * (check -> update-> check), as well as xx (check -> update-> check);

result

Our database is RC level

The first case: found in old data, update the database after navicat do not see the data update, query data found old

The second situation: found in old data, navicat after the updated database to see the data update, query data found in the old (but also a cache hit)

That is the first case when the update is not committed.

Causes

show you the code

@Getter
@Setter
@Configuration
public class TransactionConfiguration {
	private static final String CUSTOM_PLATFORM_TRANSACTION_MANAGER_NAME = "platformTransactionManager";
	private static final String CUSTOM_TRANSACTION_INTERCEPTOR_NAME = "customTransactionInterceptor";
	private static final String CUSTOM_BEAN_NAME_AUTO_PROXY_CREATOR_NAME = "beanNameAutoProxyCreator";

	/**
	 * 默认的只读事务
	 */
	private static final String[] DEFAULT_READ_ONLY_METHOD_RULE_TRANSACTION_ATTRIBUTES = { "get*", "count*", "find*",
					"query*", "select*", "list*", "*", };
	/**
	 * 默认只对 "*Service" , "*ServiceImpl" Bean 进行事务处理,"*"表示模糊匹配, 比如 :
	 * userService,orderServiceImpl
	 */
	private static final String[] DEFAULT_TRANSACTION_BEAN_NAMES = { "*Service", "*ServiceImpl" };
	/**
	 * 可传播事务配置
	 */
	private static final String[] DEFAULT_REQUIRED_METHOD_RULE_TRANSACTION_ATTRIBUTES = { "add*", "save*", "insert*",
			"delete*", "update*", "edit*", "batch*", "create*", "remove*", };

	/**
	 * 自定义事务 BeanName 拦截
	 */
	private String[] customTransactionBeanNames = {};
	/**
	 * 自定义方法名的事务属性相关联,可以使用通配符(*)字符关联相同的事务属性的设置方法; 只读事务
	 */
	private String[] customReadOnlyMethodRuleTransactionAttributes = {};
	/**
	 * 自定义方法名的事务属性相关联,可以使用通配符(*)字符关联相同的事务属性的设置方法; 传播事务(默认的)
	 * {@link org.springframework.transaction.annotation.Propagation#REQUIRED}
	 */
	private String[] customRequiredMethodRuleTransactionAttributes = {};

	@Autowired
	@Qualifier(value="druidDataSource")
	private DataSource dataSource;

	@Bean(name = CUSTOM_PLATFORM_TRANSACTION_MANAGER_NAME)
	public PlatformTransactionManager platformTransactionManager() {
		return new DataSourceTransactionManager(this.dataSource);
	}

	/**
	 * 配置事务拦截器,注意:transactionInterceptor 名称的 bean 可能已经存在,导致该生成 bean
	 * 的方法不能执行,所以定义成另外一个名字
	 *
	 * @param platformTransactionManager
	 *            事务管理器
	 * @return
	 */
	@Bean(name = CUSTOM_TRANSACTION_INTERCEPTOR_NAME)
	public TransactionInterceptor customTransactionInterceptor(
			@Qualifier(CUSTOM_PLATFORM_TRANSACTION_MANAGER_NAME) PlatformTransactionManager platformTransactionManager) {

		NameMatchTransactionAttributeSource transactionAttributeSource = new NameMatchTransactionAttributeSource();
		RuleBasedTransactionAttribute readOnly = this.readOnlyTransactionRule();
		RuleBasedTransactionAttribute required = this.requiredTransactionRule();
		// 默认的只读事务配置

		for (String methodName : DEFAULT_READ_ONLY_METHOD_RULE_TRANSACTION_ATTRIBUTES) {
			transactionAttributeSource.addTransactionalMethod(methodName, readOnly);
		}

		// 定制的只读事务配置
		for (String methodName : customReadOnlyMethodRuleTransactionAttributes) {
			transactionAttributeSource.addTransactionalMethod(methodName, readOnly);
		}

		// 默认的传播事务配置
		for (String methodName : DEFAULT_REQUIRED_METHOD_RULE_TRANSACTION_ATTRIBUTES) {
			transactionAttributeSource.addTransactionalMethod(methodName, required);
		}

		// 定制的传播事务配置
		for (String methodName : customRequiredMethodRuleTransactionAttributes) {
			transactionAttributeSource.addTransactionalMethod(methodName, required);
		}

		return new TransactionInterceptor(platformTransactionManager, transactionAttributeSource);
	}

	/**
	 * 当前存在事务就使用当前事务,当前不存在事务就创建一个新的事务
	 * {@link org.springframework.transaction.annotation.Propagation#REQUIRED}
	 */
	private RuleBasedTransactionAttribute requiredTransactionRule() {
		RuleBasedTransactionAttribute required = new RuleBasedTransactionAttribute();
		required.setRollbackRules(Collections.singletonList(new RollbackRuleAttribute(Exception.class)));
		required.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
		required.setTimeout(TransactionDefinition.TIMEOUT_DEFAULT);

		return required;
	}

	/**
	 * 只读事务
	 * {@link org.springframework.transaction.annotation.Propagation#NOT_SUPPORTED}
	 */
	private RuleBasedTransactionAttribute readOnlyTransactionRule() {
		RuleBasedTransactionAttribute readOnly = new RuleBasedTransactionAttribute();
		readOnly.setReadOnly(true);
		readOnly.setPropagationBehavior(TransactionDefinition.PROPAGATION_NOT_SUPPORTED);

		return readOnly;
	}

	/**
	 * 配置事务拦截
	 * <p>
	 * {@link #customTransactionInterceptor(PlatformTransactionManager)}
	 */
	@Bean(name = CUSTOM_BEAN_NAME_AUTO_PROXY_CREATOR_NAME)
	public BeanNameAutoProxyCreator customTransactionBeanNameAutoProxyCreator() {
		BeanNameAutoProxyCreator beanNameAutoProxyCreator = new BeanNameAutoProxyCreator();
		// 设置定制的事务拦截器
		beanNameAutoProxyCreator.setInterceptorNames(CUSTOM_TRANSACTION_INTERCEPTOR_NAME);

		// 默认 + 定制
		String[] unions = ArrayUtils.addAll(DEFAULT_TRANSACTION_BEAN_NAMES, customTransactionBeanNames);
		beanNameAutoProxyCreator.setBeanNames(unions);
		beanNameAutoProxyCreator.setProxyTargetClass(true);

		return beanNameAutoProxyCreator;
	}
}

This one on the Internet is readily possible to search, that is, after you copy over the use of non-brain type, cc ~

analysis

Cook the code above that, a bit like xml configuration of the transaction. It is a method name to match, and then add the transaction.

The reason that this is the case, then look at those two cases before due.

The reason the first case

save to open a default transaction, and then get the time, the transaction pending. update and restore the original transaction, get and hang, then submit.

The reason the second case

Common approach is to not open a transaction, and then get the normal run, update start a business, get here is not going to suspend update transaction, the transaction should be regarded as a sub, this time, update submitted to the transaction. get hit cache, found in old data.

Spring transaction propagation and isolation level learning

spring.io go from official website

Data Access

spring transaction level

Enum Propagation
Here Insert Picture Description
PROPAGATION_REQUIRED

The default isolation level
if a transaction is currently with the current transaction. If not, create one.
Here Insert Picture Description
be careful

When the inner function rollback problem, will result in a rollback outer function together.

PROPAGATION_REQUIRES_NEW

Always New Transaction.

Here Insert Picture Description
important point

Do not affect each other, transaction rollback

PROPAGATION_NESTED

Transaction nesting.
Daitao old sow, one after another, ah ha ha.
Is a transaction inside, there is another transaction. Outside large transaction rollback transaction rollback will result in a small, but small transaction rollback does not affect the large transaction execution.

Look read-only configuration

Here Insert Picture Description

Published 212 original articles · won praise 30 · views 190 000 +

Guess you like

Origin blog.csdn.net/weixin_38336658/article/details/103976888
Recommended