perf[orm]: 校验entity的map属性类型

This commit is contained in:
jaysunxiao
2022-02-22 15:19:29 +08:00
parent e7bb7fdd98
commit ae6ac9ec5e
5 changed files with 137 additions and 83 deletions
@@ -347,7 +347,7 @@ public class OrmManager implements IOrmManager {
// 校验entity格式
var entitySubClassMap = new HashMap<Class<?>, Set<Class<?>>>();
checkEntity(clazz, entitySubClassMap);
checkEntity(clazz);
// 对象循环引用检测
for (var entry : entitySubClassMap.entrySet()) {
var subClass = entry.getKey();
@@ -438,19 +438,13 @@ public class OrmManager implements IOrmManager {
AssertionUtils.isTrue(gvsReturnValue.equals(vsValue), "实体类Entity[{}]的gvs方法和svs方法定义格式不正确", clazz.getSimpleName());
}
private void checkEntity(Class<?> clazz, HashMap<Class<?>, Set<Class<?>>> entitySubClassMap) {
// 不需要检查重复的协议
if (entitySubClassMap.containsKey(clazz)) {
return;
}
entitySubClassMap.put(clazz, new HashSet<>());
// // 是否为一个简单的javabean
// ReflectionUtils.assertIsPojoClass(clazz);
// // 不能是泛型类
// AssertionUtils.isTrue(ArrayUtils.isEmpty(clazz.getTypeParameters()), "[class:{}]不能是泛型类", clazz.getCanonicalName());
// // 必须要有一个空的构造器
// ReflectionUtils.publicEmptyConstructor(clazz);
private void checkEntity(Class<?> clazz) {
// 是否为一个简单的javabean
ReflectionUtils.assertIsPojoClass(clazz);
// 不能是泛型类
AssertionUtils.isTrue(ArrayUtils.isEmpty(clazz.getTypeParameters()), "[class:{}]不能是泛型类", clazz.getCanonicalName());
// 必须要有一个空的构造器
ReflectionUtils.publicEmptyConstructor(clazz);
// 不能使用Storage的Index注解
var storageIndexes = ReflectionUtils.getFieldsByAnnoNameInPOJOClass(clazz, "com.zfoo.storage.model.anno.Index");
@@ -475,51 +469,71 @@ public class OrmManager implements IOrmManager {
} else if (fieldType.isArray()) {
// 是一个数组
Class<?> arrayClazz = fieldType.getComponentType();
checkSubEntity(clazz, arrayClazz, entitySubClassMap);
checkSubEntity(clazz, arrayClazz);
} else if (Set.class.isAssignableFrom(fieldType)) {
AssertionUtils.isTrue(fieldType.equals(Set.class), "ORM[class:{}]类型声明不正确,必须是Set接口类型", clazz.getCanonicalName());
Type type = field.getGenericType();
var type = field.getGenericType();
AssertionUtils.isTrue(type instanceof ParameterizedType, "ORM[class:{}]类型声明不正确,不是泛型类[field:{}]", clazz.getCanonicalName(), field.getName());
Type[] types = ((ParameterizedType) type).getActualTypeArguments();
var types = ((ParameterizedType) type).getActualTypeArguments();
AssertionUtils.isTrue(types.length == 1, "ORM[class:{}]中Set类型声明不正确,[field:{}]必须声明泛型类", clazz.getCanonicalName(), field.getName());
checkSubEntity(clazz, types[0], entitySubClassMap);
checkSubEntity(clazz, types[0]);
} else if (List.class.isAssignableFrom(fieldType)) {
// 是一个List
AssertionUtils.isTrue(fieldType.equals(List.class), "ORM[class:{}]类型声明不正确,必须是List接口类型", clazz.getCanonicalName());
Type type = field.getGenericType();
var type = field.getGenericType();
AssertionUtils.isTrue(type instanceof ParameterizedType, "ORM[class:{}]类型声明不正确,不是泛型类[field:{}]", clazz.getCanonicalName(), field.getName());
Type[] types = ((ParameterizedType) type).getActualTypeArguments();
var types = ((ParameterizedType) type).getActualTypeArguments();
AssertionUtils.isTrue(types.length == 1, "ORM[class:{}]中List类型声明不正确,[field:{}]必须声明泛型类", clazz.getCanonicalName(), field.getName());
checkSubEntity(clazz, types[0], entitySubClassMap);
}
// else if (Map.class.isAssignableFrom(fieldType)) {
// throw new RunException("ORM[class:{}]类型声明不正确,不支持Map类型", clazz.getCanonicalName());
// }
else {
entitySubClassMap.get(clazz).add(fieldType);
checkEntity(fieldType, entitySubClassMap);
checkSubEntity(clazz, types[0]);
} else if (Map.class.isAssignableFrom(fieldType)) {
if (!fieldType.equals(Map.class)) {
throw new RunException("ORM[class:{}]类型声明不正确,必须是Map接口类型", clazz.getCanonicalName());
}
var type = field.getGenericType();
if (!(type instanceof ParameterizedType)) {
throw new RunException("ORM[class:{}]中数组类型声明不正确,[field:{}]不是泛型类", clazz.getCanonicalName(), field.getName());
}
var types = ((ParameterizedType) type).getActualTypeArguments();
if (types.length != 2) {
throw new RunException("ORM[class:{}]中数组类型声明不正确,[field:{}]必须声明泛型类", clazz.getCanonicalName(), field.getName());
}
var keyType = types[0];
var valueType = types[1];
if (!isBaseType((Class<?>) keyType)) {
throw new RunException("ORM[class:{}]类型声明不正确,Map的key类型必须为基础类型", clazz.getCanonicalName());
}
checkSubEntity(clazz, valueType);
} else {
checkEntity(fieldType);
}
}
}
private void checkSubEntity(Class<?> currentEntityClass, Type type, HashMap<Class<?>, Set<Class<?>>> entitySubClassMap) {
private void checkSubEntity(Class<?> currentEntityClass, Type type) {
if (type instanceof ParameterizedType) {
// 泛型类
Class<?> clazz = (Class<?>) ((ParameterizedType) type).getRawType();
if (Set.class.equals(clazz)) {
// Set<Set<String>>
checkSubEntity(currentEntityClass, ((ParameterizedType) type).getActualTypeArguments()[0], entitySubClassMap);
checkSubEntity(currentEntityClass, ((ParameterizedType) type).getActualTypeArguments()[0]);
return;
} else if (List.class.equals(clazz)) {
// List<List<String>>
checkSubEntity(currentEntityClass, ((ParameterizedType) type).getActualTypeArguments()[0], entitySubClassMap);
checkSubEntity(currentEntityClass, ((ParameterizedType) type).getActualTypeArguments()[0]);
return;
} else if (Map.class.equals(clazz)) {
// Map<List<String>, List<String>>
@@ -536,8 +550,7 @@ public class OrmManager implements IOrmManager {
} else if (clazz.equals(List.class) || clazz.equals(Set.class) || clazz.equals(Map.class)) {
throw new RunException("ORM不支持数组和集合联合使用[type:{}]类型", type);
} else {
entitySubClassMap.get(currentEntityClass).add(clazz);
checkEntity(clazz, entitySubClassMap);
checkEntity(clazz);
return;
}
}
@@ -17,31 +17,47 @@ import com.zfoo.orm.OrmContext;
import com.zfoo.orm.entity.bag.BagItem;
import com.zfoo.orm.entity.bag.Item;
import com.zfoo.orm.entity.bag.MapEntity;
import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.HashMap;
@Ignore
public class MapTest {
private static final Logger log = LoggerFactory.getLogger(MapTest.class);
@Test
public void insertMapData() {
var context = new ClassPathXmlApplicationContext("application.xml");
MapEntity entity = OrmContext.getAccessor().load(1, MapEntity.class);
if (entity == null) {
entity = new MapEntity();
entity.setId(1);
entity.getRoleBag().computeIfAbsent("1", k -> new BagItem())
.getMapItem().computeIfAbsent("2", k -> new Item());
OrmContext.getAccessor().insert(entity);
log.info("数据插入成功 {}", entity);
} else {
log.info("entity已存在 {}", entity);
}
OrmContext.getAccessor().delete(1, MapEntity.class);
var entity = new MapEntity();
entity.setId(1);
var bagMap = new HashMap<String, BagItem>();
entity.setBagMap(bagMap);
var itemMap = new HashMap<String, Item>();
itemMap.put("1", new Item(1, "item1"));
itemMap.put("2", new Item(2, "item1"));
itemMap.put("3", new Item(3, "item1"));
var bagItem1 = new BagItem(1, "desc1", itemMap);
var bagItem2 = new BagItem(2, "desc2", itemMap);
var bagItem3 = new BagItem(3, "desc3", itemMap);
bagMap.put("bag1", bagItem1);
bagMap.put("bag2", bagItem2);
bagMap.put("bag3", bagItem3);
OrmContext.getAccessor().insert(entity);
var myEntity = OrmContext.getAccessor().load(1, MapEntity.class);
Assert.assertEquals(entity, myEntity);
}
}
}
@@ -15,16 +15,22 @@ package com.zfoo.orm.entity.bag;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
public class BagItem {
private int id;
private String desc;
private Map<String, Item> mapItem = new HashMap<>();
private Map<String, Item> itemMap = new HashMap<>();
public BagItem() {
this.id = 1;
this.desc = "desc";
}
public BagItem(int id, String desc, Map<String, Item> itemMap) {
this.id = id;
this.desc = desc;
this.itemMap = itemMap;
}
public int getId() {
@@ -43,20 +49,24 @@ public class BagItem {
this.desc = desc;
}
public Map<String, Item> getMapItem() {
return mapItem;
public Map<String, Item> getItemMap() {
return itemMap;
}
public void setMapItem(Map<String, Item> mapItem) {
this.mapItem = mapItem;
public void setItemMap(Map<String, Item> itemMap) {
this.itemMap = itemMap;
}
@Override
public String toString() {
return "BagItem{" +
"id=" + id +
", desc='" + desc + '\'' +
", mapItem=" + mapItem +
'}';
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
BagItem bagItem = (BagItem) o;
return id == bagItem.id && Objects.equals(desc, bagItem.desc) && Objects.equals(itemMap, bagItem.itemMap);
}
}
@Override
public int hashCode() {
return Objects.hash(id, desc, itemMap);
}
}
@@ -13,13 +13,19 @@
package com.zfoo.orm.entity.bag;
import java.util.Objects;
public class Item {
private int a;
private String b;
public Item() {
this.a = 1;
this.b = "bbbb";
}
public Item(int a, String b) {
this.a = a;
this.b = b;
}
public int getA() {
@@ -38,11 +44,17 @@ public class Item {
this.b = b;
}
@Override
public String toString() {
return "Item{" +
"a=" + a +
", b='" + b + '\'' +
'}';
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Item item = (Item) o;
return a == item.a && Objects.equals(b, item.b);
}
}
@Override
public int hashCode() {
return Objects.hash(a, b);
}
}
@@ -20,17 +20,14 @@ import com.zfoo.orm.model.entity.IEntity;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
@EntityCache(cacheStrategy = "thousand", persister = @Persister("time30s"))
public class MapEntity implements IEntity<Long> {
@Id
private long id;
private Map<String, BagItem> roleBag = new HashMap<>();
public MapEntity() {
}
private Map<String, BagItem> bagMap = new HashMap<>();
@Override
public Long id() {
@@ -45,19 +42,25 @@ public class MapEntity implements IEntity<Long> {
this.id = id;
}
public Map<String, BagItem> getRoleBag() {
return roleBag;
public Map<String, BagItem> getBagMap() {
return bagMap;
}
public void setRoleBag(Map<String, BagItem> roleBag) {
this.roleBag = roleBag;
public void setBagMap(Map<String, BagItem> bagMap) {
this.bagMap = bagMap;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
MapEntity mapEntity = (MapEntity) o;
return id == mapEntity.id && Objects.equals(bagMap, mapEntity.bagMap);
}
@Override
public String toString() {
return "MapEntity{" +
"id=" + id +
", roleBag=" + roleBag +
'}';
public int hashCode() {
return Objects.hash(id, bagMap);
}
}
}