v6.2.0 (2025-11-22)
<dependency>
<groupId>net.hasor</groupId>
<artifactId>jdbc-redis</artifactId>
<version>6.2.0</version>
</dependency>
影响范围
- JdbcOperations 接口和 JdbcTemplate 类
- dbvisitor-driver 项目
- jdbc-redis 驱动
更新内容
- 新增
- 在 Mapper 注解化、Mapper File、JdbcTemplate 级别 API 上适配 jdbc-redis 驱动。
- 恢复 5.x 版本中的 BindTypeHandler 注解。
- XmlMapper 和 Query 注解,添加 resultTypeHandler 属性可以配置 TypeHandler
- TypeHandlerColumnRowMapper 可以将 TypeHandler 作为 RowMapper 使用。
- jdbc-redis 驱动新支持 PING、ECHO、SELECT、INFO 命令。
- 对于 DataGrip 和 IDEA 内嵌 Database 插件中使用 jdbc-redis 驱动连接 Redis 的支持。
- ResultSetExtractor 接口新增 PairsResultSetExtractor 实现,用于将结果集转换为键值对集合。
- JdbcOperations/JdbcTemplate 新增三个 queryForPairs 方法,可以将查询结果的每一行数据都转换为一个键值对。
- 新的 pairs 规则,用于遍历 Map/List/Array 等集合类型,并使用固定模版生成查询条件。
- 变更
- queryForLong 方法返回值类型从 long 变更为 Long。
- queryForInt 方法返回值类型从 int 变更为 Integer。
- AbstractRowMapper 类的 getResultSetTypeHandler(ResultSet, int, Class) 方法移动到 TypeHandlerRegistry 类中。
- jdbc-redis 驱动在执行 MSET/MSETNX 命令时,返回值为添加的 Key 数量(此之前始终返回 1)
- jdbc-redis 驱动中涉及 StoreSet 类型的相关命令在同时输出 SCORE、ELEMENT 字段时,结果集字段顺序调整为 ELEMENT、SCORE。具体命令有:
- ZPOPMAX、ZPOPMIN、ZDIFF、ZINTER、ZRANDMEMBER、ZRANGE、ZRANGEBYSCORE、ZREVRANGE、ZREVRANGEBYSCORE、ZUNION、ZMPOP、BZMPOP、BZPOPMAX、BZPOPMIN、ZSCAN
- 优化
- jdbc-redis 驱动支持 ResultSet 的 isLast 方法。
- 对于部分命令在执行完毕后通过使用 updateCount 方法返回执行结果,这些命令有:
- HKEYS、HDEL、DEL、SET、HSET、HMSET、HSETNX、EXPIRE、EXPIREAT、PEXPIRE、PEXPIREAT、PERSIST、RENAME、RENAMENX、 TOUCH、LINSERT、LPUSH、LPUSHX、RPUSH、RPUSHX、LREM、LSET、LTRIM、MOVE、SADD、SDIFFSTORE、SINTERSTORE、SMOVE、 SREM、SUNIONSTORE、ZDIFFSTORE、ZINTERSTORE、ZRANGESTORE、ZREM、ZREMRANGEBYLEX、ZREMRANGEBYRANK、ZREMRANGEBYSCORE、 ZUNIONSTORE、MSET、MSETNX、PSETEX、SETEX、SETNX、SETRANGE
- 对于 antlr4 的依赖,内嵌到 jdbc-redis 驱动 jar 包中,以减少外部依赖。
- 优化 jdbc-redis 驱动报错信息。
- dbvisitor-driver 中的 ConvertUtils 在处理 toBytes 时兼容 Byte[] 类型。
- 修复
- jdbc-redis 驱动中 Statement 的 getLargeUpdateCount 和 getUpdateCount 没有结果集时会抛出 SQLException 的问题。保持和 jdbc 描述一致,在没有更多结果时返回 -1。
- jdbc-redis 驱动中 keys 命令无法执行的问题。
queryForPairs 作用
使用 JdbcTemplate 查询键值对
// 查询用户表,将用户 ID 和用户名作为 Map 返回
Map<Long, String> userMap = jdbc.queryForPairs("select uid, name from user", Long.class, String.class);
Redis 兼容如何使用?
使用 JdbcTemplate 存取对象
// 1. 使用 BindTypeHandler 注 释标记 UserInfo 类,指定使用 JsonTypeHandler 来处理该类的序列化和反序列化
@BindTypeHandler(JsonTypeHandler.class)
public class UserInfo {
...
}
// 2. 获取 Redis 连接,并构建 JdbcTemplate
Connection redisConn = ...; // 参考文档:驱动适配器 > JDBC Redis > 如何使用
JdbcTemplate jdbc = new JdbcTemplate(redisConn);
// 3. 创建 UserInfo 对象,将其插入到 Redis 中,并使用 Json 序列化存储
UserInfo user = new UserInfo();
user.setUid("j1111");
user.setName("username");
user.setLoginName("login_123");
user.setLoginPassword("password");
// 4. 使用 user_ + uid 作为键名,arg0 为 user 对象
int affected = jdbc.executeUpdate("set #{'user_' + arg0.uid} #{arg0}", user);
// 5. 从 Redis 中查询 UserInfo 对象,并进行反序列化
UserInfo info = jdbc.queryForObject("get #{'user_' + arg0}", "j1111", UserInfo.class);
// 6. 删除 Redis 中的 UserInfo 对象
int deleteCount = jdbc.executeUpdate("del #{'user_' + arg0.uid}", user);
使用 Mapper 注解存取对象
// 1. 使用 BindTypeHandler 注释标记 UserInfo 类,指定使用 JsonTypeHandler 来处理该类的序列化和反序列化
@BindTypeHandler(JsonTypeHandler.class)
public class UserInfo {
...
}
@SimpleMapper()
public interface UserInfo1Mapper {
// 1. 生成参数化命令:set ? ?
// 2. 决定键名: #{'user_' + info.uid}
// 3. 键的值: #{info}
@Insert("set #{'user_' + info.uid} #{info}")
int saveUser(@Param("info") UserInfo info);
// 1. 生成参数化命令:get ?
// 2. 决定键名: #{'user_' + uid}
@Query("get #{'user_' + uid}")
UserInfo loadUser(@Param("uid") String uid);
// 1. 生成参数化命令:del ?
// 2. 决定键名: #{'user_' + uid}
@Delete("del #{'user_' + uid}")
int deleteUser(@Param("uid") String uid);
}
使用 Mapper File 管理命令(Mapper)
@RefMapper("dbvisitor_scene/redis/user-mapper.xml")
public interface UserInfoMapper {
int saveUser(@Param("info") UserInfo info);
UserInfo loadUser1(@Param("uid") String uid);
UserInfo loadUser2(@Param("uid") String uid);
int deleteUser(@Param("uid") String uid);
}
使用 Mapper File 管理命令(Mapper File)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//dbvisitor.net//DTD Mapper 1.0//EN"
"https://www.dbvisitor.net/schema/dbvisitor-mapper.dtd">
<mapper namespace="net.hasor.scene.UserInfoMapper">
<insert id="saveUser">
set #{'user_' + uid} #{info}
</insert>
<select id="loadUser" resultType="net.hasor.scene.UserInfo">
get #{'user_' + uid}
</select>
<delete id="deleteUser">
del #{'user_' + uid}
</delete>
</mapper>