This article is generated by AI translation.
Redis Datasource Specifics
dbVisitor accesses Redis data sources via the JDBC-Redis driver, based on the JDBC protocol.
Supported capabilities:
- Execute Redis commands to manipulate data (supported command list)
- JdbcTemplate, Annotations, Mapper File — three usage methods
- Rules, Arguments, ResultSetExtractor/RowMapper and other general capabilities
- Dynamic SQL tags in Mapper Files
Not supported: Fluent API, BaseMapper, Object Mapping, ResultSet Mapping, executeBatch, stored procedures
Concept Analogy
Different Redis commands produce three types of results:
- Update count — analogous to INSERT/UPDATE/DELETE, retrieved via
executeUpdate - Single/multiple row results — analogous to SELECT result sets
Command Mode (JdbcTemplate)
Use JdbcTemplate to execute Redis commands directly. Ensure you have properly configured the Redis data source first — see Redis Driver Usage Guide.
For more usage patterns, see JdbcTemplate. The following features are not supported due to driver limitations:
- Batch operations
- Stored procedures
JdbcTemplate jdbc = new JdbcTemplate(dataSource);
// or
JdbcTemplate jdbc = new JdbcTemplate(connection);
Key Read/Write/Delete
// Direct command
String result1 = jdbc.queryForString("GET myKey");
// Parameterized command
String result2 = jdbc.queryForString("GET ?", "myKey");
// Direct command
int result1 = jdbc.executeUpdate("SET myKey myValue");
// Parameterized command
int result2 = jdbc.executeUpdate("SET ? ?", new Object[] { "myKey", "myValue" });
// Direct command
int result1 = jdbc.executeUpdate("DEL myKey");
// Parameterized command
int result2 = jdbc.executeUpdate("DEL ?", "myKey");
Key Read/Write/Delete (Multiple Keys)
Map<String, Integer> result = jdbc.queryForPairs("MGET ? ? ?", String.class, Integer.class,
new Object[] { "key1", "key2", "key3" });
int result = jdbc.executeUpdate("MSET ? ? ? ? ? ?",
new Object[] { "key1", "value1", "key2", "value2", "key3", "value3" });
int result = jdbc.executeUpdate("DEL ? ? ?", new Object[] { "key1", "key2", "key3" });
Object Read/Write
@BindTypeHandler(JsonTypeHandler.class)
public class MyObject {
...
}
// Read object
MyObject obj = jdbc.queryForObject("GET ?", MyObject.class, "myObjectKey");
// Write object
jdbc.executeUpdate("SET ? ?", new Object[] { "myObjectKey", (MyObject) myObject });
Annotations
All annotations provided by the core API work on Redis data sources, except for the @Call annotation.
@BindTypeHandler(JsonTypeHandler.class)
public class UserInfo {
private String uid;
private String name;
... // getters/setters omitted
}
// Key name uses prefix "user_" combined with UID for storing/retrieving user info
@SimpleMapper()
public interface UserInfoMapper {
@Insert("set #{'user_' + info.uid} #{info}")
int saveUser(@Param("info") UserInfo info);
@Query("get #{'user_' + uid}")
UserInfo loadUser(@Param("uid") String uid);
@Delete("del #{'user_' + uid}")
int deleteUser(@Param("uid") String uid);
}
Configuration config = new Configuration();
Session session = config.newSession(dataSource);
UserInfoMapper mapper = session.createMapper(UserInfoMapper.class);
File Mode (Mapper File)
In XML Mapper files, when configuring object serialization mapping via the select tag, the resultType attribute must be specified to correctly discover the BindTypeHandler annotation on the object.
- Approach 1: Using BindTypeHandler Annotation
- Approach 2: Non-Intrusive
@BindTypeHandler(JsonTypeHandler.class)
public class UserInfo {
private String uid;
private String name;
... // getters/setters omitted
}
<?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.test.dto.UserInfoMapper">
<insert id="saveUser">
set #{'user_' + uid} #{info}
</insert>
<select id="loadUser" resultType="net.test.dto.UserInfo">
get #{'user_' + uid}
</select>
<delete id="deleteUser">
del #{'user_' + uid}
</delete>
</mapper>
public class UserInfo {
private String uid;
private String name;
... // getters/setters omitted
}
<?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.test.dto.UserInfoMapper">
<insert id="saveUser">
set #{'user_' + uid}
#{info, typeHandler=net.hasor.dbvisitor.types.handler.json.JsonTypeHandler}
</insert>
<!-- Need to specify both resultTypeHandler and resultType attributes -->
<select id="loadUser1"
resultTypeHandler="net.hasor.dbvisitor.types.handler.json.JsonTypeHandler"
resultType="net.test.dto.UserInfo">
get #{'user_' + uid}
</select>
<select id="loadUser2" resultType="net.test.dto.UserInfo">
get #{'user_' + uid}
</select>
<delete id="deleteUser">
del #{'user_' + uid}
</delete>
</mapper>
@RefMapper("dbvisitor/mapper/UserInfoMapper.xml")
public interface UserInfoMapper {
int saveUser(@Param("info") UserInfo info);
UserInfo loadUser(@Param("uid") String uid);
int deleteUser(@Param("uid") String uid);
}
Configuration config = new Configuration();
Session session = config.newSession(dataSource);
UserInfoMapper mapper = session.createMapper(UserInfoMapper.class);
Redis Data Type Operations
Redis has 5 main data types. Below is how to use dbVisitor for read/write operations on each type.
String
jdbc.executeUpdate("SET ? ?", new Object[] { "myKey", "myValue" });
String value = jdbc.queryForString("GET ?", "myKey");
jdbc.executeUpdate("SETEX ? ? ?", new Object[] { "myKey", 60, "myValue" });
jdbc.executeUpdate("SET ? ? EX ?", new Object[] { "myKey", "myValue", 60 });
- Reference: SET command
jdbc.executeUpdate("SET myKey 0"); // Initial value 0
String result = jdbc.queryForString("INCR ?", "myKey"); // Value after increment: 1
String result = jdbc.queryForString("DECR ?", "myKey"); // Value after decrement: 0
- Reference: INCR command, DECR command
jdbc.executeUpdate("SET myKey myValue"); // Initial value: myValue
String result = jdbc.queryForString("APPEND ? ?", new Object[] { "myKey", "123" }); // After append: myValue123
String result = jdbc.queryForString("GETRANGE ? ? ?", new Object[] { "myKey", 0, 5 });// After substring: myVal
- Reference: APPEND command, GETRANGE command
// MyObject type needs to be annotated with @BindTypeHandler(JsonTypeHandler.class)
jdbc.queryForObject("GET myObjectKey", MyObject.class);
jdbc.executeUpdate("SET myObjectKey ?", (MyObject) myObject);
- Reference: GET command, SET command
Hash
jdbc.executeUpdate("HSET myHashKey field1 value1");
jdbc.queryForString("HGET ? ?", new Object[] { "myHashKey", "field1" });
- Reference: HSET command, HGET command
List<String> keys = jdbc.queryForList("HKEYS myHashKey", String.class);
- Reference: HKEYS command
Map<String, String> hashFields = jdbc.queryForPairs("HGETALL myHashKey", String.class, String.class);
- Reference: HGETALL command
Map<String,String> hashData = new HashMap<>();
hashData.put("field1", "value1");
hashData.put("field2", "value2");
jdbc.executeUpdate("HSET myKey1 @{pairs, :arg0, :k :v}", SqlArg.valueOf(hashData));
- Reference: HSET command, PAIRS Rule
List
jdbc.executeUpdate("LPUSH myListKey value1 value2 value3");
String result = jdbc.queryForString("LPOP myListKey"); // value3
String result = jdbc.queryForString("RPOP myListKey"); // value1
- Reference: LPUSH command, LPOP command, RPOP command
// Left-in right-out blocking queue
jdbc.executeUpdate("LPUSH myListKey value1");
String result = jdbc.queryForString("BRPOP myListKey");
// Right-in left-out blocking queue
jdbc.executeUpdate("RPUSH myListKey value1");
String result = jdbc.queryForString("BLPOP myListKey");
- Reference: LPUSH command, BRPOP command
List<String> listData = new ArrayList<>();
listData.add("value1");
listData.add("value2");
jdbc.executeUpdate("LPUSH myListKey @{pairs, :arg0, :v}", SqlArg.valueOf(listData));
- Reference: LPUSH command, PAIRS Rule
Set
jdbc.executeUpdate("SADD mySetKey value1 value2 value3");
jdbc.queryForList("SMEMBERS mySetKey", String.class);
- Reference: SADD command, SMEMBERS command
jdbc.executeUpdate("SADD article_1 tag1 tag2");
jdbc.executeUpdate("SADD article_1 tag1 tag3");
jdbc.queryForList("SMEMBERS article_1", String.class); // Result: [tag1, tag2, tag3]
Map<String,String> hashData = new HashMap<>();
hashData.put("field1", "value1");
hashData.put("field2", "value2");
jdbc.executeUpdate("SADD myKey1 @{pairs, :arg0, :k}", SqlArg.valueOf(hashData));
jdbc.queryForList("SMEMBERS myKey1", String.class); // Result: [field1, field2]
- Reference: SADD command, PAIRS Rule
Sorted Set
Sorted Set is similar to Set, but each element has a score, allowing elements to be sorted by score.
jdbc.execute("ZADD mySetKey 3 value3 2 value2 1 value1");
jdbc.queryForList("ZRANGEBYSCORE mySetKey -inf +inf ", String.class); // [value1, value2, value3]
- Reference: ZADD command, ZRANGEBYSCORE command
Map<String,Double> hashData = new HashMap<>();
hashData.put("field1", 3.0);
hashData.put("field2", 2.0);
hashData.put("field3", 1.0);
jdbc.executeUpdate("ZADD myKey1 @{pairs, :arg0, :v :k}", SqlArg.valueOf(hashData));
jdbc.queryForList("ZRANGEBYSCORE myKey1 -inf +inf ", String.class); // [field3, field2, field1]
- Reference: ZADD command, PAIRS Rule
List<Tuple> data = new ArrayList<>();
data.add(Tuple.of("field1", 3.0));
data.add(Tuple.of("field2", 2.0));
data.add(Tuple.of("field3", 1.0));
jdbc.queryForString("ZADD myKey1 @{pairs, :arg0, :v.arg1 :v.arg0 }", SqlArg.valueOf(data));
jdbc.queryForList("ZRANGEBYSCORE myKey1 -inf +inf ", String.class); // [field3, field2, field1]
- Reference: ZADD command, PAIRS Rule
- In addition to Tuple type, you can also use Map type or custom types to store elements and scores
:v.arg1uses the Named Arguments approach to pass parameters