org.yx.db.sql.PojoMeta Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of sumk Show documentation
Show all versions of sumk Show documentation
A quick developing framewort for internet company
/**
* Copyright (C) 2016 - 2030 youtongluan.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.yx.db.sql;
import java.lang.reflect.Array;
import java.lang.reflect.Type;
import java.sql.Time;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.function.IntFunction;
import org.yx.annotation.db.AutoCreateTime;
import org.yx.annotation.doc.Comment;
import org.yx.annotation.spec.TableSpec;
import org.yx.bean.Loader;
import org.yx.common.date.TimeUtil;
import org.yx.conf.AppInfo;
import org.yx.db.enums.CacheType;
import org.yx.exception.SumkException;
import org.yx.log.Log;
import org.yx.log.Logs;
import org.yx.main.StartContext;
import org.yx.redis.RedisPool;
import org.yx.util.CollectionUtil;
import org.yx.util.StringUtil;
public final class PojoMeta implements Cloneable {
public static final String WILDCHAR = "#";
private static final char KEY_SPLIT = ':';
final List fieldMetas;
/**
* 数据库表所对应的java pojo类
*/
final Class> pojoClz;
final List cacheIDs;
final List databaseIds;
private VisitCounter counter;
private int ttlSec;
private String pre;
private final CacheType cacheType;
private String tableName;
final SoftDeleteMeta softDelete;
private final Map columnDBNameMap = new HashMap<>();
private final Map filedNameMap = new HashMap<>();
final List createColumns;
final Type pojoArrayClz;
public Type pojoArrayClz() {
return this.pojoArrayClz;
}
public List fieldMetas() {
return this.fieldMetas;
}
public ColumnMeta getByColumnDBName(String columnDBName) {
if (columnDBName == null || columnDBName.isEmpty()) {
return null;
}
return this.columnDBNameMap.get(columnDBName.toLowerCase());
}
public ColumnMeta getByFieldName(String fieldName) {
if (fieldName == null || fieldName.isEmpty()) {
return null;
}
return this.filedNameMap.get(fieldName.toLowerCase());
}
public boolean isNoCache() {
return cacheType == CacheType.NOCACHE || RedisPool.defaultRedis() == null || this.cacheIDs.isEmpty();
}
public CacheType cacheType() {
return cacheType;
}
public boolean isPrimeKeySameWithCache() {
return databaseIds == cacheIDs;
}
public List getDatabaseIds() {
return databaseIds;
}
public boolean isSoftDelete() {
return this.softDelete != null;
}
public VisitCounter getCounter() {
return counter;
}
public int getTtlSec() {
return ttlSec;
}
private List unmodifyList(List source) {
if (source.size() > 1) {
return CollectionUtil.unmodifyList(source.toArray(new ColumnMeta[source.size()]));
}
return CollectionUtil.unmodifyList(source);
}
public PojoMeta(TableSpec table, ColumnMeta[] fieldMetas, Class> pojoClz) {
this.cacheType = table.cacheType();
this.fieldMetas = CollectionUtil.unmodifyList(fieldMetas);
this.pojoClz = pojoClz;
List rids = new ArrayList<>();
List pids = new ArrayList<>();
List ctimes = new ArrayList<>();
for (ColumnMeta m : this.fieldMetas) {
columnDBNameMap.put(m.dbColumn.toLowerCase(), m);
filedNameMap.put(m.getFieldName().toLowerCase(), m);
if (m.isCacheID()) {
rids.add(m);
}
if (m.isDBID()) {
pids.add(m);
}
if (m.field.isAnnotationPresent(AutoCreateTime.class)) {
if (TimeUtil.isGenericDate(m.field.getType()) && !timeOnly(m.field.getType())) {
ctimes.add(m);
} else {
Logs.db().warn("{}.{}的类型{}不是@CreateTime支持的类型", pojoClz.getSimpleName(), m.field.getName(),
m.field.getType());
}
}
}
this.cacheIDs = unmodifyList(rids);
this.databaseIds = pids.equals(rids) ? this.cacheIDs : unmodifyList(pids);
this.createColumns = unmodifyList(ctimes);
this.softDelete = softDeleteParser().parse(this.pojoClz, this.fieldMetas);
this.parseTable(table);
this.pojoArrayClz = Array.newInstance(this.pojoClz, 0).getClass();
}
private SoftDeleteParser softDeleteParser() {
return StartContext.inst().get(SoftDeleteParser.class, new SoftDeleteParserImpl());
}
private void parseTable(TableSpec table) {
int ttl = table.duration();
if (ttl > 0) {
this.ttlSec = ttl;
} else if (ttl == 0) {
this.ttlSec = AppInfo.getInt("sumk.cache.ttl", 3600);
} else {
this.ttlSec = -1;
}
int maxHit = AppInfo.getInt("sumk.db.table.cache.maxHit", table.maxHit());
@SuppressWarnings("unchecked")
IntFunction factory = (IntFunction) StartContext.inst().get(VisitCounter.class);
this.counter = factory != null ? factory.apply(maxHit) : new DefaultVisitCounter(maxHit);
this.tableName = StringUtil.isEmpty(table.value())
? DBNameResolvers.getTableNameResolver().apply(this.pojoClz.getSimpleName())
: table.value().replace('?', '#');
String _pre = table.preInCache();
if (StringUtil.isEmpty(_pre)) {
_pre = DBNameResolvers.getCachePrefixResolver().apply(this.tableName);
}
this.pre = _pre.replace('?', '#');
}
public String getTableName() {
return this.tableName;
}
public String getPre() {
return this.pre;
}
public boolean isOnlyCacheID(Object condition) throws IllegalArgumentException, IllegalAccessException {
if (this.pojoClz.isInstance(condition)) {
for (ColumnMeta m : this.fieldMetas) {
Object v = m.value(condition);
if (m.isCacheID() == (v == null)) {
return false;
}
}
return true;
}
if (condition instanceof Map) {
@SuppressWarnings("unchecked")
Map map = (Map) condition;
if (map.size() != this.cacheIDs.size()) {
return false;
}
Set> set = map.entrySet();
for (Map.Entry entry : set) {
if (entry.getValue() == null) {
continue;
}
String key = entry.getKey();
ColumnMeta cm = this.getByFieldName(key);
if (cm == null || !cm.isCacheID()) {
return false;
}
}
return true;
}
return false;
}
public List getCacheIDs() {
return this.cacheIDs;
}
public Object buildFromDBColumn(Map map) throws Exception {
if (map == null) {
return null;
}
Object ret = Loader.newInstance(this.pojoClz);
Set> set = map.entrySet();
for (Entry en : set) {
String key = en.getKey();
ColumnMeta m = this.getByColumnDBName(key);
if (m == null) {
Logs.db().warn("{}数据库字段{}找不到对应的属性", this.tableName, key);
continue;
}
m.setValue(ret, en.getValue());
}
return ret;
}
@SuppressWarnings("unchecked")
public Map populate(Object source, boolean keepNull)
throws InstantiationException, IllegalAccessException {
if (source instanceof Map) {
return (Map) source;
}
Map map = new HashMap<>();
if (!this.pojoClz.isInstance(source)) {
throw new SumkException(548092345,
source.getClass().getName() + " is not instance of " + this.pojoClz.getName());
}
for (ColumnMeta m : this.fieldMetas) {
Object v = m.value(source);
if (!keepNull && v == null) {
continue;
}
String name = m.getFieldName();
map.put(name, v);
}
return map;
}
public Object buildPojo(Map map) throws Exception {
Object obj = Loader.newInstance(this.pojoClz);
for (ColumnMeta m : this.fieldMetas) {
Object v = map.get(m.getFieldName());
if (v == null) {
continue;
}
m.setValue(obj, v);
}
return obj;
}
@SuppressWarnings("unchecked")
public Map populateByDbColumn(Object source, boolean withnull)
throws InstantiationException, IllegalAccessException {
if (source instanceof Map) {
return (Map) source;
}
Map map = new HashMap<>();
if (!this.pojoClz.isInstance(source)) {
Log.get("sumk.event").debug("{} is not instance of {}", source.getClass().getName(),
this.pojoClz.getName());
return map;
}
for (ColumnMeta m : this.fieldMetas) {
Object v = m.value(source);
if (!withnull && v == null) {
continue;
}
String name = m.dbColumn;
map.put(name, v);
}
return map;
}
public String getCacheID(Object source, boolean exceptionIfHasNull) throws Exception {
return joinColumns(source, exceptionIfHasNull, this.cacheIDs);
}
public String getCacheIDWithNULL(Map map) throws Exception {
StringBuilder key = new StringBuilder();
for (ColumnMeta m : this.cacheIDs) {
Object v = map.get(m.getFieldName());
if (key.length() > 0) {
key.append(KEY_SPLIT);
}
key.append(v);
}
return key.toString();
}
private String joinColumnsFromMap(Map map, boolean exceptionIfHasNull, List cols) {
StringBuilder key = new StringBuilder();
for (ColumnMeta m : cols) {
Object v = map.get(m.getFieldName());
if (v == null) {
if (exceptionIfHasNull) {
throw new SumkException(1232142356,
this.pojoClz.getName() + ": redis key [" + m.getFieldName() + "] cannot be null");
}
return null;
}
if (key.length() > 0) {
key.append(KEY_SPLIT);
}
key.append(v);
}
return key.toString();
}
@SuppressWarnings("unchecked")
public String joinColumns(Object source, boolean exceptionIfHasNull, List cols) throws Exception {
if (source instanceof Map) {
return this.joinColumnsFromMap((Map) source, exceptionIfHasNull, cols);
}
StringBuilder key = new StringBuilder();
for (ColumnMeta m : cols) {
Object v = m.value(source);
if (v == null) {
if (exceptionIfHasNull) {
throw new SumkException(1232142356,
this.pojoClz.getName() + ": value of " + m.getFieldName() + " cannot be null");
}
return null;
}
if (key.length() > 0) {
key.append(KEY_SPLIT);
}
key.append(v);
}
return key.toString();
}
public PojoMeta subPojoMeta(String sub) {
if (!this.tableName.contains(WILDCHAR)) {
return this;
}
PojoMeta clone;
try {
clone = (PojoMeta) this.clone();
} catch (CloneNotSupportedException e) {
throw new SumkException(3456346, e.getMessage());
}
clone.tableName = subTableName(sub);
clone.pre = this.pre.replace(WILDCHAR, sub.toLowerCase());
return clone;
}
String subTableName(String sub) {
return this.tableName.replace(WILDCHAR, sub);
}
public List createColumns() {
return createColumns;
}
private static boolean timeOnly(Class> type) {
return type == Time.class || type == LocalTime.class;
}
public Class> pojoClz() {
return this.pojoClz;
}
public String getComment() {
Comment c = this.pojoClz.getAnnotation(Comment.class);
return c == null ? "" : c.value();
}
public SoftDeleteMeta getSoftDelete() {
return softDelete;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy