001/* 002 * Copyright (c) 2022-2025, Mybatis-Flex (fuhai999@gmail.com). 003 * <p> 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * <p> 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * <p> 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package com.mybatisflex.spring.service.impl; 018 019import com.mybatisflex.core.BaseMapper; 020import com.mybatisflex.core.query.QueryTable; 021import com.mybatisflex.core.query.QueryWrapper; 022import com.mybatisflex.core.service.IService; 023import com.mybatisflex.core.table.TableInfo; 024import com.mybatisflex.core.table.TableInfoFactory; 025import com.mybatisflex.core.util.ClassUtil; 026import org.springframework.beans.factory.annotation.Autowired; 027 028/** 029 * <p>可缓存数据的 Service 实现类。 030 * 031 * <p>该实现类对缓存做了以下处理: 032 * 033 * <ul> 034 * <li>重写 {@link #saveOrUpdate(Object)} 方法,分别调用 {@link #save(Object)} 和 {@link #updateById(Object)} 035 * 方法,避免缓存无法更新造成数据不一致。 036 * <li>重写 {@link #query()} 方法,解决使用 {@link QueryWrapper#toSQL()} 作为缓存 037 * 的主键时,"SELECT * FROM" 后面没有表名的问题。 038 * </ul> 039 * 040 * @author 王帅 041 * @since 2023-05-30 042 */ 043public class CacheableServiceImpl<M extends BaseMapper<T>, T> implements IService<T> { 044 045 @Autowired 046 @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection") 047 protected M mapper; 048 049 /** 050 * {@inheritDoc} 051 */ 052 @Override 053 public BaseMapper<T> getMapper() { 054 return mapper; 055 } 056 057 /** 058 * {@inheritDoc} 059 */ 060 @Override 061 public boolean saveOrUpdate(T entity) { 062 TableInfo tableInfo = TableInfoFactory.ofEntityClass(entity.getClass()); 063 Object[] pkArgs = tableInfo.buildPkSqlArgs(entity); 064 if (pkArgs.length == 0 || pkArgs[0] == null) { 065 return save(entity); 066 } else { 067 return updateById(entity); 068 } 069 } 070 071 /** 072 * <p>获取默认的 {@link QueryWrapper}。 073 * 074 * <p>使用 {@link QueryWrapper#create()} 构建默认查询条件的时候, 075 * 要使用 {@link QueryWrapper#from(String...)} 方法指定从哪个表 076 * 查询数据,不然使用 {@link QueryWrapper#toSQL()} 生成的 077 * SQL 语句就是 {@code "SELECT * FROM"},没有表名信息。 078 * 079 * <p>默认通过反射获取表名,建议重写,根据情况设置默认表名,以提升效率。 080 * 081 * <p>例如: 082 * 083 * <pre>{@code 084 * @Override 085 * public QueryWrapper query() { 086 * return QueryWrapper.create().from(ACCOUNT); 087 * } 088 * }</pre> 089 * 090 * @return 默认的 {@link QueryWrapper} 091 */ 092 @Override 093 public QueryWrapper query() { 094 Class<?> mapperClass = ClassUtil.getUsefulClass(getMapper().getClass()); 095 TableInfo tableInfo = TableInfoFactory.ofMapperClass(mapperClass); 096 return QueryWrapper.create().from(new QueryTable(tableInfo.getSchema(), tableInfo.getTableName())); 097 } 098 099}