编写实体类工具类,通过表名注解的值获取实体类以及主键字段
场景:执行动态sql,只知道表名,需要通过动态表名获取动态实体类以及动态主键字段
如下图所示,需要通过①获取到②和③

思路:项目启动的时候,清空相关redis缓存。扫描到所有实体类,通过反射获取到表名、实体类、主键等信息,将其存入redis方便后续获取。
工具类代码如下
import com.cenboomh.basicframework.utils.json.JacksonUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.core.io.Resource; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.core.type.classreading.CachingMetadataReaderFactory; import org.springframework.core.type.classreading.MetadataReader; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Component; import javax.persistence.Column; import javax.persistence.Id; import javax.persistence.Table; import java.util.HashMap; import java.util.Map; import java.util.Set; /** * 实体类工具类 * 通过表名获取实体类和主键 * * @author xiaomaju */ @Slf4j @Component public class MqmEntityUtils implements ApplicationRunner { @Autowired private StringRedisTemplate stringRedisTemplate; private static final String REDIS_ENTITY_KEY_PREFIX = "mqm:entity:"; private static final String REDIS_TABLE_CLASS_KEY = REDIS_ENTITY_KEY_PREFIX + "table:class:map"; private static final String REDIS_TABLE_PK_KEY = REDIS_ENTITY_KEY_PREFIX + "table:pk:map"; private static final String CLASS_PATTERN = "classpath*:com/xmj/**/*Entity.class"; @Override public void run(ApplicationArguments args) { refreshCache(); } /** * 初始化缓存 */ private void initializeCache() { try { // 先删除旧的缓存 Set<String> keys = stringRedisTemplate.keys(REDIS_ENTITY_KEY_PREFIX + "*"); if (keys != null && !keys.isEmpty()) { stringRedisTemplate.delete(keys); log.info("已删除旧的实体类缓存"); } Map<String, String> tableClassMap = new HashMap<>(); Map<String, String> tablePkMap = new HashMap<>(); PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); CachingMetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(resolver); Resource[] resources = resolver.getResources(CLASS_PATTERN); for (Resource resource : resources) { MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(resource); String className = metadataReader.getClassMetadata().getClassName(); Class<?> clazz = Class.forName(className); Table tableAnnotation = clazz.getAnnotation(Table.class); if (tableAnnotation != null) { String tableName = tableAnnotation.name().toUpperCase(); tableClassMap.put(tableName, className); // 查找主键字段 java.lang.reflect.Field[] fields = clazz.getDeclaredFields(); for (java.lang.reflect.Field field : fields) { if (field.isAnnotationPresent(Id.class)) { Column column = field.getAnnotation(Column.class); if (column != null) { tablePkMap.put(tableName, column.name()); } break; } } } } // 将映射信息存入Redis(永不过期) stringRedisTemplate.opsForValue().set( REDIS_TABLE_CLASS_KEY, JacksonUtil.writeValueAsString(tableClassMap) ); stringRedisTemplate.opsForValue().set( REDIS_TABLE_PK_KEY, JacksonUtil.writeValueAsString(tablePkMap) ); log.info("实体类缓存初始化完成,共缓存{}个实体类", tableClassMap.size()); } catch (Exception e) { log.error("初始化实体类缓存失败", e); } } /** * 根据表名获取实体类 * * @param tableName 表名 * @return 实体类 */ public Class<?> getEntityByTableName(String tableName) { if (StringUtils.isBlank(tableName)) { return null; } try { String tableClassMapJson = stringRedisTemplate.opsForValue().get(REDIS_TABLE_CLASS_KEY); if (StringUtils.isNotBlank(tableClassMapJson)) { Map<String, String> tableClassMap = JacksonUtil.readValue(tableClassMapJson, Map.class); String className = tableClassMap.get(tableName.toUpperCase()); if (StringUtils.isNotBlank(className)) { return Class.forName(className); } } } catch (Exception e) { log.error("获取实体类失败, tableName: {}", tableName, e); } return null; } /** * 根据表名获取主键字段名 * * @param tableName 表名 * @return 主键字段名 */ public String getPrimaryKeyColumn(String tableName) { if (StringUtils.isBlank(tableName)) { return null; } try { String tablePkMapJson = stringRedisTemplate.opsForValue().get(REDIS_TABLE_PK_KEY); if (StringUtils.isNotBlank(tablePkMapJson)) { Map<String, String> tablePkMap = JacksonUtil.readValue(tablePkMapJson, Map.class); return tablePkMap.get(tableName.toUpperCase()); } } catch (Exception e) { log.error("获取主键字段失败, tableName: {}", tableName, e); } return null; } /** * 刷新缓存 */ public void refreshCache() { initializeCache(); } }
启动本地服务,接口测试效果如下

浙公网安备 33010602011771号