pers.clare.hisql.store.SQLStoreFactory Maven / Gradle / Ivy
The newest version!
package pers.clare.hisql.store;
import pers.clare.hisql.exception.HiSqlException;
import pers.clare.hisql.function.FieldSetter;
import pers.clare.hisql.function.KeySQLBuilder;
import pers.clare.hisql.function.ResultSetValueConverter;
import pers.clare.hisql.naming.NamingStrategy;
import pers.clare.hisql.support.ResultSetConverter;
import pers.clare.hisql.util.ClassUtil;
import pers.clare.hisql.util.FieldColumnFactory;
import pers.clare.hisql.util.SQLQueryUtil;
import javax.persistence.Table;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@SuppressWarnings("unused")
public class SQLStoreFactory {
static final Map, SQLStore>> storeCacheMap = new ConcurrentHashMap<>();
static final Map, Map>> converterFieldSetMap = new ConcurrentHashMap<>();
public static KeySQLBuilder buildKey(Class keyClass, SQLCrudStore> store) {
if (ClassUtil.isBasicType(keyClass)
|| keyClass.isArray()
) {
return (builder, key) -> SQLQueryUtil.setValue(builder, store.getKeyFields(), new Object[]{key});
} else {
Field[] keyFields = new Field[store.getKeyFields().length];
int count = 0;
for (Field field : store.getKeyFields()) {
try {
Field keyField = keyFields[count++] = keyClass.getDeclaredField(field.getName());
keyField.setAccessible(true);
} catch (NoSuchFieldException e) {
throw new IllegalArgumentException(String.format("%s %s field not found!", keyClass, field.getName()));
}
}
return (builder, key) -> SQLQueryUtil.setValue(builder, keyFields, key);
}
}
@SuppressWarnings("unchecked")
public static SQLStore build(
NamingStrategy naming
, ResultSetConverter converter
, Class clazz
) {
if (FieldColumnFactory.isIgnore(clazz)) throw new Error(String.format("%s can not build SQLStore", clazz));
return (SQLStore) storeCacheMap.computeIfAbsent(clazz, (key) -> doBuild(naming, converter, clazz));
}
@SuppressWarnings("unchecked")
public static SQLCrudStore buildCrud(
NamingStrategy naming
, ResultSetConverter converter
, Class clazz
) {
if (FieldColumnFactory.isIgnore(clazz))
throw new Error(String.format("%s can not build SQLSchemaStore", clazz));
SQLStore store = (SQLStore) storeCacheMap.get(clazz);
if (!(store instanceof SQLCrudStore)) {
store = doBuildCrud(naming, converter, clazz);
storeCacheMap.put(clazz, store);
}
return (SQLCrudStore) store;
}
private static SQLStore doBuild(
NamingStrategy naming
, ResultSetConverter converter
, Class clazz
) {
try {
return new SQLStore<>(clazz.getConstructor(), buildFieldSetters(naming, clazz, converter));
} catch (NoSuchMethodException e) {
throw new HiSqlException(e.getMessage());
}
}
private static SQLCrudStore doBuildCrud(
NamingStrategy naming
, ResultSetConverter converter
, Class clazz
) {
String tableName;
Table table = clazz.getAnnotation(Table.class);
if (table == null) {
tableName = naming.turnCamelCase(clazz.getSimpleName());
} else {
tableName = table.name();
}
FieldColumn[] fieldColumns = FieldColumnFactory.get(naming, clazz);
int length = fieldColumns.length;
int keyCount = 0;
Field[] keyFields = new Field[length];
Field autoKey = null;
boolean ps = false;
for (FieldColumn column : fieldColumns) {
if (column.isAuto()) autoKey = column.getField();
if (column.isId()) {
keyFields[keyCount++] = column.getField();
}
if (InputStream.class.isAssignableFrom(column.getField().getType())) {
ps = true;
}
}
Field[] temp = keyFields;
keyFields = new Field[keyCount];
System.arraycopy(temp, 0, keyFields, 0, keyCount);
try {
return new SQLCrudStore<>(clazz.getConstructor()
, buildFieldSetters(naming, clazz, converter)
, tableName, fieldColumns, autoKey, keyFields, ps
);
} catch (NoSuchMethodException e) {
throw new HiSqlException(e.getMessage());
}
}
private static Map buildFieldSetters(NamingStrategy naming, Class> clazz, ResultSetConverter converter) {
return converterFieldSetMap.computeIfAbsent(converter, (c) -> new ConcurrentHashMap<>()).computeIfAbsent(clazz, (key) -> {
FieldColumn[] fields = FieldColumnFactory.get(naming, clazz);
Map fieldSetMap = new ConcurrentHashMap<>();
for (FieldColumn fieldColumn : fields) {
Field field = fieldColumn.getField();
String name = fieldColumn.getColumnName().replaceAll("`", "");
FieldSetter fieldSetter = buildFieldSetter(converter, field);
fieldSetMap.put(field.getName(), fieldSetter);
fieldSetMap.put(name, fieldSetter);
fieldSetMap.put(name.toUpperCase(), fieldSetter);
}
return fieldSetMap;
});
}
private static FieldSetter buildFieldSetter(ResultSetConverter resultSetConverter, Field field) {
ResultSetValueConverter> valueConverter = resultSetConverter.get(field.getType());
if (valueConverter == null) {
if (field.getType() == Object.class) {
return (target, rs, index) -> field.set(target, rs.getObject(index));
} else {
return (target, rs, index) -> field.set(target, rs.getObject(index, field.getType()));
}
} else {
return (target, rs, index) -> field.set(target, valueConverter.apply(rs, index));
}
}
private static char[] merge(String... strings) {
int size = 0;
for (String string : strings) {
size += string.length();
}
char[] cs = new char[size];
int i = 0;
for (String string : strings) {
string.getChars(0, string.length(), cs, i);
i += string.length();
}
return cs;
}
}