1.情况

SpringBoot在使用@Cacheable缓存对象为空

具体就是在实体类的时候,List<Integer>为空

1.1 实体类

@Schema( description = "赠送礼物id")
private List<Integer> itemId;
@Schema( description = "赠送礼物数量")
private List<Integer> itemNum;

1.2 数据库

item_id varchar(255)

item_num varchar(255)

1.3 Service

@Cacheable(cacheNames = "Task", sync = true, key = "#root.methodName+ '_'+ #root.args[1] + #page + '_' + #size")

1.4 具体情况

在mybatisplus的日志中

Row: 5, 1333, 333, [3037], [1], 1, 2025-11-05 16:10:45, null, 2025-11-05 16:10:45, 0

也就是在mybatisplus读取数据的时候是正常的,但是

List<Task> taskList = iPage.getRecords();
        for (Task task1 : taskList) {
            System.out.println(task1);
            System.out.println(task1.getItemId() + "---" + task1.getItemNum());
        }

在输出taskList的时候

Task(id=9, name=555, content=555, itemId=null, itemNum=null, onlineCount=1, createTime=Wed Nov 05 16:54:30 CST 2025, endTime=Thu Nov 06 00:00:00 CST 2025, updateTime=Wed Nov 05 16:54:30 CST 2025, deleted=0)

null---null

可以看到itemId itemNum均为null

redisTemplate配置了FastJsonRedisSerializer

就是在转为 List<Integer>的时候出了问题

2.解决方案

我的Fastjson2

2.1 maven导入Fastjson2

	<!-- fastJson -->
		<!-- https://mvnrepository.com/artifact/com.alibaba.fastjson2/fastjson2 -->
		<dependency>
			<groupId>com.alibaba.fastjson2</groupId>
			<artifactId>fastjson2</artifactId>
			<version>2.0.59</version>
		</dependency>

2.2 附上我的RedisConfig.java

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
@Configuration
//@EnableCaching开启对SpringCache的支持(提供基于方法级别的缓存)
@EnableCaching
public class RedisConfig {

    /**
     * 默认缓存到期时间
     */
    private static final Integer DEFAULT_EXPIRE_TIME = 3600;

    @Bean
    @SuppressWarnings("all")
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory, ObjectMapper objectMapper) {
        //便于开发自己编写redis
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory);
        //序列化配置
        GenericJackson2JsonRedisSerializer serializer = new GenericJackson2JsonRedisSerializer();
//        FastJsonRedisSerializer<Object> serializer = new FastJsonRedisSerializer<>(Object.class);
//        FastJson2JsonRedisSerializer<Object> serializer = new FastJson2JsonRedisSerializer<>(Object.class);
        //string序列化

        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        //key 采用string的序列化
        template.setKeySerializer(stringRedisSerializer);
        template.setValueSerializer(serializer);
        //hansh的key也采用string的序列化方式
        template.setHashKeySerializer(stringRedisSerializer);
        //hansh的value也采用string的序列化方式
        template.setHashValueSerializer(serializer);
        //设置默认
        template.setDefaultSerializer(serializer);

        template.afterPropertiesSet();

        return template;
    }

    /**
     * 配置SpringCache基于方法级别的缓存的过期时间、key-value的序列化方式
     *
     * @param connectionFactory
     * @return
     */
    @Bean
    public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {
        //设置特有的Redis配置
        Map<String, RedisCacheConfiguration> speCacheConfigurations = new HashMap<>();
        //定制化的Cache为300s\400s\500s
        speCacheConfigurations.put("cacheName1",redisCacheConfiguration(300));
        speCacheConfigurations.put("cacheName2",redisCacheConfiguration(400));
        speCacheConfigurations.put("cacheName3",redisCacheConfiguration(500));
        //根据redis缓存配置和redis连接工厂生成redis缓存管理器
        RedisCacheManager redisCacheManager = RedisCacheManager.builder(connectionFactory)
                .cacheDefaults(redisCacheConfiguration(DEFAULT_EXPIRE_TIME)) // 默认缓存配置
                .withInitialCacheConfigurations(speCacheConfigurations) // 定制化的缓存配置
                .build();
        return redisCacheManager;
    }

    /**
     * RedisCacheConfiguration redis缓存配置
     *
     * @param ttl 缓存过期时间
     * @return
     */
    public RedisCacheConfiguration redisCacheConfiguration(Integer ttl) {
        //redis缓存配置
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                //缓存生存时间60秒
                .entryTtl(Duration.ofSeconds(ttl))
                // 配置Key序列化(解决乱码的问题)
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
                // 配置Value序列化
                .serializeValuesWith(RedisSerializationContext.SerializationPair
                        .fromSerializer(
                                new GenericJackson2JsonRedisSerializer()
//                                new FastJsonRedisSerializer<Object>(Object.class)
                        ))
                // 不缓存空值
                .disableCachingNullValues();
        return config;
    }
}

2.3 创建JsonListIntegerTypeHandler.java

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.TypeReference;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

public class JsonListIntegerTypeHandler extends BaseTypeHandler<List<Integer>> {
    // 插入/更新时:将List<Integer>转为JSON字符串存入数据库
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, List<Integer> parameter, JdbcType jdbcType) throws SQLException {
        String jsonStr = JSON.toJSONString(parameter); // 例如:[3037, 3038]
        ps.setString(i, jsonStr);
    }

    // 查询时:从数据库读取字符串并解析为List<Integer>
    @Override
    public List<Integer> getNullableResult(ResultSet rs, String columnName) throws SQLException {
        String jsonStr = rs.getString(columnName);
        return parseJsonToList(jsonStr);
    }

    @Override
    public List<Integer> getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        String jsonStr = rs.getString(columnIndex);
        return parseJsonToList(jsonStr);
    }

    @Override
    public List<Integer> getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        String jsonStr = cs.getString(columnIndex);
        return parseJsonToList(jsonStr);
    }

    // 解析JSON字符串为List<Integer>
    private List<Integer> parseJsonToList(String jsonStr) {
        if (jsonStr == null || jsonStr.trim().isEmpty()) {
            return null;
        }
        // 使用FastJSON解析为List<Integer>
        return JSON.parseObject(jsonStr, new TypeReference<List<Integer>>() {});
    }
}

2.4 在实体类上注解@TableField

    @Schema( description = "赠送礼物id")
    @TableField(value = "item_id", typeHandler = JsonListIntegerTypeHandler.class)
    private List<Integer> itemId;
    @Schema( description = "赠送礼物数量")
    @TableField(value = "item_Num", typeHandler = JsonListIntegerTypeHandler.class)
    private List<Integer> itemNum;

2.5 最重要的在properties或者yaml中启动Handler

下面的xxx换成你自己包的目录

2.5.1 yaml

mybatis-plus:
  typehandlers-package: com.xxx.handler

2.5.2 properties

mybaits-plus.typehandlers-package=com.xxx.handler

3 结果展示

Task(id=9, name=555, content=555, itemId=[3037], itemNum=[1], onlineCount=1, createTime=Wed Nov 05 16:54:30 CST 2025, endTime=Thu Nov 06 00:00:00 CST 2025, updateTime=Wed Nov 05 16:54:30 CST 2025, deleted=0)
[3037]---[1]