refactor: rename TransactionDefinitionManager to TimeoutHolder

This commit is contained in:
Michael Yang 2024-10-29 10:01:21 +08:00
parent 657cb59b79
commit 7aad5d8410
4 changed files with 91 additions and 149 deletions

View File

@ -19,7 +19,6 @@ import com.mybatisflex.core.datasource.FlexDataSource;
import com.mybatisflex.core.transaction.TransactionContext;
import com.mybatisflex.core.util.StringUtil;
import org.apache.ibatis.transaction.Transaction;
import org.springframework.transaction.TransactionDefinition;
import java.sql.Connection;
import java.sql.SQLException;
@ -83,10 +82,6 @@ public class FlexSpringTransaction implements Transaction {
@Override
public Integer getTimeout() throws SQLException {
TransactionDefinition definition = TransactionDefinitionManager.getTransactionDefinition();
if (definition != null) {
return TransactionDefinitionManager.getTimeToLiveInSeconds();
}
return null;
return TimeoutHolder.getTimeToLiveInSeconds();
}
}

View File

@ -31,7 +31,6 @@ import org.springframework.transaction.support.DefaultTransactionStatus;
*/
public class FlexTransactionManager extends AbstractPlatformTransactionManager {
@Override
protected Object doGetTransaction() throws TransactionException {
return new TransactionObject(TransactionContext.getXID());
@ -59,8 +58,9 @@ public class FlexTransactionManager extends AbstractPlatformTransactionManager {
@Override
protected void doBegin(Object transaction, TransactionDefinition definition) throws TransactionException {
TransactionObject transactionObject = (TransactionObject) transaction;
TransactionDefinitionManager.setTransactionDefinition(definition);
transactionObject.currentXid = TransactionalManager.startTransactional();
TimeoutHolder.hold(definition);
}
@Override
@ -88,12 +88,11 @@ public class FlexTransactionManager extends AbstractPlatformTransactionManager {
@Override
protected void doCleanupAfterCompletion(Object transaction) {
TransactionDefinitionManager.clear();
TimeoutHolder.clear();
}
static class TransactionObject extends JdbcTransactionObjectSupport {
private static final ThreadLocal<String> ROLLBACK_ONLY_XIDS = new ThreadLocal<>();
private final String prevXid;

View File

@ -0,0 +1,87 @@
/*
* Copyright (c) 2022-2025, Mybatis-Flex (fuhai999@gmail.com).
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mybatisflex.spring;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionTimedOutException;
import java.util.Date;
/**
* 事务定义管理器 用于更完整的实现Spring事务
* 仅支持传统事务不支持R2DBC事务
*
* @author Aliothmoon
* @author Michael
* @since 2024/10/25
*/
public final class TimeoutHolder {
private static final ThreadLocal<Long> TRANSACTION_DEADLINE = new ThreadLocal<>();
public static void hold(TransactionDefinition definition) {
if (definition == null) {
return;
}
int timeout = definition.getTimeout();
if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
Long deadline = System.currentTimeMillis() + timeout * 1000L;
TRANSACTION_DEADLINE.set(deadline);
}
}
/**
* 清除事务上下文
*/
public static void clear() {
TRANSACTION_DEADLINE.remove();
}
/**
* 获取当前事务可用TTL
*
* @return int
*/
public static Integer getTimeToLiveInSeconds() {
Long deadline = TRANSACTION_DEADLINE.get();
if (deadline == null) {
return null;
}
double diff = ((double) getTimeToLiveInMillis(deadline)) / 1000;
int secs = (int) Math.ceil(diff);
checkTransactionTimeout(secs <= 0, deadline);
return secs;
}
private static void checkTransactionTimeout(boolean deadlineReached, Long deadline) throws TransactionTimedOutException {
if (deadlineReached) {
throw new TransactionTimedOutException("Transaction timed out: deadline was " + new Date(deadline));
}
}
private static long getTimeToLiveInMillis(Long deadline) throws TransactionTimedOutException {
if (deadline == null) {
throw new IllegalStateException("No timeout specified for this resource holder");
}
long timeToLive = deadline - System.currentTimeMillis();
checkTransactionTimeout(timeToLive <= 0, deadline);
return timeToLive;
}
}

View File

@ -1,139 +0,0 @@
package com.mybatisflex.spring;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionTimedOutException;
import java.util.Date;
/**
* 事务定义管理器 用于更完整的实现Spring事务
* 仅支持传统事务不支持R2DBC事务
*
* @author Aliothmoon
* @since 2024/10/25
*/
public final class TransactionDefinitionManager {
private static final ThreadLocal<TransactionDefinition> TRANSACTION_DEFINITION = new ThreadLocal<>();
private static final ThreadLocal<Date> TRANSACTION_DEADLINE = new ThreadLocal<>();
public static TransactionDefinition getTransactionDefinition() {
return TRANSACTION_DEFINITION.get();
}
public static void setTransactionDefinition(TransactionDefinition definition) {
if (definition == null) {
return;
}
int timeout = definition.getTimeout();
Definition def = new Definition();
def.setTimeout(timeout);
def.setIsolationLevel(definition.getIsolationLevel());
def.setPropagationBehavior(definition.getPropagationBehavior());
def.setIsolationLevel(definition.getIsolationLevel());
def.setName(definition.getName());
TRANSACTION_DEFINITION.set(def);
if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
Date deadline = new Date(System.currentTimeMillis() + timeout * 1000L);
TRANSACTION_DEADLINE.set(deadline);
}
}
/**
* 清除事务上下文
*
*/
public static void clear() {
TRANSACTION_DEFINITION.remove();
TRANSACTION_DEADLINE.remove();
}
/**
* 获取当前事务可用TTL
*
* @return int
*/
public static int getTimeToLiveInSeconds() {
Date deadline = TRANSACTION_DEADLINE.get();
if (deadline == null) {
return 0;
}
double diff = ((double) getTimeToLiveInMillis(deadline)) / 1000;
int secs = (int) Math.ceil(diff);
checkTransactionTimeout(secs <= 0, deadline);
return secs;
}
private static void checkTransactionTimeout(boolean deadlineReached, Date deadline) throws TransactionTimedOutException {
if (deadlineReached) {
throw new TransactionTimedOutException("Transaction timed out: deadline was " + deadline);
}
}
private static long getTimeToLiveInMillis(Date deadline) throws TransactionTimedOutException {
if (deadline == null) {
throw new IllegalStateException("No timeout specified for this resource holder");
}
long timeToLive = deadline.getTime() - System.currentTimeMillis();
checkTransactionTimeout(timeToLive <= 0, deadline);
return timeToLive;
}
private static class Definition implements TransactionDefinition {
private Integer propagationBehavior;
private Integer isolationLevel;
private Integer timeout;
private String name;
private Boolean readOnly;
public void setReadOnly(Boolean readOnly) {
this.readOnly = readOnly;
}
public void setTimeout(Integer timeout) {
this.timeout = timeout;
}
public void setIsolationLevel(Integer isolationLevel) {
this.isolationLevel = isolationLevel;
}
public void setPropagationBehavior(Integer propagationBehavior) {
this.propagationBehavior = propagationBehavior;
}
public void setName(String name) {
this.name = name;
}
@Override
public int getPropagationBehavior() {
return propagationBehavior == null ? TransactionDefinition.super.getPropagationBehavior() : propagationBehavior;
}
@Override
public int getIsolationLevel() {
return isolationLevel == null ? TransactionDefinition.super.getIsolationLevel() : isolationLevel;
}
@Override
public int getTimeout() {
return timeout == null ? TransactionDefinition.super.getTimeout() : timeout;
}
@Override
public boolean isReadOnly() {
return readOnly == null ? TransactionDefinition.super.isReadOnly() : readOnly;
}
@Override
public String getName() {
return name == null ? TransactionDefinition.super.getName() : name;
}
}
}