请问java怎么存储一个TransactionStatus对象?

现在遇到的问题:想存储一个TransactionStatus对象,不是类似entity存储到db,或者随便找个map什么的放在内存中。
是想存在redis里。

org.springframework.transaction.TransactionStatus

能想到的三种方式:
  1 是使用java自带的序列化,但是 TransactionStatus没实现 Serializable。
  2 是用json存,在序列化时,会报错,但是异常被吞了,调试也没看出来哪里报错了。
  3 是使用protobuf 序列化,结果同上,报异常但是被吞了。

请求:后两种方式报错,是不是因为 TransactionStatus是个interface ?
      后两种序列化简单对象是没问题的

TransactionStatus是一个接口,无法直接序列化。要存储TransactionStatus对象,有几种思路的
1.使TransactionStatus实现Serializable接口。但是这个Interfaces通常不推荐实现Serializable
2. 在Redis中存储TransactionStatus的具体实现类。比如DefaultTransactionStatus。然后你可以在Redis中获取DefaultTransactionStatus对象,并将其转换为TransactionStatus接口。
3. 只存储TransactionStatus对象的相关信息,不直接存储整个对象。
4.自定义一个TransactionStatus的包装类,使其实现Serializable,里面包含一个TransactionStatus对象。在序列化与反序列化时,对这个内部对象进行处理。

TransactionStatus 是一个接口而不是一个具体的类,所以无法直接进行序列化。如果你想要将 TransactionStatus 存储到 Redis 中,你可以使用 TransactionSynchronizationManager 中提供的一些方法,将 TransactionStatus 转换成一个可序列化的对象,然后再存储到 Redis 中。

下面是一种可能的实现方式:

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionStatus;
import org.springframework.transaction.support.TransactionSynchronizationManager;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;

public class RedisTransactionStatusStore {

  @Resource
  private RedisTemplate<String, Object> redisTemplate;

  public void storeTransactionStatus(String transactionId) {
    TransactionStatus transactionStatus = TransactionSynchronizationManager.getCurrentTransactionStatus();
    if (transactionStatus == null) {
      return;
    }
    Map<String, Object> serializedTransactionStatus = serializeTransactionStatus(transactionStatus);
    redisTemplate.opsForHash().putAll(transactionId, serializedTransactionStatus);
  }

  private Map<String, Object> serializeTransactionStatus(TransactionStatus transactionStatus) {
    Map<String, Object> serializedTransactionStatus = new HashMap<>();
    serializedTransactionStatus.put("isCompleted", transactionStatus.isCompleted());
    serializedTransactionStatus.put("hasSavepoint", transactionStatus.hasSavepoint());
    // 将其他需要存储的 TransactionStatus 属性也放到 serializedTransactionStatus 中
    return serializedTransactionStatus;
  }

  public TransactionStatus retrieveTransactionStatus(String transactionId) {
    Map<Object, Object> serializedTransactionStatus = redisTemplate.opsForHash().entries(transactionId);
    if (serializedTransactionStatus.isEmpty()) {
      return null;
    }
    return deserializeTransactionStatus(serializedTransactionStatus);
  }

  private TransactionStatus deserializeTransactionStatus(Map<Object, Object> serializedTransactionStatus) {
    boolean isCompleted = (boolean) serializedTransactionStatus.get("isCompleted");
    boolean hasSavepoint = (boolean) serializedTransactionStatus.get("hasSavepoint");
    // 从 serializedTransactionStatus 中读取其他 TransactionStatus 属性的值,创建一个 DefaultTransactionStatus 对象
    return new DefaultTransactionStatus(null, isCompleted, false, hasSavepoint, false, null);
  }
}

在这个例子中,我们创建了一个 RedisTransactionStatusStore 类,该类依赖于 RedisTemplate 对象,用于将 TransactionStatus 存储到 Redis 中。在 storeTransactionStatus 方法中,我们首先获取当前的 TransactionStatus 对象,然后将其转换成一个可序列化的对象,并存储到 Redis 中。在 retrieveTransactionStatus 方法中,我们从 Redis 中读取存储的对象,并将其反序列化为一个 TransactionStatus 对象。

这种方法的关键在于如何将 TransactionStatus 转换成一个可序列化的对象,以及如何从可序列化的对象反序列化为一个 TransactionStatus 对象。在这个例子中,我们只是将 TransactionStatus 的一些属性值存储到了一个 Map 中,并在需要时从 Map 中读取这些属性值,创建一个 DefaultTransactionStatus 对象。你可以根据自己的需要调整这些属性的值,或者添加其他需要存储的属性。

我好奇,为什么需要缓存TransactionStatus对象呢。想知道背后的原因,或者你想实现什么样的功能呢

是的,您提到的问题出现的原因可能是 TransactionStatus 是一个接口,而不是一个具体的类。因此,使用一般的序列化方法(如Java自带的序列化、JSON序列化或Protobuf)可能会导致异常或无法正常序列化。

对于存储 TransactionStatus 对象到 Redis 中,有两种常用的解决方案:

  1. 自定义序列化器:您可以实现 RedisSerializer 接口来自定义序列化器,并在配置 RedisTemplate 时指定该序列化器。在自定义序列化器中,您可以根据 TransactionStatus 的实际信息进行序列化和反序列化操作。这种方式需要您编写额外的代码来处理对象的序列化和反序列化逻辑。

  2. 使用代理对象:Spring 提供了 TransactionOperations 接口,其实现类为 TransactionTemplate。您可以将 TransactionTemplate 作为一个代理对象存储到 Redis 中,并在需要使用 TransactionStatus 的时候从 Redis 中获取该代理对象。通过代理对象,在必要的时候还可以通过相应的方法调用间接操作 TransactionStatus