(非常感谢)https://blog.csdn.net/weixin_42687829/article/details/103289383
小公司新项目加上本人也就两个开发,很多地方用到了字典,于是在网上参考一篇数据字典翻译类,自己记录一下,方便之后项目用到使用。
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @Author: Yin XX
* @Description:
* @Date: Create in 11:33 2020/4/30
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Dict {
/**
* 方法描述:数据dataSource
* @return 返回类型: String
*/
String dictDataSource();
/**
* 方法描述:这是返回后Put到josn中的文本key值
* @return 返回类型: String
*/
String dictText() default "";
}
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.renren.common.annotation.Dict;
import io.renren.common.utils.ObjConvertUtils;
import io.renren.common.utils.PageUtils;
import io.renren.modules.dictionaries.service.DictionariesService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* @Author: Yin XX
* @Description:
* @Date: Create in 11:26 2020/4/30
*/
@Aspect
@Component
@Slf4j
public class DictAspect {
//表对应字段加上_dictText即可显示出文本
private static String DICT_TEXT_SUFFIX = "_dictText";
@Autowired
private DictionariesService dataItemService;
//定义切点Pointcut拦截所有对服务器的请求
@Pointcut("execution(* io.renren.modules.*.service.*.*(..))")
public void excudeService() {
}
/**
* 这是触发DictionariesService的时候会执行的,在环绕通知中目标对象方法被调用后的结果进行再处理
* @param pjp
* @return
* @throws Throwable
*/
@Around("excudeService()")
public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
//这是定义开始事件
long time1 = System.currentTimeMillis();
//这是方法并获取返回结果
Object result = pjp.proceed();
//这是获取到结束时间
long time2 = System.currentTimeMillis();
log.info("获取JSON数据耗时:" + (time2 - time1) + "ms");
//解析开始时间
long start = System.currentTimeMillis();
//开始解析(翻译字段内部的值凡是打了@Dict这玩意的都会被翻译)
this.parseDictText(result);
//解析结束时间
long end = System.currentTimeMillis();
log.info("解析注入JSON数据耗时:" + (end - start) + "ms");
return result;
}
private void parseDictText(Object result) {
if (result instanceof PageUtils) {
List<JSONObject> items = new ArrayList<>();
PageUtils pageUtils = (PageUtils) result;
//循环查找出来的数据
for (Object record : pageUtils.getList()) {
ObjectMapper mapper = new ObjectMapper();
String json = "{}";
try {
//解决@JsonFormat注解解析不了的问题详见SysAnnouncement类的@JsonFormat
json = mapper.writeValueAsString(record);
} catch (JsonProcessingException e) {
log.error("Json解析失败:" + e);
}
JSONObject item = JSONObject.parseObject(json);
//解决继承实体字段无法翻译问题
for (Field field : ObjConvertUtils.getAllFields(record)) {
//解决继承实体字段无法翻译问题
if (field.getAnnotation(Dict.class) != null) {
//如果该属性上面有@Dict注解,则进行翻译
String datasource = field.getAnnotation(Dict.class).dictDataSource();//拿到注解的dictDataSource属性的值
String text = field.getAnnotation(Dict.class).dictText();//拿到注解的dictText属性的值
//获取当前带翻译的值
String key = String.valueOf(item.get(field.getName()));
//翻译字典值对应的text值
String textValue = translateDictValue(datasource, key);
//DICT_TEXT_SUFFIX的值为,是默认值:
//public static final String DICT_TEXT_SUFFIX = "_dictText";
log.debug("字典Val: " + textValue);
log.debug("翻译字典字段:" + field.getName() + DICT_TEXT_SUFFIX + ": " + textValue);
//如果给了文本名
if (!StringUtils.isBlank(text)) {
item.put(text, textValue);
} else {
//走默认策略
item.put(field.getName() + DICT_TEXT_SUFFIX, textValue);
}
}
//date类型默认转换string格式化日期
if (field.getType().getName().equals("java.util.Date") && field.getAnnotation(JsonFormat.class) == null && item.get(field.getName()) != null) {
SimpleDateFormat aDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
item.put(field.getName(), aDate.format(new Date((Long) item.get(field.getName()))));
}
}
items.add(item);
}
pageUtils.setList(items);
}
}
/**
* 翻译字典文本
* @param datasource
* @param key
* @return
*/
private String translateDictValue(String datasource, String key) {
//如果key为空直接返回就好了
if (ObjConvertUtils.isEmpty(key)) {
return null;
}
StringBuffer textValue = new StringBuffer();
//分割key值
String[] keys = key.split(",");
//循环keys中的所有值
for (String k : keys) {
String tmpValue = null;
log.debug("字典key:" + k);
if (k.trim().length() == 0) {
continue;//跳过循环
}
tmpValue = dataItemService.selectByFieldNameAndFieldValue(datasource, k.trim());
if (tmpValue != null) {
if (!"".equals(textValue.toString())) {
textValue.append(",");
}
textValue.append(tmpValue);
}
}
//返回翻译的值
return textValue.toString();
}
}
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @Author: Yin xx
* @Description:
* @Date: Create in 11:38 2020/4/30
*/
public class ObjConvertUtils {
/**
* 获取类的所有属性,包括父类
* @param object
* @return
*/
public static Field[] getAllFields(Object object) {
Class<?> clazz = object.getClass();
List<Field> fieldList = new ArrayList<>();
while (clazz != null) {
fieldList.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields())));
clazz = clazz.getSuperclass();
}
Field[] fields = new Field[fieldList.size()];
fieldList.toArray(fields);
return fields;
}
public static boolean isEmpty(Object object) {
if (object == null) {
return (true);
}
if ("".equals(object)) {
return (true);
}
if ("null".equals(object)) {
return (true);
}
return (false);
}
}
/**
* Copyright (c) 2016-2019 人人开源 All rights reserved.
*
* https://www.renren.io
*
* 版权所有,侵权必究!
*/
package io.renren.common.utils;
import com.baomidou.mybatisplus.core.metadata.IPage;
import java.io.Serializable;
import java.util.List;
/**
* 分页工具类
*
* @author Mark [email protected]
*/
public class PageUtils implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 总记录数
*/
private int totalCount;
/**
* 每页记录数
*/
private int pageSize;
/**
* 总页数
*/
private int totalPage;
/**
* 当前页数
*/
private int currPage;
/**
* 列表数据
*/
private List<?> list;
/**
* 分页
* @param list 列表数据
* @param totalCount 总记录数
* @param pageSize 每页记录数
* @param currPage 当前页数
*/
public PageUtils(List<?> list, int totalCount, int pageSize, int currPage) {
this.list = list;
this.totalCount = totalCount;
this.pageSize = pageSize;
this.currPage = currPage;
this.totalPage = (int)Math.ceil((double)totalCount/pageSize);
}
/**
* 分页
*/
public PageUtils(IPage<?> page) {
this.list = page.getRecords();
this.totalCount = (int)page.getTotal();
this.pageSize = (int)page.getSize();
this.currPage = (int)page.getCurrent();
this.totalPage = (int)page.getPages();
}
public int getTotalCount() {
return totalCount;
}
public void setTotalCount(int totalCount) {
this.totalCount = totalCount;
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public int getTotalPage() {
return totalPage;
}
public void setTotalPage(int totalPage) {
this.totalPage = totalPage;
}
public int getCurrPage() {
return currPage;
}
public void setCurrPage(int currPage) {
this.currPage = currPage;
}
public List<?> getList() {
return list;
}
public void setList(List<?> list) {
this.list = list;
}
}
import com.baomidou.mybatisplus.extension.service.IService;
import io.renren.common.utils.PageUtils;
import io.renren.modules.dictionaries.entity.DictionariesEntity;
import org.springframework.cache.annotation.Cacheable;
import java.util.Map;
/**
* @Author: Yin xx
* @Description:
* @Date: Create in 16:06 2020/4/29
*/
public interface DictionariesService extends IService<DictionariesEntity> {
/**
* 列表查询
* @param params
* @return
*/
PageUtils queryPage(Map<String, Object> params);
/**
* 将查询出来的字段存放在缓存中
* @param fieldName
* @param fieldValue
* @return
*/
@Cacheable(value = "dictEhcache") //把数据缓存到本地
String selectByFieldNameAndFieldValue(String fieldName,String fieldValue);
}
@Override
public String selectByFieldNameAndFieldValue(String fieldName, String fieldValue) {
DictionariesEntity entity = this.baseMapper.selectByFieldNameAndFieldValue(fieldName, fieldValue);
if(entity ==null){
return "无翻译词汇";
}
return entity.getFieldDetail();
}
==============================分割线,以下是SQL=================================================
<!--通过表格字段名和字段值查询该字典信息-->
<select id="selectByFieldNameAndFieldValue" parameterType="java.lang.String"
resultType="io.renren.modules.dictionaries.entity.DictionariesEntity">
SELECT * FROM pz_dictionaries
<where>
<if test="fieldName != null and fieldName !=''">
field_name = #{
fieldName}
</if>
<if test="fieldValue != null and fieldValue !=''">
and field_value = #{
fieldValue}
</if>
</where>
</select>
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.io.Serializable;
/**
* @Author: Yin xx
* @Description: 数据字典表
* @Date: Create in 16:11 2020/4/29
*/
@Data
@TableName("pz_dictionaries")
public class DictionariesEntity implements Serializable {
/**
* 字段唯一标识
*/
@TableId(value = "id",type = IdType.UUID)
private String id;
/**
* 字段名
*/
@TableField("field_name")
private String fieldName;
/**
* 字段值
*/
@TableField("field_value")
private String fieldValue;
/**
* 字段说明
*/
@TableField("field_detail")
private String fieldDetail;
/**
* 具体描述
*/
@TableField("field_describe")
private String fieldDescribe;
}
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="./config/ehcache.xsd"
updateCheck="false">
<!--这个是磁盘存储路径,当内存缓存满了的时候,就会往这里面放,java.io.tmdir是操作系统缓存的临时目录,不同操作系统缓存目录不一样。-->
<diskStore path="D:/ehcacheData"/>
<!--maxElementsInMemory 内存缓存中最多可以存放的元素数量,若放入Cache中的元素超过这个数值,则有以下两种情况
1)若overflowToDisk=true,则会将Cache中多出的元素放入磁盘文件中
2)若overflowToDisk=false,则根据memoryStoreEvictionPolicy策略替换Cache中原有的元素overflowToDisk,
内存不足时,是否启用磁盘缓存-->
<!--eternal:缓存中对象是否永久有效-->
<!--timeToIdleSeconds:缓存数据在失效前的允许闲置时间(单位:秒),仅当eternal=false时使用,
默认值是0表示可闲置时间无穷大,若超过这个时间没有访问此Cache中的某个元素,那么此元素将被从Cache中清除-->
<!--timeToLiveSeconds:缓存数据的总的存活时间(单位:秒),仅当eternal=false时使用,从创建开始计时,失效结束。-->
<!--maxElementsOnDisk:磁盘缓存中最多可以存放的元素数量,0表示无穷大-->
<defaultCache
eternal="false"
maxElementsInMemory="10000"
overflowToDisk="false"
diskPersistent="false"
timeToIdleSeconds="600"
timeToLiveSeconds="600"
maxElementsOnDisk="10000000"
memoryStoreEvictionPolicy="LRU" />
<!-- 这里的 dictEhcache 缓存空间是为了缓存字典数据做准备 -->
<cache
name="dictEhcache"
eternal="false"
maxElementsInMemory="1000"
overflowToDisk="false"
diskPersistent="false"
timeToIdleSeconds="600"
timeToLiveSeconds="600"
memoryStoreEvictionPolicy="LRU" />
</ehcache>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" version="1.7">
<xs:element name="ehcache">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="1" minOccurs="0" ref="diskStore"/>
<xs:element maxOccurs="1" minOccurs="0" ref="sizeOfPolicy"/>
<xs:element maxOccurs="1" minOccurs="0" ref="transactionManagerLookup"/>
<xs:element maxOccurs="1" minOccurs="0" ref="cacheManagerEventListenerFactory"/>
<xs:element maxOccurs="1" minOccurs="0" ref="managementRESTService"/>
<xs:element maxOccurs="unbounded" minOccurs="0" ref="cacheManagerPeerProviderFactory"/>
<xs:element maxOccurs="unbounded" minOccurs="0" ref="cacheManagerPeerListenerFactory"/>
<xs:element maxOccurs="1" minOccurs="0" ref="terracottaConfig"/>
<xs:element maxOccurs="1" minOccurs="0" ref="defaultCache"/>
<xs:element maxOccurs="unbounded" minOccurs="0" ref="cache"/>
</xs:sequence>
<xs:attribute name="name" use="optional"/>
<xs:attribute default="true" name="updateCheck" type="xs:boolean" use="optional"/>
<xs:attribute default="autodetect" name="monitoring" type="monitoringType" use="optional"/>
<xs:attribute default="true" name="dynamicConfig" type="xs:boolean" use="optional"/>
<xs:attribute default="15" name="defaultTransactionTimeoutInSeconds" type="xs:integer" use="optional"/>
<xs:attribute default="0" name="maxBytesLocalHeap" type="memoryUnitOrPercentage" use="optional"/>
<xs:attribute default="0" name="maxBytesLocalOffHeap" type="memoryUnit" use="optional"/>
<xs:attribute default="0" name="maxBytesLocalDisk" type="memoryUnit" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="managementRESTService">
<xs:complexType>
<xs:attribute name="enabled" type="xs:boolean" use="optional"/>
<xs:attribute name="bind" use="optional"/>
<xs:attribute name="securityServiceLocation" use="optional"/>
<xs:attribute name="securityServiceTimeout" use="optional" type="xs:integer"/>
<xs:attribute name="sslEnabled" use="optional" type="xs:boolean"/>
<xs:attribute name="needClientAuth" use="optional" type="xs:boolean"/>
<xs:attribute name="sampleHistorySize" use="optional" type="xs:integer"/>
<xs:attribute name="sampleIntervalSeconds" use="optional" type="xs:integer"/>
<xs:attribute name="sampleSearchIntervalSeconds" use="optional" type="xs:integer"/>
</xs:complexType>
</xs:element>
<xs:element name="diskStore">
<xs:complexType>
<xs:attribute name="path" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="transactionManagerLookup">
<xs:complexType>
<xs:attribute name="class" use="required"/>
<xs:attribute name="properties" use="optional"/>
<xs:attribute name="propertySeparator" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="cacheManagerEventListenerFactory">
<xs:complexType>
<xs:attribute name="class" use="required"/>
<xs:attribute name="properties" use="optional"/>
<xs:attribute name="propertySeparator" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="cacheManagerPeerProviderFactory">
<xs:complexType>
<xs:attribute name="class" use="required"/>
<xs:attribute name="properties" use="optional"/>
<xs:attribute name="propertySeparator" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="cacheManagerPeerListenerFactory">
<xs:complexType>
<xs:attribute name="class" use="required"/>
<xs:attribute name="properties" use="optional"/>
<xs:attribute name="propertySeparator" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="terracottaConfig">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="1" minOccurs="0" name="tc-config">
<xs:complexType>
<xs:sequence>
<xs:any maxOccurs="unbounded" minOccurs="0" processContents="skip"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute default="localhost:9510" name="url" use="optional"/>
<xs:attribute name="rejoin" type="xs:boolean" use="optional" default="false"/>
<xs:attribute name="wanEnabledTSA" type="xs:boolean" use="optional" default="false"/>
</xs:complexType>
</xs:element>
<!--
add clone support for addition of cacheExceptionHandler. Important!
-->
<xs:element name="defaultCache">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="unbounded" ref="cacheEventListenerFactory"/>
<xs:element minOccurs="0" maxOccurs="unbounded" ref="cacheExtensionFactory"/>
<xs:element minOccurs="0" maxOccurs="unbounded" ref="cacheLoaderFactory"/>
<xs:element minOccurs="0" maxOccurs="unbounded" ref="cacheDecoratorFactory"/>
<xs:element minOccurs="0" maxOccurs="1" ref="bootstrapCacheLoaderFactory"/>
<xs:element minOccurs="0" maxOccurs="1" ref="cacheExceptionHandlerFactory"/>
<xs:element minOccurs="0" maxOccurs="1" ref="pinning"/>
<xs:element minOccurs="0" maxOccurs="1" ref="terracotta"/>
<xs:element minOccurs="0" maxOccurs="1" ref="cacheWriter"/>
<xs:element minOccurs="0" maxOccurs="1" ref="copyStrategy"/>
<xs:element minOccurs="0" maxOccurs="1" ref="elementValueComparator"/>
<xs:element minOccurs="0" maxOccurs="1" ref="sizeOfPolicy"/>
<xs:element minOccurs="0" maxOccurs="1" ref="persistence"/>
</xs:sequence>
<xs:attribute name="diskExpiryThreadIntervalSeconds" type="xs:integer" use="optional"/>
<xs:attribute name="diskSpoolBufferSizeMB" type="xs:integer" use="optional"/>
<xs:attribute name="diskPersistent" type="xs:boolean" use="optional"/>
<xs:attribute name="diskAccessStripes" type="xs:integer" use="optional" default="1"/>
<xs:attribute name="eternal" type="xs:boolean" use="optional" default="false"/>
<xs:attribute name="maxElementsInMemory" type="xs:nonNegativeInteger" use="optional"/>
<xs:attribute name="maxEntriesLocalHeap" type="xs:nonNegativeInteger" use="optional"/>
<xs:attribute name="clearOnFlush" type="xs:boolean" use="optional"/>
<xs:attribute name="memoryStoreEvictionPolicy" type="xs:string" use="optional"/>
<xs:attribute name="overflowToDisk" type="xs:boolean" use="optional"/>
<xs:attribute name="timeToIdleSeconds" type="xs:nonNegativeInteger" use="optional"/>
<xs:attribute name="timeToLiveSeconds" type="xs:nonNegativeInteger" use="optional"/>
<xs:attribute name="maxElementsOnDisk" type="xs:nonNegativeInteger" use="optional"/>
<xs:attribute name="maxEntriesLocalDisk" type="xs:nonNegativeInteger" use="optional"/>
<xs:attribute name="transactionalMode" type="transactionalMode" use="optional" default="off"/>
<xs:attribute name="statistics" type="xs:boolean" use="optional" default="false"/>
<xs:attribute name="copyOnRead" type="xs:boolean" use="optional" default="false"/>
<xs:attribute name="copyOnWrite" type="xs:boolean" use="optional" default="false"/>
<xs:attribute name="cacheLoaderTimeoutMillis" type="xs:integer" use="optional" default="0"/>
<xs:attribute name="overflowToOffHeap" type="xs:boolean" use="optional" default="false"/>
<xs:attribute name="maxMemoryOffHeap" type="xs:string" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="cache">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="unbounded" ref="cacheEventListenerFactory"/>
<xs:element minOccurs="0" maxOccurs="unbounded" ref="cacheExtensionFactory"/>
<xs:element minOccurs="0" maxOccurs="unbounded" ref="cacheLoaderFactory"/>
<xs:element minOccurs="0" maxOccurs="unbounded" ref="cacheDecoratorFactory"/>
<xs:element minOccurs="0" maxOccurs="1" ref="bootstrapCacheLoaderFactory"/>
<xs:element minOccurs="0" maxOccurs="1" ref="cacheExceptionHandlerFactory"/>
<xs:element minOccurs="0" maxOccurs="1" ref="pinning"/>
<xs:element minOccurs="0" maxOccurs="1" ref="terracotta"/>
<xs:element minOccurs="0" maxOccurs="1" ref="cacheWriter"/>
<xs:element minOccurs="0" maxOccurs="1" ref="copyStrategy"/>
<xs:element minOccurs="0" maxOccurs="1" ref="searchable"/>
<xs:element minOccurs="0" maxOccurs="1" ref="elementValueComparator"/>
<xs:element minOccurs="0" maxOccurs="1" ref="sizeOfPolicy"/>
<xs:element minOccurs="0" maxOccurs="1" ref="persistence"/>
</xs:sequence>
<xs:attribute name="diskExpiryThreadIntervalSeconds" type="xs:integer" use="optional"/>
<xs:attribute name="diskSpoolBufferSizeMB" type="xs:integer" use="optional"/>
<xs:attribute name="diskPersistent" type="xs:boolean" use="optional"/>
<xs:attribute name="diskAccessStripes" type="xs:integer" use="optional" default="1"/>
<xs:attribute name="eternal" type="xs:boolean" use="optional" default="false"/>
<xs:attribute name="maxElementsInMemory" type="xs:nonNegativeInteger" use="optional"/>
<xs:attribute name="maxEntriesLocalHeap" type="xs:nonNegativeInteger" use="optional"/>
<xs:attribute name="memoryStoreEvictionPolicy" type="xs:string" use="optional"/>
<xs:attribute name="clearOnFlush" type="xs:boolean" use="optional"/>
<xs:attribute name="name" type="xs:string" use="required"/>
<xs:attribute name="overflowToDisk" type="xs:boolean" use="optional"/>
<xs:attribute name="timeToIdleSeconds" type="xs:nonNegativeInteger" use="optional"/>
<xs:attribute name="timeToLiveSeconds" type="xs:nonNegativeInteger" use="optional"/>
<xs:attribute name="maxElementsOnDisk" type="xs:nonNegativeInteger" use="optional"/>
<xs:attribute name="maxEntriesLocalDisk" type="xs:nonNegativeInteger" use="optional"/>
<xs:attribute name="maxEntriesInCache" type="xs:nonNegativeInteger" use="optional"/>
<xs:attribute name="transactionalMode" type="transactionalMode" use="optional" default="off"/>
<xs:attribute name="statistics" type="xs:boolean" use="optional" default="false"/>
<xs:attribute name="copyOnRead" type="xs:boolean" use="optional" default="false"/>
<xs:attribute name="copyOnWrite" type="xs:boolean" use="optional" default="false"/>
<xs:attribute name="logging" type="xs:boolean" use="optional" default="false"/>
<xs:attribute name="cacheLoaderTimeoutMillis" type="xs:integer" use="optional" default="0"/>
<xs:attribute name="overflowToOffHeap" type="xs:boolean" use="optional" default="false"/>
<xs:attribute name="maxMemoryOffHeap" type="xs:string" use="optional"/>
<xs:attribute default="0" name="maxBytesLocalHeap" type="memoryUnitOrPercentage" use="optional"/>
<xs:attribute default="0" name="maxBytesLocalOffHeap" type="memoryUnitOrPercentage" use="optional"/>
<xs:attribute default="0" name="maxBytesLocalDisk" type="memoryUnitOrPercentage" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="cacheEventListenerFactory">
<xs:complexType>
<xs:attribute name="class" use="required"/>
<xs:attribute name="properties" use="optional"/>
<xs:attribute name="propertySeparator" use="optional"/>
<xs:attribute name="listenFor" use="optional" type="notificationScope" default="all"/>
</xs:complexType>
</xs:element>
<xs:element name="bootstrapCacheLoaderFactory">
<xs:complexType>
<xs:attribute name="class" use="required"/>
<xs:attribute name="properties" use="optional"/>
<xs:attribute name="propertySeparator" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="cacheExtensionFactory">
<xs:complexType>
<xs:attribute name="class" use="required"/>
<xs:attribute name="properties" use="optional"/>
<xs:attribute name="propertySeparator" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="cacheExceptionHandlerFactory">
<xs:complexType>
<xs:attribute name="class" use="required"/>
<xs:attribute name="properties" use="optional"/>
<xs:attribute name="propertySeparator" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="cacheLoaderFactory">
<xs:complexType>
<xs:attribute name="class" use="required"/>
<xs:attribute name="properties" use="optional"/>
<xs:attribute name="propertySeparator" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="cacheDecoratorFactory">
<xs:complexType>
<xs:attribute name="class" use="required"/>
<xs:attribute name="properties" use="optional"/>
<xs:attribute name="propertySeparator" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="searchAttribute">
<xs:complexType>
<xs:attribute name="name" use="required" type="xs:string"/>
<xs:attribute name="expression" type="xs:string"/>
<xs:attribute name="class" type="xs:string"/>
<xs:attribute name="type" type="xs:string" use="optional"/>
<xs:attribute name="properties" use="optional"/>
<xs:attribute name="propertySeparator" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="searchable">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="unbounded" ref="searchAttribute"/>
</xs:sequence>
<xs:attribute name="keys" use="optional" type="xs:boolean" default="true"/>
<xs:attribute name="values" use="optional" type="xs:boolean" default="true"/>
<xs:attribute name="allowDynamicIndexing" use="optional" type="xs:boolean" default="false"/>
</xs:complexType>
</xs:element>
<xs:element name="pinning">
<xs:complexType>
<xs:attribute name="store" use="required" type="pinningStoreType"/>
</xs:complexType>
</xs:element>
<xs:element name="terracotta">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="1" ref="nonstop"/>
</xs:sequence>
<xs:attribute name="clustered" use="optional" type="xs:boolean" default="true"/>
<xs:attribute name="coherentReads" use="optional" type="xs:boolean" default="true"/>
<xs:attribute name="localKeyCache" use="optional" type="xs:boolean" default="false"/>
<xs:attribute name="localKeyCacheSize" use="optional" type="xs:positiveInteger" default="300000"/>
<xs:attribute name="orphanEviction" use="optional" type="xs:boolean" default="true"/>
<xs:attribute name="orphanEvictionPeriod" use="optional" type="xs:positiveInteger" default="4"/>
<xs:attribute name="copyOnRead" use="optional" type="xs:boolean" default="false"/>
<xs:attribute name="coherent" use="optional" type="xs:boolean" default="false"/>
<xs:attribute name="consistency" use="optional" type="consistencyType" default="eventual"/>
<xs:attribute name="synchronousWrites" use="optional" type="xs:boolean" default="false"/>
<xs:attribute name="concurrency" use="optional" type="xs:nonNegativeInteger" default="0"/>
<xs:attribute name="localCacheEnabled" use="optional" type="xs:boolean" default="true"/>
<xs:attribute name="compressionEnabled" use="optional" type="xs:boolean" default="false"/>
</xs:complexType>
</xs:element>
<xs:simpleType name="consistencyType">
<xs:restriction base="xs:string">
<xs:enumeration value="strong"/>
<xs:enumeration value="eventual"/>
</xs:restriction>
</xs:simpleType>
<xs:element name="nonstop">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="1" ref="timeoutBehavior"/>
</xs:sequence>
<xs:attribute name="enabled" use="optional" type="xs:boolean" default="true"/>
<xs:attribute name="immediateTimeout" use="optional" type="xs:boolean" default="false"/>
<xs:attribute name="timeoutMillis" use="optional" type="xs:positiveInteger" default="30000"/>
<xs:attribute name="searchTimeoutMillis" use="optional" type="xs:positiveInteger" default="30000"/>
</xs:complexType>
</xs:element>
<xs:element name="timeoutBehavior">
<xs:complexType>
<xs:attribute name="type" use="optional" type="timeoutBehaviorType" default="exception"/>
<xs:attribute name="properties" use="optional" default=""/>
<xs:attribute name="propertySeparator" use="optional" default=","/>
</xs:complexType>
</xs:element>
<xs:simpleType name="timeoutBehaviorType">
<xs:restriction base="xs:string">
<xs:enumeration value="noop"/>
<xs:enumeration value="exception"/>
<xs:enumeration value="localReads"/>
<xs:enumeration value="localReadsAndExceptionOnWrite"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="monitoringType">
<xs:restriction base="xs:string">
<xs:enumeration value="autodetect"/>
<xs:enumeration value="on"/>
<xs:enumeration value="off"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="pinningStoreType">
<xs:restriction base="xs:string">
<xs:enumeration value="localMemory"/>
<xs:enumeration value="inCache"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="terracottaCacheValueType">
<xs:restriction base="xs:string">
<xs:enumeration value="serialization"/>
<xs:enumeration value="identity"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="transactionalMode">
<xs:restriction base="xs:string">
<xs:enumeration value="off"/>
<xs:enumeration value="xa_strict"/>
<xs:enumeration value="xa"/>
<xs:enumeration value="local"/>
</xs:restriction>
</xs:simpleType>
<xs:element name="cacheWriter">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="1" ref="cacheWriterFactory"/>
</xs:sequence>
<xs:attribute name="writeMode" use="optional" type="writeModeType" default="write-through"/>
<xs:attribute name="notifyListenersOnException" use="optional" type="xs:boolean" default="false"/>
<xs:attribute name="minWriteDelay" use="optional" type="xs:nonNegativeInteger" default="1"/>
<xs:attribute name="maxWriteDelay" use="optional" type="xs:nonNegativeInteger" default="1"/>
<xs:attribute name="rateLimitPerSecond" use="optional" type="xs:nonNegativeInteger" default="0"/>
<xs:attribute name="writeCoalescing" use="optional" type="xs:boolean" default="false"/>
<xs:attribute name="writeBatching" use="optional" type="xs:boolean" default="false"/>
<xs:attribute name="writeBatchSize" use="optional" type="xs:positiveInteger" default="1"/>
<xs:attribute name="retryAttempts" use="optional" type="xs:nonNegativeInteger" default="0"/>
<xs:attribute name="retryAttemptDelaySeconds" use="optional" type="xs:nonNegativeInteger" default="1"/>
<xs:attribute name="writeBehindConcurrency" use="optional" type="xs:nonNegativeInteger" default="1"/>
<xs:attribute name="writeBehindMaxQueueSize" use="optional" type="xs:nonNegativeInteger" default="0"/>
</xs:complexType>
</xs:element>
<xs:simpleType name="writeModeType">
<xs:restriction base="xs:string">
<xs:enumeration value="write-through"/>
<xs:enumeration value="write-behind"/>
</xs:restriction>
</xs:simpleType>
<xs:element name="cacheWriterFactory">
<xs:complexType>
<xs:attribute name="class" use="required"/>
<xs:attribute name="properties" use="optional"/>
<xs:attribute name="propertySeparator" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="copyStrategy">
<xs:complexType>
<xs:attribute name="class" use="required" type="xs:string"/>
</xs:complexType>
</xs:element>
<xs:element name="elementValueComparator">
<xs:complexType>
<xs:attribute name="class" use="required" type="xs:string"/>
</xs:complexType>
</xs:element>
<xs:element name="sizeOfPolicy">
<xs:complexType>
<xs:attribute name="maxDepth" use="required" type="xs:integer"/>
<xs:attribute name="maxDepthExceededBehavior" use="optional" default="continue"
type="maxDepthExceededBehavior"/>
</xs:complexType>
</xs:element>
<xs:element name="persistence">
<xs:complexType>
<xs:attribute name="strategy" use="required" type="persistenceStrategy"/>
<xs:attribute name="synchronousWrites" use="optional" default="false" type="xs:boolean"/>
</xs:complexType>
</xs:element>
<xs:simpleType name="persistenceStrategy">
<xs:restriction base="xs:string">
<xs:enumeration value="localTempSwap"/>
<xs:enumeration value="localRestartable"/>
<xs:enumeration value="none"/>
<xs:enumeration value="distributed"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="maxDepthExceededBehavior">
<xs:restriction base="xs:string">
<xs:enumeration value="continue"/>
<xs:enumeration value="abort"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="notificationScope">
<xs:restriction base="xs:string">
<xs:enumeration value="local"/>
<xs:enumeration value="remote"/>
<xs:enumeration value="all"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="memoryUnit">
<xs:restriction base="xs:token">
<xs:pattern value="[0-9]+[bBkKmMgG]?"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="memoryUnitOrPercentage">
<xs:restriction base="xs:token">
<xs:pattern value="([0-9]+[bBkKmMgG]?|100%|[0-9]{1,2}%)"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>
/**
* 保存
* @param entity
* @return
*/
@RequestMapping("/save")
@RequiresPermissions("dictionaries:list")
@CacheEvict(value="dictEhcache", allEntries=true) //清空缓存
public R save(@RequestBody DictionariesEntity entity) {
String errMassage = "保存失败";
if(entity != null){
Map<String,Object> parMap = new HashMap<>();
parMap.put("field_name",entity.getFieldName());
parMap.put("field_value",entity.getFieldValue());
Collection<DictionariesEntity> collections = service.listByMap(parMap);
if(collections.size()==0){
boolean b = service.save(entity);
if (b) {
return R.ok();
}
}else {
errMassage="该表'字段名'和'字段码值'已存在";
}
}
return R.error().put("msg",errMassage);
}
pz_dictionaries表字段:
字段名 | 类型 | 备注 |
---|---|---|
id | varchar | uuid,唯一标识 |
field_name | varchar | 对应表格字段名 |
field_value | varchar | 字段值 |
field_detail | varchar | 字段说明 |
field_describe | varchar | 具体描述 |
/**
* 子任务状态
*/
@TableField("subtask_status")
@Dict(dictDataSource = "subtask_status")//需要翻译的实体类字段加上注解
private String subtaskStatus;
==============================前端样例======================================
<el-table-column
prop="subtaskStatus_dictText" //在字段后加上_dictText
header-align="center"
align="center"
label="子任务状态">
</el-table-column>