All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.yuweix.kuafu.sharding.utils.ShardingUtil Maven / Gradle / Ivy
package com.yuweix.kuafu.sharding.utils;
import com.yuweix.kuafu.sharding.annotation.Sharding;
import com.yuweix.kuafu.sharding.strategy.Strategy;
import javax.persistence.Column;
import javax.persistence.Id;
import javax.persistence.Table;
import java.lang.ref.SoftReference;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author yuwei
*/
public abstract class ShardingUtil {
private static SoftReference> TABLE_NAME_REF;
private static final Object tableNameLock = new Object();
private static SoftReference> SELECT_SQL_REF;
private static final Object selectSqlLock = new Object();
private static SoftReference> SELECT_SQL_WITH_TABLE_ALIAS_REF;
private static final Object selectSqlWithAliasLock = new Object();
private static SoftReference>> PERSIST_FIELD_REF;
private static final Object persistFieldLock = new Object();
private static SoftReference, Strategy>> SHARD_STRATEGY_REF;
private static final Object shardStrategyLock = new Object();
private static SoftReference, FieldCol>> CLASS_PK_FIELD_REF;
private static final Object classPkFieldLock = new Object();
private static SoftReference, FieldCol>> CLASS_SHARDING_FIELD_REF;
private static final Object classShardingFieldLock = new Object();
/**
* 驼峰转下划线
* @param str
* @return
*/
private static String toUnderline(String str) {
Pattern pattern = Pattern.compile("[A-Z]");
Matcher matcher = pattern.matcher(str);
StringBuffer buf = new StringBuffer(str);
if (!matcher.find()) {
return buf.toString();
}
buf = new StringBuffer();
matcher.appendReplacement(buf, "_" + matcher.group(0).toLowerCase());
matcher.appendTail(buf);
String res = toUnderline(buf.toString());
if (res.startsWith("_")) {
res = res.substring(1);
}
return res;
}
private static Map getTableNameMap() {
Map map = null;
if (TABLE_NAME_REF == null || (map = TABLE_NAME_REF.get()) == null) {
synchronized (tableNameLock) {
if (TABLE_NAME_REF == null || (map = TABLE_NAME_REF.get()) == null) {
map = new ConcurrentHashMap<>();
TABLE_NAME_REF = new SoftReference<>(map);
}
}
}
return map;
}
/**
* 根据持久化类获取对应的关系表表名。
* @param clz
* @return
*/
public static String getTableName(Class clz) {
String className = clz.getName();
Map map = getTableNameMap();
String tableName = map.get(className);
if (tableName == null) {
Table table = clz.getAnnotation(Table.class);
if (table != null && !"".equals(table.name().trim())) {
tableName = table.name().trim();
} else {
tableName = toUnderline(clz.getSimpleName());
if (tableName == null || "".equals(tableName)) {
throw new RuntimeException("Table name is not found.");
}
}
map.put(className, tableName);
}
return tableName;
}
public static class FieldCol {
private final String columnName;
private final Field field;
public FieldCol(String columnName, Field field) {
this.columnName = columnName;
this.field = field;
}
public String getColumnName() {
return columnName;
}
public Field getField() {
return field;
}
}
private static Map getSelectSqlMap() {
Map map = null;
if (SELECT_SQL_REF == null || (map = SELECT_SQL_REF.get()) == null) {
synchronized (selectSqlLock) {
if (SELECT_SQL_REF == null || (map = SELECT_SQL_REF.get()) == null) {
map = new ConcurrentHashMap<>();
SELECT_SQL_REF = new SoftReference<>(map);
}
}
}
return map;
}
/**
* 根据持久化类获取对应的所有需要持久化的属性SQL。
* eg:id as id, user_name as userName, create_time as createTime
* @param clz
* @return
*/
public static String getAllColumnSql(Class clz) {
String className = clz.getName();
Map map = getSelectSqlMap();
String selectSql = map.get(className);
if (selectSql == null) {
StringBuilder builder = new StringBuilder("");
List fcList = getPersistFieldList(clz);
for (int i = 0, size = fcList.size(); i < size; i++) {
FieldCol fc = fcList.get(i);
if (i > 0) {
builder.append(", ");
}
builder.append(fc.getColumnName()).append(" as ").append(fc.getField().getName());
}
selectSql = builder.toString();
map.put(className, selectSql);
}
return selectSql;
}
private static Map getSelectSqlWithTableAliasMap() {
Map map = null;
if (SELECT_SQL_WITH_TABLE_ALIAS_REF == null || (map = SELECT_SQL_WITH_TABLE_ALIAS_REF.get()) == null) {
synchronized (selectSqlWithAliasLock) {
if (SELECT_SQL_WITH_TABLE_ALIAS_REF == null || (map = SELECT_SQL_WITH_TABLE_ALIAS_REF.get()) == null) {
map = new ConcurrentHashMap<>();
SELECT_SQL_WITH_TABLE_ALIAS_REF = new SoftReference<>(map);
}
}
}
return map;
}
/**
* eg:a.id as id, a.user_name as userName, a.create_time as createTime
* @param clz
* @param tableAlias
* @return
*/
public static String getAllColumnSql(Class clz, String tableAlias) {
String key = clz.getName() + "_" + tableAlias;
Map map = getSelectSqlWithTableAliasMap();
String selectSql = map.get(key);
if (selectSql == null) {
StringBuilder builder = new StringBuilder("");
List fcList = getPersistFieldList(clz);
for (int i = 0, size = fcList.size(); i < size; i++) {
FieldCol fc = fcList.get(i);
if (i > 0) {
builder.append(", ");
}
builder.append(tableAlias).append(".").append(fc.getColumnName()).append(" as ").append(fc.getField().getName());
}
selectSql = builder.toString();
map.put(key, selectSql);
}
return selectSql;
}
private static Map> getPersistFieldMap() {
Map> map = null;
if (PERSIST_FIELD_REF == null || (map = PERSIST_FIELD_REF.get()) == null) {
synchronized (persistFieldLock) {
if (PERSIST_FIELD_REF == null || (map = PERSIST_FIELD_REF.get()) == null) {
map = new ConcurrentHashMap<>();
PERSIST_FIELD_REF = new SoftReference<>(map);
}
}
}
return map;
}
/**
* 根据持久化类获取对应的所有需要持久化的属性集合
* @param clz
* @return
*/
public static List getPersistFieldList(Class clz) {
String className = clz.getName();
Map> map = getPersistFieldMap();
List fcList = map.get(className);
if (fcList == null) {
fcList = getPersistFieldList0(clz);
map.put(className, fcList);
}
return fcList;
}
/**
* Gets all fields of the given class and its parents (if any).
* @return
*/
private static List getPersistFieldList0(Class clz) {
final List allFields = new ArrayList<>();
Class currentClass = clz;
while (currentClass != null) {
allFields.addAll(Arrays.asList(currentClass.getDeclaredFields()));
currentClass = currentClass.getSuperclass();
}
List list = new ArrayList<>();
for (Field field: allFields) {
Column column = field.getAnnotation(Column.class);
if (column == null) {
continue;
}
String colName = column.name();
if ("".equals(colName.trim())) {
colName = toUnderline(field.getName());
}
if (colName == null || "".equals(colName.trim())) {
continue;
}
list.add(new FieldCol(colName.trim(), field));
}
return list;
}
public static Object getFieldVal(Field field, Object t) {
if (!field.isAccessible()) {
field.setAccessible(true);
}
try {
return field.get(t);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
private static Map, Strategy> getShardStrategyMap() {
Map, Strategy> map = null;
if (SHARD_STRATEGY_REF == null || (map = SHARD_STRATEGY_REF.get()) == null) {
synchronized (shardStrategyLock) {
if (SHARD_STRATEGY_REF == null || (map = SHARD_STRATEGY_REF.get()) == null) {
map = new ConcurrentHashMap<>();
SHARD_STRATEGY_REF = new SoftReference<>(map);
}
}
}
return map;
}
public static String getPhysicalTableName(Sharding sharding, String tableName, Object shardingVal) {
if (sharding == null || shardingVal == null) {
return null;
}
Class strategyClz = sharding.strategy();
Map, Strategy> map = getShardStrategyMap();
Strategy strategy = map.get(strategyClz);
if (strategy == null) {
try {
strategy = strategyClz.getDeclaredConstructor().newInstance();
} catch (Exception e) {
throw new RuntimeException(e);
}
map.put(strategyClz, strategy);
}
return strategy.getPhysicalTableName(tableName, shardingVal);
}
public static String getPhysicalTableName(Class poClz, Object shardingVal) {
String tbName = getTableName(poClz);
List fcList = getPersistFieldList(poClz);
for (FieldCol fc: fcList) {
Field field = fc.getField();
Sharding sharding = field.getAnnotation(Sharding.class);
if (sharding != null) {
return getPhysicalTableName(sharding, tbName, shardingVal);
}
}
return tbName;
}
/**
* 获取指定持久化类的分库分表策略对象。
*/
public static Strategy getShardingStrategy(Class clz) {
FieldCol fieldCol = getShardingFieldCol(clz);
if (fieldCol == null) {
return null;
}
if (!fieldCol.getField().isAnnotationPresent(Sharding.class)) {
return null;
}
Sharding sharding = fieldCol.getField().getAnnotation(Sharding.class);
if (sharding == null) {
return null;
}
Class strategyClz = sharding.strategy();
Map, Strategy> map = getShardStrategyMap();
Strategy strategy = map.get(strategyClz);
if (strategy == null) {
try {
strategy = strategyClz.getDeclaredConstructor().newInstance();
} catch (Exception e) {
throw new RuntimeException(e);
}
map.put(strategyClz, strategy);
}
return strategy;
}
private static Map, FieldCol> getClassPkFieldMap() {
Map, FieldCol> map = null;
if (CLASS_PK_FIELD_REF == null || (map = CLASS_PK_FIELD_REF.get()) == null) {
synchronized (classPkFieldLock) {
if (CLASS_PK_FIELD_REF == null || (map = CLASS_PK_FIELD_REF.get()) == null) {
map = new ConcurrentHashMap<>();
CLASS_PK_FIELD_REF = new SoftReference<>(map);
}
}
}
return map;
}
public static FieldCol getPKFieldCol(Class clz) {
Map, FieldCol> map = getClassPkFieldMap();
FieldCol fc = map.get(clz);
if (fc == null) {
Field[] fields = clz.getDeclaredFields();
for (Field field: fields) {
field.setAccessible(true);
Id idAnn = field.getAnnotation(Id.class);
if (idAnn != null) {
Column col = field.getAnnotation(Column.class);
fc = new FieldCol(col == null ? field.getName() : col.name(), field);
map.put(clz, fc);
break;
}
}
}
return fc;
}
public static Field getPKField(Class clz) {
FieldCol fc = getPKFieldCol(clz);
return fc == null ? null : fc.getField();
}
private static Map, FieldCol> getClassShardingFieldMap() {
Map, FieldCol> map = null;
if (CLASS_SHARDING_FIELD_REF == null || (map = CLASS_SHARDING_FIELD_REF.get()) == null) {
synchronized (classShardingFieldLock) {
if (CLASS_SHARDING_FIELD_REF == null || (map = CLASS_SHARDING_FIELD_REF.get()) == null) {
map = new ConcurrentHashMap<>();
CLASS_SHARDING_FIELD_REF = new SoftReference<>(map);
}
}
}
return map;
}
public static FieldCol getShardingFieldCol(Class clz) {
Map, FieldCol> map = getClassShardingFieldMap();
FieldCol fc = map.get(clz);
if (fc == null) {
Field[] fields = clz.getDeclaredFields();
for (Field field: fields) {
field.setAccessible(true);
Sharding sAnn = field.getAnnotation(Sharding.class);
if (sAnn != null) {
Column col = field.getAnnotation(Column.class);
fc = new FieldCol(col == null ? field.getName() : col.name(), field);
map.put(clz, fc);
break;
}
}
}
return fc;
}
public static Field getShardingField(Class clz) {
FieldCol fc = getShardingFieldCol(clz);
return fc == null ? null : fc.getField();
}
}