
com.moon.data.identifier.IdentifierUtil Maven / Gradle / Ivy
package com.moon.data.identifier;
import com.moon.core.lang.ClassUtil;
import com.moon.core.lang.StringUtil;
import com.moon.core.lang.reflect.ConstructorUtil;
import com.moon.core.util.SetUtil;
import com.moon.core.util.TypeUtil;
import com.moon.core.util.converter.TypeCaster;
import com.moon.data.IdentifierGenerator;
import com.moon.data.Record;
import com.moon.spring.data.jpa.JpaRecord;
import com.moon.spring.data.jpa.factory.AbstractRepositoryImpl;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.BiFunction;
/**
* @author moonsky
*/
@SuppressWarnings("all")
public class IdentifierUtil {
private final static String packageName = IdentifierUtil.class.getPackage().getName();
private final static Set USED_IDENTIFIER_TYPES = new HashSet<>();
protected IdentifierUtil() { }
private static void assertNot(String classname, Class> type) {
if (type.getName().equals(classname)) {
throw new IllegalStateException("不允许:" + classname);
}
}
private static String assertClassname(String classname) {
assertNot(classname, IdentifierUtil.class);
return classname;
}
private static Class toClassOrNull(String classname) {
return ClassUtil.forNameOrNull(assertClassname(classname));
}
private static Class toIdentifierClass(String classname) {
// 类全名
Class type = toClassOrNull(classname);
if (type == null) {
// 类简写
classname = packageName + "." + classname;
type = toClassOrNull(classname);
}
if (type == null) {
// 省略后缀的简写
classname = classname + "Identifier";
type = toClassOrNull(classname);
}
return Objects.requireNonNull(type);
}
/*
* **********************************************************************************************
* * default methods ****************************************************************************
* **********************************************************************************************
*/
/**
* 这是给缓存主键用的,KEY 是将要保存对象的内存地址,VALUE 是对象预设的 ID 值
*
* {@link AbstractRepositoryImpl#persist(JpaRecord)}这个方法是给手动设置主键用的
*
* 手动设置的主键值会先缓存在这里,并设为 null,后续通过 IdentifierGenerator 获取主键时,
*
* 通过{@link #returnIfRecordIdNotEmpty(Object, Object, BiFunction)}优先获取预设的主键
*
*
* 一般预设主键都是极少数情况,也不建议这样做,通常也只是在启动时添加一些基础数据等,此种情况系统基本处于稳定状态
*
* 整个系统运行期间也不会很多,故这里未考虑超大数据量、并发以及异常(异常会产生少量垃圾数据堆积)等情况,如确有必要,请自行处理
*/
private final static Map temporaryIdMap = new ConcurrentHashMap<>();
protected final static > T putRecordPresetPrimaryKey(T record) {
if (record != null) {
Object id = record.getId();
if (id instanceof CharSequence) {
if (!id.toString().isEmpty()) {
temporaryIdMap.put(System.identityHashCode(record), id);
record.setId(null);
}
} else if (id != null) {
temporaryIdMap.put(System.identityHashCode(record), id);
record.setId(null);
}
}
return record;
}
private final static Object obtainRecordId(Object entity) {
return temporaryIdMap.remove(System.identityHashCode(entity));
}
/**
* 当 Record 字符串形式主键不为空(null或 "")时返回已存在的主键,否则按主键策略生成主键
*
* @param entity
* @param o
* @param generator
*
* @return
*/
protected final static ID returnIfRecordIdNotEmpty(
Object entity, METADATA o, BiFunction