|
|
@@ -57,6 +57,64 @@ public class BaseDao<T extends BaseEntity> {
|
|
|
entityClass = (Class<T>) actualTypeArguments[0];
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 对对象的字段进行检查,包括是否为空等,主要关注 {@link FieldProperty} 注解
|
|
|
+ *
|
|
|
+ * @param <K> 要检查的对象的类型
|
|
|
+ * @param k 要检查的对象
|
|
|
+ */
|
|
|
+ public static <K> void checkFields(@NotEmpty("k") K k) throws IllegalArgumentException, IllegalStateException {
|
|
|
+ Class<?> clazz = k.getClass();
|
|
|
+ Field[] declaredFields = clazz.getDeclaredFields();
|
|
|
+ String collectionName;
|
|
|
+ if (k instanceof BaseEntity) {
|
|
|
+ collectionName = ((BaseEntity) k).collectionSimpleName();
|
|
|
+ } else {
|
|
|
+ collectionName = clazz.getSimpleName();
|
|
|
+ }
|
|
|
+ for (Field field : declaredFields) {
|
|
|
+ int modifiers = field.getModifiers();
|
|
|
+ // 不处理static修饰的变量
|
|
|
+ if (Modifier.isStatic(modifiers)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ Embedded embedded = field.getAnnotation(Embedded.class);
|
|
|
+ Reference reference = field.getAnnotation(Reference.class);
|
|
|
+ FieldProperty fieldProperty = field.getAnnotation(FieldProperty.class);
|
|
|
+ // 只有使用 {@link FieldProperty} 指定不可为空,或者是嵌入或引用对象,才处理
|
|
|
+ if ((fieldProperty == null || fieldProperty.nullable()) && embedded == null && reference == null) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ Object value = ObjectUtils.getValue(field, k);
|
|
|
+
|
|
|
+ // 如果使用 {@link FieldProperty} 指定不可为空,但是值为空,则抛出异常
|
|
|
+ if (fieldProperty != null && !fieldProperty.nullable() && ObjectUtils.isEmpty(value)) {
|
|
|
+ throw new IllegalArgumentException(collectionName + "字段为空:" + field.getName());
|
|
|
+ }
|
|
|
+ // 如果是嵌入或引用对象,并且不为空,则递归检测
|
|
|
+ if ((embedded != null || reference != null) && !ObjectUtils.isEmpty(value)) {
|
|
|
+ // 如果是Collection
|
|
|
+ if (value instanceof Collection) {
|
|
|
+ Collection<?> collection = (Collection<?>) value;
|
|
|
+ for (Object obj : collection) {
|
|
|
+ checkFields(obj);
|
|
|
+ }
|
|
|
+ } else if (value instanceof Map) {
|
|
|
+ Map<?, ?> map = (Map<?, ?>) value;
|
|
|
+ for (Object key : map.keySet()) {
|
|
|
+ checkFields(key);
|
|
|
+ }
|
|
|
+ for (Object v : map.values()) {
|
|
|
+ checkFields(v);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ checkFields(value);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* Returns a new query bound to the collection (a specific {@link DBCollection})
|
|
|
*
|
|
|
@@ -77,7 +135,6 @@ public class BaseDao<T extends BaseEntity> {
|
|
|
return datastore.createQuery(entityClass);
|
|
|
}
|
|
|
|
|
|
-
|
|
|
/**
|
|
|
* 全局过滤,如有需要,可重写该方法
|
|
|
*
|
|
|
@@ -147,7 +204,7 @@ public class BaseDao<T extends BaseEntity> {
|
|
|
* @param ignoreFields 不更新的字段
|
|
|
* @return the new UpdateOperations instance
|
|
|
*/
|
|
|
- public UpdateOperations<T> createUpdateOperations(@NotEmpty("t") T t, Set<String> ignoreFields) {
|
|
|
+ private UpdateOperations<T> createUpdateOperations(@NotEmpty("t") T t, Set<String> ignoreFields) {
|
|
|
UpdateOperations<T> operations = createUpdateOperations();
|
|
|
Field[] declaredFields = entityClass.getDeclaredFields();
|
|
|
// 通过反射遍历对象的成员变量,自动构造UpdateOperations
|
|
|
@@ -163,7 +220,7 @@ public class BaseDao<T extends BaseEntity> {
|
|
|
if (Modifier.isStatic(modifiers) || Modifier.isFinal(modifiers) || Modifier.isTransient(modifiers)) {
|
|
|
continue;
|
|
|
}
|
|
|
- Object value = getValue(field, t);
|
|
|
+ Object value = ObjectUtils.getValue(field, t);
|
|
|
// 如果值为空,则移除文档中的该字段
|
|
|
if (ObjectUtils.isEmpty(value)) {
|
|
|
operations.unset(name);
|
|
|
@@ -174,60 +231,6 @@ public class BaseDao<T extends BaseEntity> {
|
|
|
return operations;
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * 利用反射获取指定对象的指定字段的值
|
|
|
- *
|
|
|
- * @param field 指定字段
|
|
|
- * @param k 指定对象
|
|
|
- * @return 指定字段的值
|
|
|
- */
|
|
|
- private <K> Object getValue(@NotEmpty("field") String field, @NotEmpty("k") K k) throws IllegalStateException, NoSuchFieldException {
|
|
|
- return getValue(getField(field, k.getClass()), k);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 递归获取指定类的指定字段(包括父类的私有字段)
|
|
|
- *
|
|
|
- * @param field 指定字段
|
|
|
- * @param clazz 指定类
|
|
|
- * @return 指定字段
|
|
|
- * @throws NoSuchFieldException
|
|
|
- */
|
|
|
- private Field getField(@NotEmpty("field") String field, @NotEmpty("clazz") Class<?> clazz) throws NoSuchFieldException {
|
|
|
- try {
|
|
|
- return clazz.getDeclaredField(field);
|
|
|
- } catch (NoSuchFieldException e) {
|
|
|
- Class<?> superclass = clazz.getSuperclass();
|
|
|
- if (superclass != null) {
|
|
|
- return getField(field, superclass);
|
|
|
- }
|
|
|
- throw e;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 利用反射获取指定对象的指定字段的值
|
|
|
- *
|
|
|
- * @param field 指定字段
|
|
|
- * @param k 指定对象
|
|
|
- * @return 指定字段的值
|
|
|
- */
|
|
|
- private <K> Object getValue(Field field, @NotEmpty("k") K k) throws IllegalStateException {
|
|
|
- Object value;
|
|
|
- try {
|
|
|
- if (!field.isAccessible()) {
|
|
|
- field.setAccessible(true);
|
|
|
- value = field.get(k);
|
|
|
- field.setAccessible(false);
|
|
|
- } else {
|
|
|
- value = field.get(k);
|
|
|
- }
|
|
|
- } catch (SecurityException | IllegalArgumentException | IllegalAccessException e) {
|
|
|
- throw new IllegalStateException("通过反射取值失败", e);
|
|
|
- }
|
|
|
- return value;
|
|
|
- }
|
|
|
-
|
|
|
/**
|
|
|
* Saves an entity (Object) and updates the @Id field
|
|
|
*
|
|
|
@@ -291,58 +294,6 @@ public class BaseDao<T extends BaseEntity> {
|
|
|
return "已存在:{" + message.replace(":", "") + "}";
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * 对对象的字段进行检查,包括是否为空等,主要关注 {@link FieldProperty} 注解
|
|
|
- *
|
|
|
- * @param <K> 要检查的对象的类型,可与 {@link T} 不同
|
|
|
- * @param k 要检查的对象
|
|
|
- */
|
|
|
- public <K> void checkFields(@NotEmpty("k") K k) throws IllegalArgumentException, IllegalStateException {
|
|
|
- Class<?> clazz = k.getClass();
|
|
|
- Field[] declaredFields = clazz.getDeclaredFields();
|
|
|
- for (Field field : declaredFields) {
|
|
|
- int modifiers = field.getModifiers();
|
|
|
- // 不处理static修饰的变量
|
|
|
- if (Modifier.isStatic(modifiers)) {
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
- Embedded embedded = field.getAnnotation(Embedded.class);
|
|
|
- Reference reference = field.getAnnotation(Reference.class);
|
|
|
- FieldProperty fieldProperty = field.getAnnotation(FieldProperty.class);
|
|
|
- // 只有使用 {@link FieldProperty} 指定不可为空,或者是嵌入或引用对象,才处理
|
|
|
- if ((fieldProperty == null || fieldProperty.nullable()) && embedded == null && reference == null) {
|
|
|
- continue;
|
|
|
- }
|
|
|
- Object value = getValue(field, k);
|
|
|
-
|
|
|
- // 如果使用 {@link FieldProperty} 指定不可为空,但是值为空,则抛出异常
|
|
|
- if (fieldProperty != null && !fieldProperty.nullable() && ObjectUtils.isEmpty(value)) {
|
|
|
- throw new IllegalArgumentException("字段为空:" + clazz.getName() + "." + field.getName() + " = " + value);
|
|
|
- }
|
|
|
- // 如果是嵌入或引用对象,并且不为空,则递归检测
|
|
|
- if ((embedded != null || reference != null) && !ObjectUtils.isEmpty(value)) {
|
|
|
- // 如果是Collection
|
|
|
- if (value instanceof Collection) {
|
|
|
- Collection<?> collection = (Collection<?>) value;
|
|
|
- for (Object obj : collection) {
|
|
|
- checkFields(obj);
|
|
|
- }
|
|
|
- } else if (value instanceof Map) {
|
|
|
- Map<?, ?> map = (Map<?, ?>) value;
|
|
|
- for (Object key : map.keySet()) {
|
|
|
- checkFields(key);
|
|
|
- }
|
|
|
- for (Object v : map.values()) {
|
|
|
- checkFields(v);
|
|
|
- }
|
|
|
- } else {
|
|
|
- checkFields(value);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
/**
|
|
|
* 删除所有数据
|
|
|
*
|
|
|
@@ -433,12 +384,16 @@ public class BaseDao<T extends BaseEntity> {
|
|
|
*/
|
|
|
public int updatePart(@NotEmpty("json") String json) {
|
|
|
JSONObject jsonObject = JSONObject.parseObject(json);
|
|
|
- T t = JSONObject.parseObject(json, entityClass);
|
|
|
- if (t == null) {
|
|
|
- throw new IllegalArgumentException("解析得到的数据为空");
|
|
|
+ String code = jsonObject.getString("code");
|
|
|
+ if (StringUtils.isEmpty(code)) {
|
|
|
+ throw new IllegalArgumentException("未指定 code");
|
|
|
}
|
|
|
- String code = t.codeNotEmpty();
|
|
|
- jsonObject.remove("code");
|
|
|
+ // 不更新父类中的字段,可能包括 id, code, version 等
|
|
|
+ List<Field> parentFields = ObjectUtils.recursivelyGetParentField(entityClass);
|
|
|
+ for (Field field : parentFields) {
|
|
|
+ jsonObject.remove(field.getName());
|
|
|
+ }
|
|
|
+
|
|
|
UpdateOperations<T> operations = createUpdateOperations();
|
|
|
Set<String> keySet = jsonObject.keySet();
|
|
|
for (String key : keySet) {
|
|
|
@@ -453,7 +408,7 @@ public class BaseDao<T extends BaseEntity> {
|
|
|
if (Modifier.isStatic(modifiers) || Modifier.isFinal(modifiers) || Modifier.isTransient(modifiers)) {
|
|
|
continue;
|
|
|
}
|
|
|
- Object value = getValue(field, t);
|
|
|
+ Object value = jsonObject.getObject(field.getName(), field.getType());
|
|
|
// 如果值为空,则移除文档中的该字段
|
|
|
if (ObjectUtils.isEmpty(value)) {
|
|
|
operations.unset(key);
|
|
|
@@ -528,18 +483,11 @@ public class BaseDao<T extends BaseEntity> {
|
|
|
public T checkExist(@NotEmpty("code") String code) throws IllegalStateException {
|
|
|
T t = findOne(code);
|
|
|
if (t == null) {
|
|
|
- throw new IllegalStateException(collectionSimpleName() + "不存在:" + code);
|
|
|
+ throw new IllegalStateException(t.collectionSimpleName() + "不存在:" + code);
|
|
|
}
|
|
|
return t;
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * @return 集合简称
|
|
|
- */
|
|
|
- protected String collectionSimpleName() {
|
|
|
- return entityClass.getSimpleName();
|
|
|
- }
|
|
|
-
|
|
|
/**
|
|
|
* Find the given entities (by code);
|
|
|
*
|
|
|
@@ -619,7 +567,7 @@ public class BaseDao<T extends BaseEntity> {
|
|
|
if (!CollectionUtils.isEmpty(list)) {
|
|
|
for (T t : list) {
|
|
|
try {
|
|
|
- Object value = getValue(field, t);
|
|
|
+ Object value = ObjectUtils.recursivelyGetValue(field, t);
|
|
|
if (value != null) {
|
|
|
Class<?> valueClass = value.getClass();
|
|
|
if (clazz.isAssignableFrom(valueClass)) {
|