-
Notifications
You must be signed in to change notification settings - Fork 2.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
The query cache is not cleared after transaction rolls back to a savepoint #785
Comments
The cache feature belong the MyBatis core module. Probably, the MyBatis core module does not support to clear cache when rollback savepoint. You can prevent this behavior with @harawata |
MyBatis' cache is not aware of Spring transaction's savepoint. |
@harawata How about merge the following code into mybatis-spring-boot-starter? I solved this problem by add a clear cache post processor just like spring-tx did. import org.aopalliance.intercept.MethodInterceptor;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.aop.framework.AbstractAdvisingBeanPostProcessor;
import org.springframework.aop.support.AopUtils;
import org.springframework.aop.support.StaticMethodMatcherPointcutAdvisor;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.annotation.AnnotationTransactionAttributeSource;
import org.springframework.transaction.interceptor.TransactionAttribute;
import org.springframework.transaction.interceptor.TransactionalProxy;
import java.lang.reflect.Method;
/**
* Clear mybatis cache after transaction rollback
* <p>Spring will not notify mybatis to clear cache after a savepoint rollback. This class
* catches a exception, clears the mybatis cache and rethrows it back</p>
*
* @author luozhenyu
*/
@Component
public class MybatisClearCachePostProcessor extends AbstractAdvisingBeanPostProcessor implements InitializingBean {
private final AnnotationTransactionAttributeSource annotationTransactionAttributeSource
= new AnnotationTransactionAttributeSource();
private final SqlSessionTemplate sqlSessionTemplate;
@Autowired
public MybatisClearCachePostProcessor(SqlSessionTemplate sqlSessionTemplate) {
this.sqlSessionTemplate = sqlSessionTemplate;
}
@Override
public void afterPropertiesSet() {
StaticMethodMatcherPointcutAdvisor clearCacheAdvisor = new StaticMethodMatcherPointcutAdvisor() {
@Override
public boolean matches(Method method, Class<?> targetClass) {
if (targetClass != null && TransactionalProxy.class.isAssignableFrom(targetClass)) {
return false;
}
TransactionAttribute attribute = annotationTransactionAttributeSource.getTransactionAttribute(method, targetClass);
return attribute != null && attribute.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED;
}
};
clearCacheAdvisor.setAdvice((MethodInterceptor) invocation -> {
try {
return invocation.proceed();
} catch (Throwable t) {
Method method = invocation.getMethod();
Class<?> targetClass = invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null;
TransactionAttribute attribute = annotationTransactionAttributeSource.getTransactionAttribute(method, targetClass);
if (attribute != null && attribute.rollbackOn(t)) {
sqlSessionTemplate.clearCache();
}
throw t;
}
});
this.advisor = clearCacheAdvisor;
this.beforeExistingAdvisors = true;
}
} |
The text was updated successfully, but these errors were encountered: