mirror of
https://github.com/tiennm99/zfoo.git
synced 2026-08-11 14:23:17 +00:00
Merge pull request #117 from awakeyoyoyo/main
perf[orm]: Rewrite collection declaration type check & Support deseri…
This commit is contained in:
@@ -17,6 +17,7 @@ import org.bson.BsonWriter;
|
||||
import org.bson.codecs.Codec;
|
||||
import org.bson.codecs.DecoderContext;
|
||||
import org.bson.codecs.EncoderContext;
|
||||
import org.bson.codecs.configuration.CodecConfigurationException;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
@@ -61,7 +62,7 @@ public class MapCodec<K, V> implements Codec<Map<K, V>> {
|
||||
|
||||
@Override
|
||||
public Map<K, V> decode(BsonReader reader, DecoderContext context) {
|
||||
var map = new HashMap<K, V>();
|
||||
var map = getInstance();
|
||||
reader.readStartDocument();
|
||||
while (BsonType.END_OF_DOCUMENT != reader.readBsonType()) {
|
||||
K key = keyDecodeFunction.apply(reader.readName());
|
||||
@@ -81,6 +82,15 @@ public class MapCodec<K, V> implements Codec<Map<K, V>> {
|
||||
public Class<Map<K, V>> getEncoderClass() {
|
||||
return encoderClass;
|
||||
}
|
||||
|
||||
private Map<K, V> getInstance() {
|
||||
if (encoderClass.isInterface()) {
|
||||
return new HashMap<>();
|
||||
}
|
||||
try {
|
||||
return encoderClass.getDeclaredConstructor().newInstance();
|
||||
} catch (Exception e) {
|
||||
throw new CodecConfigurationException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -40,6 +40,8 @@ import org.bson.Document;
|
||||
import org.bson.codecs.configuration.CodecRegistries;
|
||||
import org.bson.codecs.pojo.PojoCodecProvider;
|
||||
import org.bson.types.ObjectId;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.aop.framework.AopProxyUtils;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
|
||||
@@ -61,7 +63,7 @@ import java.util.concurrent.TimeUnit;
|
||||
* @author godotg
|
||||
*/
|
||||
public class OrmManager implements IOrmManager {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(OrmManager.class);
|
||||
private OrmConfig ormConfig;
|
||||
|
||||
private MongoClient mongoClient;
|
||||
@@ -479,6 +481,7 @@ public class OrmManager implements IOrmManager {
|
||||
}
|
||||
|
||||
var filedList = ReflectionUtils.notStaticAndTransientFields(clazz);
|
||||
boolean concurrentSecurityFlag=true;
|
||||
|
||||
for (var field : filedList) {
|
||||
// entity必须包含属性的get和set方法
|
||||
@@ -495,9 +498,10 @@ public class OrmManager implements IOrmManager {
|
||||
// ORM的数组类型只支持byte[]
|
||||
AssertionUtils.isTrue(arrayClazz == byte.class, "The array type of ORM[class:{}] only supports byte[]", clazz.getCanonicalName());
|
||||
} else if (Set.class.isAssignableFrom(fieldType)) {
|
||||
// 必须是Set接口类型
|
||||
AssertionUtils.isTrue(fieldType.equals(Set.class), "[class:{}] type declaration is incorrect, and it must be of the Set interface type", clazz.getCanonicalName());
|
||||
|
||||
// 是一个Set
|
||||
if (fieldType.equals(Set.class)){
|
||||
concurrentSecurityFlag = false;
|
||||
}
|
||||
var type = field.getGenericType();
|
||||
// field必须泛型类
|
||||
AssertionUtils.isTrue(type instanceof ParameterizedType, "[class:{}] type declaration is incorrect, not a generic class[field:{}]", clazz.getCanonicalName(), field.getName());
|
||||
@@ -508,8 +512,9 @@ public class OrmManager implements IOrmManager {
|
||||
checkSubEntity(clazz, types[0]);
|
||||
} else if (List.class.isAssignableFrom(fieldType)) {
|
||||
// 是一个List
|
||||
AssertionUtils.isTrue(fieldType.equals(List.class), "[class:{}] type declaration is incorrect, and it must be of the List interface type", clazz.getCanonicalName());
|
||||
|
||||
if (fieldType.equals(List.class)){
|
||||
concurrentSecurityFlag = false;
|
||||
}
|
||||
var type = field.getGenericType();
|
||||
// field必须泛型类
|
||||
AssertionUtils.isTrue(type instanceof ParameterizedType, "[class:{}] type declaration is incorrect, not a generic class[field:{}]", clazz.getCanonicalName(), field.getName());
|
||||
@@ -520,9 +525,9 @@ public class OrmManager implements IOrmManager {
|
||||
|
||||
checkSubEntity(clazz, types[0]);
|
||||
} else if (Map.class.isAssignableFrom(fieldType)) {
|
||||
// 必须是Map接口类型
|
||||
if (!fieldType.equals(Map.class)) {
|
||||
throw new RunException("[class:{}] type declaration is incorrect, and it must be a Map interface type", clazz.getCanonicalName());
|
||||
// 是Map接口类型
|
||||
if (fieldType.equals(Map.class)) {
|
||||
concurrentSecurityFlag=false;
|
||||
}
|
||||
|
||||
var type = field.getGenericType();
|
||||
@@ -543,30 +548,34 @@ public class OrmManager implements IOrmManager {
|
||||
if (!ClassUtils.isBaseType((Class<?>) keyType)) {
|
||||
throw new RunException("[class:{}] type declaration is incorrect, and the key type of the Map must be the Base type", clazz.getCanonicalName());
|
||||
}
|
||||
|
||||
checkSubEntity(clazz, valueType);
|
||||
if (concurrentSecurityFlag) {
|
||||
concurrentSecurityFlag = checkSubEntity(clazz, valueType);
|
||||
}
|
||||
} else if (ObjectId.class.isAssignableFrom(fieldType)) {
|
||||
// do nothing
|
||||
} else {
|
||||
checkEntity(fieldType);
|
||||
}
|
||||
}
|
||||
if (!concurrentSecurityFlag) {
|
||||
logger.warn("class[{}] has collection not declared with specified implementation, deserialization defaults to using the thread unsafe implementation", clazz.getSimpleName());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void checkSubEntity(Class<?> currentEntityClass, Type type) {
|
||||
private boolean checkSubEntity(Class<?> currentEntityClass, Type type) {
|
||||
if (type instanceof ParameterizedType) {
|
||||
// 泛型类
|
||||
Class<?> clazz = (Class<?>) ((ParameterizedType) type).getRawType();
|
||||
if (Set.class.equals(clazz)) {
|
||||
if (Set.class.isAssignableFrom(clazz)) {
|
||||
// Set<Set<String>>
|
||||
checkSubEntity(currentEntityClass, ((ParameterizedType) type).getActualTypeArguments()[0]);
|
||||
return;
|
||||
} else if (List.class.equals(clazz)) {
|
||||
return clazz.equals(Set.class);
|
||||
} else if (List.class.isAssignableFrom(clazz)) {
|
||||
// List<List<String>>
|
||||
checkSubEntity(currentEntityClass, ((ParameterizedType) type).getActualTypeArguments()[0]);
|
||||
return;
|
||||
} else if (Map.class.equals(clazz)) {
|
||||
return clazz.equals(List.class);
|
||||
} else if (Map.class.isAssignableFrom(clazz)) {
|
||||
// Map<List<String>, List<String>>
|
||||
var types = ((ParameterizedType) type).getActualTypeArguments();
|
||||
var keyType = types[0];
|
||||
@@ -575,13 +584,13 @@ public class OrmManager implements IOrmManager {
|
||||
throw new RunException("The key of the map in the ORM must be of the Base type");
|
||||
}
|
||||
checkSubEntity(currentEntityClass, valueType);
|
||||
return;
|
||||
return clazz.equals(Map.class);
|
||||
}
|
||||
} else if (type instanceof Class) {
|
||||
Class<?> clazz = ((Class<?>) type);
|
||||
if (isBaseType(clazz)) {
|
||||
// do nothing
|
||||
return;
|
||||
return true;
|
||||
} else if (clazz.getComponentType() != null) {
|
||||
// ORM不支持多维数组或集合嵌套数组类型,仅支持一维数组
|
||||
throw new RunException("[type:{}] does not support multi-dimensional arrays or nested arrays, and only supports one-dimensional arrays", type);
|
||||
@@ -590,7 +599,7 @@ public class OrmManager implements IOrmManager {
|
||||
throw new RunException("ORMs do not support the combination of arrays and collections with the [type:{}] type", type);
|
||||
} else {
|
||||
checkEntity(clazz);
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
throw new RunException("[type:{}] is incorrect", type);
|
||||
|
||||
@@ -63,6 +63,7 @@ public class EntityDef {
|
||||
public IEntity<?> newEntity(Object id) {
|
||||
var entity = ReflectionUtils.newInstance(clazz);
|
||||
var idFields = ReflectionUtils.getFieldsByAnnoInPOJOClass(clazz, Id.class);
|
||||
ReflectionUtils.makeAccessible(idFields[0]);
|
||||
ReflectionUtils.setField(idFields[0], entity, id);
|
||||
return entity;
|
||||
}
|
||||
|
||||
@@ -27,6 +27,8 @@ import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
@Ignore
|
||||
public class MapTest {
|
||||
@@ -54,6 +56,22 @@ public class MapTest {
|
||||
|
||||
entity.setList(List.of(1, 2, 3));
|
||||
|
||||
CopyOnWriteArrayList<Integer> copyOnWriteArrayList = new CopyOnWriteArrayList<>();
|
||||
copyOnWriteArrayList.add(1);
|
||||
copyOnWriteArrayList.add(2);
|
||||
entity.setCopyOnWriteArrayList(copyOnWriteArrayList);
|
||||
|
||||
ConcurrentHashMap<Long,Integer> concurrentHashMap=new ConcurrentHashMap<>();
|
||||
concurrentHashMap.put(1L,1);
|
||||
concurrentHashMap.put(2L,2);
|
||||
entity.setConcurrentHashMap(concurrentHashMap);
|
||||
|
||||
ConcurrentHashMap<Long,ConcurrentHashMap<Integer,Integer>> concurrentHashMapConcurrentHashMap=new ConcurrentHashMap<>();
|
||||
|
||||
ConcurrentHashMap<Integer, Integer> conMap = new ConcurrentHashMap<>();
|
||||
conMap.put(1,1);
|
||||
concurrentHashMapConcurrentHashMap.putIfAbsent(1L,conMap);
|
||||
entity.setConcurrentHashMapAndConcurrentHashMap(concurrentHashMapConcurrentHashMap);
|
||||
var bagMap = new HashMap<String, BagItem>();
|
||||
entity.setBagMap(bagMap);
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ import com.zfoo.orm.anno.Persister;
|
||||
import com.zfoo.orm.model.IEntity;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
@EntityCache(persister = @Persister("time30s"))
|
||||
@@ -26,7 +27,13 @@ public class MapEntity implements IEntity<Long> {
|
||||
@Id
|
||||
private long id;
|
||||
|
||||
private List<Integer> list = new CopyOnWriteArrayList<>();
|
||||
private List<Integer> list = new ArrayList<>();
|
||||
|
||||
private CopyOnWriteArrayList<Integer> copyOnWriteArrayList = new CopyOnWriteArrayList<>();
|
||||
|
||||
private ConcurrentHashMap<Long, Integer> concurrentHashMap = new ConcurrentHashMap<>();
|
||||
|
||||
private ConcurrentHashMap<Long, ConcurrentHashMap<Integer,Integer>> concurrentHashMapAndConcurrentHashMap = new ConcurrentHashMap<>();
|
||||
private Map<String, BagItem> bagMap = new HashMap<>();
|
||||
|
||||
private Map<String, Map<String, String>> baseMap = new HashMap<>();
|
||||
@@ -168,6 +175,31 @@ public class MapEntity implements IEntity<Long> {
|
||||
this.doubleBagMap = doubleBagMap;
|
||||
}
|
||||
|
||||
public CopyOnWriteArrayList<Integer> getCopyOnWriteArrayList() {
|
||||
return copyOnWriteArrayList;
|
||||
}
|
||||
|
||||
public void setCopyOnWriteArrayList(CopyOnWriteArrayList<Integer> copyOnWriteArrayList) {
|
||||
this.copyOnWriteArrayList = copyOnWriteArrayList;
|
||||
}
|
||||
|
||||
public ConcurrentHashMap<Long, Integer> getConcurrentHashMap() {
|
||||
return concurrentHashMap;
|
||||
}
|
||||
|
||||
public void setConcurrentHashMap(ConcurrentHashMap<Long, Integer> concurrentHashMap) {
|
||||
this.concurrentHashMap = concurrentHashMap;
|
||||
}
|
||||
|
||||
|
||||
public ConcurrentHashMap<Long, ConcurrentHashMap<Integer, Integer>> getConcurrentHashMapAndConcurrentHashMap() {
|
||||
return concurrentHashMapAndConcurrentHashMap;
|
||||
}
|
||||
|
||||
public void setConcurrentHashMapAndConcurrentHashMap(ConcurrentHashMap<Long, ConcurrentHashMap<Integer, Integer>> concurrentHashMapAndConcurrentHashMap) {
|
||||
this.concurrentHashMapAndConcurrentHashMap = concurrentHashMapAndConcurrentHashMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
|
||||
Reference in New Issue
Block a user