适用版本:v3.3.6+;
dependency
<dependency>
<groupId>net.oschina.j2cache</groupId>
<artifactId>j2cache-core</artifactId>
<version>${j2cache-core.version}</version>
</dependency>
<dependency>
<groupId>net.oschina.j2cache</groupId>
<artifactId>j2cache-mybatis</artifactId>
<version>${j2cache.version}</version>
</dependency>
配置说明
j2cache.properties配置说明:
配置文件位于platform/business服务下的config/j2cache.properties文件
# 缓存广播方法,支持 jgroups/redis/lettuce/rabbitmq/rocketmq
j2cache.broadcast = lettuce
# 第一二级缓存实现方式,一级支持 ehcache/caffeine, 二级支持 redis/lettuce/memcached
j2cache.L1.provider_class = caffeine
j2cache.L2.provider_class = lettuce
# 在redis缓存数据中启用/禁用ttl(如果禁用,redis中的对象将永远不会过期,默认值:true)
j2cache.sync_ttl_to_redis = true
# 默认情况下是否缓存空对象(默认为false)
j2cache.default_cache_null_object = true
# 缓存序列化方式,支持 fst/kryo/fastjson/java/json/fse
j2cache.serialization = kryo
# caffeine配置文件
caffeine.properties = /config/caffeine.properties
# 缓存名称空间可选,默认为[空]
# redis存储模式 支持 generic/hash
# 发布/订阅频道名称
lettuce.namespace =
lettuce.storage = generic
lettuce.channel = j2cache.platform
caffeine.properties配置说明:
配置文件位于platform/business服务下的config/caffeine.properties文件
#########################################
# Caffeine configuration
# [name] = size, xxxx[s|m|h|d]
#########################################
// 默认缓存,大小是 1000 个对象,TTL 是 30 分钟
// default 是当我们调用如下方法时:
//public void set(String region, String key, Object value)
//如果我们传入的 region 参数(假设为:region1)没有在 caffeine.properties 中定义的话,那 J2Cache 会自动创建一个名为 region1 的缓存 Region,其配置和 default 的配置一致。
default = 1000, 30m
ifrom.context = 10000, 10m
ifrom.sys = 10000, 1h
ifrom.res = 10000, 1h
ifrom.client = 3000, 1h
ifrom.category = 10000, 2h
ifrom.desktop = 1000, 8h
ifrom.group = 1000, 1h
ifrom.attr = 10000, 1h
ifrom.level = 100, 1h
ifrom.party = 10000, 1h
API说明
缓存的相关操作是在Domain和Repository层实现的,具体代码可以在 IBase,IRepository,AbstracDomain,AbstracRepository 中查看。
IBase
// 对象缓存是否启用
default boolean isCacheOpenning()
// 对象缓存是否启用空对象缓存,v3.2.4配置
default boolean isCacheNullObject()
// 返回缓存名称
default String getCacheName()
// 返回内部缓存名称
default String getInternalCacheName()
// 根据pk清除对应缓存
default void evict(PK pk)
// 根据pk和data存入缓存
default void caching(PK pk, P data)
// 返回内部类型
default String getInternalType()
// 根据pk值返回存入缓存中的key值
default String getPKString(PK pk)
IRepository
// 列表缓存是否启用
default boolean isCacheListOpenning()
// 是否跳过内部方法
default Boolean isSkipInternal()
// 是否跳过缓存
default Boolean isSkipCache()
AbstracRepository
// 根据id值从缓存中获取到对应对象完整信息
public P get(PK id)
// originSqlKey:查询所有字段的SqlKey,cacheSqlKey:只查询id字段的SqlKey,queryFilter:查询条件
public List<P> queryByKey(String originSqlKey, String cacheSqlKey, QueryFilter queryFilter)
使用示例
以 DefaultPartyUser 的仓库和领域类为例子
- 仓库
// DefaultPartyUserRepositoryImpl
...
@Override
public String getInternalCacheName() {
return CacheKeyConstants.Region.REGION_IBPS_PARTY; // 返回对应的region名称
}
@Override
public String getInternalType() {
return "DefaultPartyUser"; // 返回对应的类型名称,一般为类的名称即可
}
@Override
public void getInternal(DefaultPartyUserPo p) {
if(BeanUtils.isEmpty(p)) {
return;
}
partyEmployeeRepository.setSkipInternal();
PartyEmployeePo employeePo = partyEmployeeRepository.get(p.getId());
partyEmployeeRepository.removeSkipInternal();
if(BeanUtils.isEmpty(employeePo)) {
return;
}
p.setFullname(employeePo.getName());
p.setName(employeePo.getName());
p.setStatus(employeePo.getStatus());
p.setGender(employeePo.getGender());
p.setMobile(employeePo.getMobile());
p.setEmail(employeePo.getEmail());
p.setAddress(employeePo.getAddress());
p.setQq(employeePo.getQq());
p.setPhoto(employeePo.getPhoto());
p.setWcAccount(employeePo.getWcAccount());
}
@Override
public List<DefaultPartyUserPo> findByParams(Map<String, Object> params) {
return findByKey("findByParams", "findIdsByParams", params);
}
...
- 领域
// DefaultPartyUser
...
@Override
public String getInternalCacheName() {
return CacheKeyConstants.Region.REGION_IBPS_PARTY; // 返回对应的region名称
}
@Override
public String getInternalType() {
return "DefaultPartyUser"; // 返回对应的类型名称,一般为类的名称即可
}
...
- Provider
// PartyUserProvider
...
@ApiOperation(value = "查询", notes = "根据id查询")
@Override
public APIResult<PartyUserPo> get(
@ApiParam(name = "userId", value = "用户ID", required = true)
@RequestParam(name = "userId", required = true)String userId) {
APIResult<PartyUserPo> result = new APIResult<>();
try {
PartyUserPo partyUserPo = defaultPartyUserRepository.get(userId);
result.setData(partyUserPo);
} catch (Exception e) {
setExceptionResult(result, StateEnum.ERROR_EMPLOYEE.getCode(), I18nUtil.getMessage(StateEnum.ERROR_EMPLOYEE.getCode()+""), e);
}
return result;
}
...
- 映射文件
// DefaultPartyUser.map
<sql id="querySql">
SELECT * FROM IFORM_PARTY_USER
left join
(
select ID_ USER_ID_, NAME_, NAME_ FULL_NAME_,STATUS_,GENDER_,EMAIL_,WC_ACCOUNT_,ADDRESS_,MOBILE_,QQ_,PHOTO_ from IBPS_PARTY_EMPLOYEE
)A on USER_ID_ = ID_
<where>
USER_ID_ != '-1' AND A.STATUS_ != 'deleted'
<if test="@o.Ognl@isNotEmpty(whereSql)">
and ${whereSql}
</if>
</where>
<if test="@o.Ognl@isNotEmpty(orderBySql)">
ORDER BY ${orderBySql}
</if>
<if test="@o.Ognl@isEmpty(orderBySql)">
ORDER BY CREATE_TIME_ DESC
</if>
</sql>
<select id="query" parameterType="java.util.Map" resultMap="DefaultPartyUser">
<include refid="querySql"/>
</select>
<select id="queryIds" parameterType="java.util.Map" resultMap="DefaultPartyUser">
SELECT ID_ FROM (<include refid="querySql"/>) T
</select>
<select id="findDialogUserByParam" parameterType="java.util.Map" resultMap="DefaultPartyUser">
<include refid="findDialogUserByParamSql"/>
</select>
<select id="findDialogUserIdsByParamNew" parameterType="java.util.Map" resultMap="DefaultPartyUser">
SELECT ID_ FROM (<include refid="findDialogUserByParamSql"/>) T
</select>
缓存中对象是根据id值进行区分,映射文件中,除了常规的query方法,还应该有只查询id字段的queryIds方法,提供给缓存使用。findByKey和queryByKey方法同理,但非必须,写法参考如上代码。
仓库和领域类需要重写getInternalCacheName方法,参考如上写法,返回对应的缓存分区。setSkipInternal 和 removeSkipInternal 方法为设置是否跳过内部方法,即是否跳过getInternal方法,具体可查看AbstracReposity类中的get方法。
通过如上配置后,通过仓库的get方法,传入对象的id值,会先去缓存中查找对象,缓存中没有,才会到数据库中查询。
作者:caoyl 创建时间:2024-02-29 18:01
最后编辑:caoyl 更新时间:2024-11-25 19:17
最后编辑:caoyl 更新时间:2024-11-25 19:17