mirror of
https://github.com/hs-web/hsweb-framework.git
synced 2026-06-03 03:12:25 +08:00
refactor: 优化
This commit is contained in:
@@ -34,13 +34,13 @@ public class ValidateEventListener implements EventListener, Ordered {
|
||||
|
||||
if (resultHolder.isPresent()) {
|
||||
resultHolder
|
||||
.ifPresent(holder -> holder
|
||||
.invoke(LocaleUtils
|
||||
.doInReactive(() -> {
|
||||
tryValidate(type, context);
|
||||
return null;
|
||||
})
|
||||
));
|
||||
.ifPresent(holder -> holder
|
||||
.invoke(LocaleUtils
|
||||
.doInReactive(() -> {
|
||||
tryValidate(type, context);
|
||||
return null;
|
||||
})
|
||||
));
|
||||
} else {
|
||||
tryValidate(type, context);
|
||||
}
|
||||
@@ -48,7 +48,8 @@ public class ValidateEventListener implements EventListener, Ordered {
|
||||
|
||||
@SuppressWarnings("all")
|
||||
public void tryValidate(EventType type, EventContext context) {
|
||||
if (type == MappingEventTypes.insert_before || type == MappingEventTypes.save_before) {
|
||||
if (type == MappingEventTypes.insert_before
|
||||
|| type == MappingEventTypes.save_before) {
|
||||
|
||||
boolean single = context.get(MappingContextKeys.type).map("single"::equals).orElse(false);
|
||||
if (single) {
|
||||
@@ -60,10 +61,11 @@ public class ValidateEventListener implements EventListener, Ordered {
|
||||
context.get(MappingContextKeys.instance)
|
||||
.filter(List.class::isInstance)
|
||||
.map(List.class::cast)
|
||||
.ifPresent(lst -> lst.stream()
|
||||
.filter(Entity.class::isInstance)
|
||||
.map(Entity.class::cast)
|
||||
.forEach(e -> ((Entity) e).tryValidate(CreateGroup.class))
|
||||
.ifPresent(lst -> lst
|
||||
.stream()
|
||||
.filter(Entity.class::isInstance)
|
||||
.map(Entity.class::cast)
|
||||
.forEach(e -> ((Entity) e).tryValidate(CreateGroup.class))
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ public interface CrudService<E, K> {
|
||||
return getRepository().createDelete();
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true, transactionManager = TransactionManagers.jdbcTransactionManager)
|
||||
@Transactional( readOnly = true, transactionManager = TransactionManagers.jdbcTransactionManager)
|
||||
default Optional<E> findById(K id) {
|
||||
return getRepository()
|
||||
.findById(id);
|
||||
@@ -48,48 +48,48 @@ public interface CrudService<E, K> {
|
||||
.findById(id);
|
||||
}
|
||||
|
||||
@Transactional(transactionManager = TransactionManagers.jdbcTransactionManager)
|
||||
@Transactional(rollbackFor = Throwable.class,transactionManager = TransactionManagers.jdbcTransactionManager)
|
||||
default SaveResult save(Collection<E> entityArr) {
|
||||
return getRepository()
|
||||
.save(entityArr);
|
||||
}
|
||||
|
||||
@Transactional(transactionManager = TransactionManagers.jdbcTransactionManager)
|
||||
@Transactional(rollbackFor = Throwable.class,transactionManager = TransactionManagers.jdbcTransactionManager)
|
||||
default int insert(Collection<E> entityArr) {
|
||||
return getRepository()
|
||||
.insertBatch(entityArr);
|
||||
}
|
||||
|
||||
@Transactional(transactionManager = TransactionManagers.jdbcTransactionManager)
|
||||
@Transactional(rollbackFor = Throwable.class, transactionManager = TransactionManagers.jdbcTransactionManager)
|
||||
default void insert(E entityArr) {
|
||||
getRepository()
|
||||
.insert(entityArr);
|
||||
}
|
||||
|
||||
@Transactional(transactionManager = TransactionManagers.jdbcTransactionManager)
|
||||
@Transactional(rollbackFor = Throwable.class,transactionManager = TransactionManagers.jdbcTransactionManager)
|
||||
default int updateById(K id, E entityArr) {
|
||||
return getRepository()
|
||||
.updateById(id, entityArr);
|
||||
}
|
||||
|
||||
@Transactional(transactionManager = TransactionManagers.jdbcTransactionManager)
|
||||
@Transactional(rollbackFor = Throwable.class,transactionManager = TransactionManagers.jdbcTransactionManager)
|
||||
default SaveResult save(E entity) {
|
||||
return getRepository()
|
||||
.save(Collections.singletonList(entity));
|
||||
}
|
||||
|
||||
@Transactional(transactionManager = TransactionManagers.jdbcTransactionManager)
|
||||
@Transactional(rollbackFor = Throwable.class,transactionManager = TransactionManagers.jdbcTransactionManager)
|
||||
default SaveResult save(List<E> entities) {
|
||||
return getRepository()
|
||||
.save(entities);
|
||||
}
|
||||
|
||||
@Transactional(transactionManager = TransactionManagers.jdbcTransactionManager)
|
||||
@Transactional(rollbackFor = Throwable.class,transactionManager = TransactionManagers.jdbcTransactionManager)
|
||||
default int deleteById(Collection<K> idArr) {
|
||||
return getRepository().deleteById(idArr);
|
||||
}
|
||||
|
||||
@Transactional(transactionManager = TransactionManagers.jdbcTransactionManager)
|
||||
@Transactional(rollbackFor = Throwable.class,transactionManager = TransactionManagers.jdbcTransactionManager)
|
||||
default int deleteById(K idArr) {
|
||||
return deleteById(Collections.singletonList(idArr));
|
||||
}
|
||||
|
||||
@@ -34,48 +34,55 @@ public interface EnableCacheReactiveCrudService<E, K> extends ReactiveCrudServic
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(transactionManager = TransactionManagers.reactiveTransactionManager)
|
||||
@Transactional(rollbackFor = Throwable.class, transactionManager = TransactionManagers.reactiveTransactionManager)
|
||||
default Mono<Integer> updateById(K id, E data) {
|
||||
return updateById(id, Mono.just(data));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Throwable.class, transactionManager = TransactionManagers.reactiveTransactionManager)
|
||||
default Mono<Integer> updateById(K id, Mono<E> entityPublisher) {
|
||||
return registerClearCache(Collections.singleton("id:" + id))
|
||||
.then(ReactiveCrudService.super.updateById(id, entityPublisher));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Throwable.class, transactionManager = TransactionManagers.reactiveTransactionManager)
|
||||
default Mono<SaveResult> save(Collection<E> collection) {
|
||||
return registerClearCache()
|
||||
.then(ReactiveCrudService.super.save(collection));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Throwable.class, transactionManager = TransactionManagers.reactiveTransactionManager)
|
||||
default Mono<SaveResult> save(E data) {
|
||||
return registerClearCache()
|
||||
.then(ReactiveCrudService.super.save(data));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Throwable.class, transactionManager = TransactionManagers.reactiveTransactionManager)
|
||||
default Mono<SaveResult> save(Publisher<E> entityPublisher) {
|
||||
return registerClearCache()
|
||||
.then(ReactiveCrudService.super.save(entityPublisher));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Throwable.class, transactionManager = TransactionManagers.reactiveTransactionManager)
|
||||
default Mono<Integer> insert(E data) {
|
||||
return registerClearCache()
|
||||
.then(ReactiveCrudService.super.insert(data));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Throwable.class, transactionManager = TransactionManagers.reactiveTransactionManager)
|
||||
default Mono<Integer> insert(Publisher<E> entityPublisher) {
|
||||
return registerClearCache()
|
||||
.then(ReactiveCrudService.super.insert(entityPublisher));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Throwable.class, transactionManager = TransactionManagers.reactiveTransactionManager)
|
||||
default Mono<Integer> insertBatch(Publisher<? extends Collection<E>> entityPublisher) {
|
||||
return registerClearCache()
|
||||
.then(ReactiveCrudService.super.insertBatch(entityPublisher));
|
||||
@@ -106,12 +113,13 @@ public interface EnableCacheReactiveCrudService<E, K> extends ReactiveCrudServic
|
||||
|
||||
|
||||
@Override
|
||||
@Transactional(transactionManager = TransactionManagers.reactiveTransactionManager)
|
||||
@Transactional(rollbackFor = Throwable.class, transactionManager = TransactionManagers.reactiveTransactionManager)
|
||||
default Mono<Integer> deleteById(K id) {
|
||||
return deleteById(Mono.just(id));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Throwable.class, transactionManager = TransactionManagers.reactiveTransactionManager)
|
||||
default Mono<Integer> deleteById(Publisher<K> idPublisher) {
|
||||
Flux<K> cache = Flux.from(idPublisher).cache();
|
||||
return cache
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package org.hswebframework.web.crud.service;
|
||||
|
||||
import org.hswebframework.ezorm.rdb.mapping.SyncRepository;
|
||||
import org.hswebframework.web.api.crud.entity.TransactionManagers;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
public abstract class GenericCrudService<E,K> implements CrudService<E,K> {
|
||||
|
||||
|
||||
@@ -90,13 +90,13 @@ public interface ReactiveCrudService<E, K> {
|
||||
}
|
||||
|
||||
|
||||
@Transactional(readOnly = true, transactionManager = TransactionManagers.reactiveTransactionManager)
|
||||
@Transactional(rollbackFor = Throwable.class, transactionManager = TransactionManagers.reactiveTransactionManager)
|
||||
default Mono<E> findById(K id) {
|
||||
return getRepository()
|
||||
.findById(id);
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true, transactionManager = TransactionManagers.reactiveTransactionManager)
|
||||
@Transactional(rollbackFor = Throwable.class, transactionManager = TransactionManagers.reactiveTransactionManager)
|
||||
default Flux<E> findById(Collection<K> publisher) {
|
||||
return getRepository()
|
||||
.findById(publisher);
|
||||
@@ -114,61 +114,61 @@ public interface ReactiveCrudService<E, K> {
|
||||
.findById(publisher);
|
||||
}
|
||||
|
||||
@Transactional(transactionManager = TransactionManagers.reactiveTransactionManager)
|
||||
@Transactional(rollbackFor = Throwable.class, transactionManager = TransactionManagers.reactiveTransactionManager)
|
||||
default Mono<SaveResult> save(Publisher<E> entityPublisher) {
|
||||
return getRepository()
|
||||
.save(entityPublisher);
|
||||
}
|
||||
|
||||
@Transactional(transactionManager = TransactionManagers.reactiveTransactionManager)
|
||||
@Transactional(rollbackFor = Throwable.class, transactionManager = TransactionManagers.reactiveTransactionManager)
|
||||
default Mono<SaveResult> save(E data) {
|
||||
return getRepository()
|
||||
.save(data);
|
||||
}
|
||||
|
||||
@Transactional(transactionManager = TransactionManagers.reactiveTransactionManager)
|
||||
@Transactional(rollbackFor = Throwable.class, transactionManager = TransactionManagers.reactiveTransactionManager)
|
||||
default Mono<SaveResult> save(Collection<E> collection) {
|
||||
return getRepository()
|
||||
.save(collection);
|
||||
}
|
||||
|
||||
@Transactional(transactionManager = TransactionManagers.reactiveTransactionManager)
|
||||
@Transactional(rollbackFor = Throwable.class, transactionManager = TransactionManagers.reactiveTransactionManager)
|
||||
default Mono<Integer> updateById(K id, Mono<E> entityPublisher) {
|
||||
return getRepository()
|
||||
.updateById(id, entityPublisher);
|
||||
}
|
||||
|
||||
@Transactional(transactionManager = TransactionManagers.reactiveTransactionManager)
|
||||
@Transactional(rollbackFor = Throwable.class, transactionManager = TransactionManagers.reactiveTransactionManager)
|
||||
default Mono<Integer> updateById(K id, E data) {
|
||||
return getRepository()
|
||||
.updateById(id, Mono.just(data));
|
||||
}
|
||||
|
||||
@Transactional(transactionManager = TransactionManagers.reactiveTransactionManager)
|
||||
@Transactional(rollbackFor = Throwable.class, transactionManager = TransactionManagers.reactiveTransactionManager)
|
||||
default Mono<Integer> insertBatch(Publisher<? extends Collection<E>> entityPublisher) {
|
||||
return getRepository()
|
||||
.insertBatch(entityPublisher);
|
||||
}
|
||||
|
||||
@Transactional(transactionManager = TransactionManagers.reactiveTransactionManager)
|
||||
@Transactional(rollbackFor = Throwable.class, transactionManager = TransactionManagers.reactiveTransactionManager)
|
||||
default Mono<Integer> insert(Publisher<E> entityPublisher) {
|
||||
return getRepository()
|
||||
.insert(entityPublisher);
|
||||
}
|
||||
|
||||
@Transactional(transactionManager = TransactionManagers.reactiveTransactionManager)
|
||||
@Transactional(rollbackFor = Throwable.class, transactionManager = TransactionManagers.reactiveTransactionManager)
|
||||
default Mono<Integer> insert(E data) {
|
||||
return getRepository()
|
||||
.insert(Mono.just(data));
|
||||
}
|
||||
|
||||
@Transactional(transactionManager = TransactionManagers.reactiveTransactionManager)
|
||||
@Transactional(rollbackFor = Throwable.class, transactionManager = TransactionManagers.reactiveTransactionManager)
|
||||
default Mono<Integer> deleteById(Publisher<K> idPublisher) {
|
||||
return getRepository()
|
||||
.deleteById(idPublisher);
|
||||
}
|
||||
|
||||
@Transactional(transactionManager = TransactionManagers.reactiveTransactionManager)
|
||||
@Transactional(rollbackFor = Throwable.class, transactionManager = TransactionManagers.reactiveTransactionManager)
|
||||
default Mono<Integer> deleteById(K id) {
|
||||
return getRepository()
|
||||
.deleteById(Mono.just(id));
|
||||
|
||||
@@ -174,23 +174,23 @@ public interface ReactiveTreeSortEntityService<E extends TreeSortSupportEntity<K
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(transactionManager = TransactionManagers.reactiveTransactionManager)
|
||||
@Transactional(rollbackFor = Throwable.class, transactionManager = TransactionManagers.reactiveTransactionManager)
|
||||
default Mono<Integer> insert(Publisher<E> entityPublisher) {
|
||||
return insertBatch(Flux.from(entityPublisher).collectList());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(transactionManager = TransactionManagers.reactiveTransactionManager)
|
||||
@Transactional(rollbackFor = Throwable.class, transactionManager = TransactionManagers.reactiveTransactionManager)
|
||||
default Mono<Integer> insert(E data) {
|
||||
return this.insertBatch(Flux.just(Collections.singletonList(data)));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(transactionManager = TransactionManagers.reactiveTransactionManager)
|
||||
@Transactional(rollbackFor = Throwable.class, transactionManager = TransactionManagers.reactiveTransactionManager)
|
||||
default Mono<Integer> insertBatch(Publisher<? extends Collection<E>> entityPublisher) {
|
||||
return this
|
||||
.getRepository()
|
||||
.insertBatch(new TreeSortServiceHelper<>(this)
|
||||
.insertBatch(new ReactiveTreeSortServiceHelper<>(this)
|
||||
.prepare(Flux.from(entityPublisher)
|
||||
.flatMapIterable(Function.identity()))
|
||||
// .doOnNext(e -> e.tryValidate(CreateGroup.class))
|
||||
@@ -201,105 +201,11 @@ public interface ReactiveTreeSortEntityService<E extends TreeSortSupportEntity<K
|
||||
return 200;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
default Mono<E> applyTreeProperty(E ele) {
|
||||
if (StringUtils.hasText(ele.getPath()) ||
|
||||
ObjectUtils.isEmpty(ele.getParentId())) {
|
||||
return Mono.just(ele);
|
||||
}
|
||||
|
||||
return this.checkCyclicDependency(ele.getId(), ele)
|
||||
.then(this.findById(ele.getParentId())
|
||||
.doOnNext(parent -> ele.setPath(parent.getPath() + "-" + RandomUtil.randomChar(4))))
|
||||
.thenReturn(ele);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
//校验是否有循环依赖,修改父节点为自己的子节点?
|
||||
default Mono<E> checkCyclicDependency(K id, E ele) {
|
||||
if (ObjectUtils.isEmpty(id)) {
|
||||
return Mono.empty();
|
||||
}
|
||||
return this
|
||||
.queryIncludeChildren(Collections.singletonList(id))
|
||||
.doOnNext(e -> {
|
||||
if (Objects.equals(ele.getParentId(), e.getId())) {
|
||||
throw new ValidationException.NoStackTrace("parentId", "error.tree_entity_cyclic_dependency");
|
||||
}
|
||||
})
|
||||
.then(Mono.just(ele));
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
default Mono<Collection<E>> checkParentId(Collection<E> source) {
|
||||
|
||||
Set<K> idSet = source
|
||||
.stream()
|
||||
.map(TreeSupportEntity::getId)
|
||||
.filter(e -> !ObjectUtils.isEmpty(e))
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
if (idSet.isEmpty()) {
|
||||
return Mono.just(source);
|
||||
}
|
||||
|
||||
Set<K> readyToCheck = source
|
||||
.stream()
|
||||
.map(TreeSupportEntity::getParentId)
|
||||
.filter(e -> !ObjectUtils.isEmpty(e) && !idSet.contains(e))
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
if (readyToCheck.isEmpty()) {
|
||||
return Mono.just(source);
|
||||
}
|
||||
|
||||
return this
|
||||
.createQuery()
|
||||
.select("id")
|
||||
.in("id", readyToCheck)
|
||||
.fetch()
|
||||
.doOnNext(e -> readyToCheck.remove(e.getId()))
|
||||
.then(Mono.fromSupplier(() -> {
|
||||
if (!readyToCheck.isEmpty()) {
|
||||
throw new ValidationException(
|
||||
"error.tree_entity_parent_id_not_exist",
|
||||
Collections.singletonList(
|
||||
new ValidationException.Detail(
|
||||
"parentId",
|
||||
"error.tree_entity_parent_id_not_exist",
|
||||
readyToCheck))
|
||||
);
|
||||
}
|
||||
return source;
|
||||
}));
|
||||
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
//重构子节点的path
|
||||
default void refactorChildPath(K id, Function<K, Collection<E>> childGetter, String path, Consumer<E> pathAccepter) {
|
||||
|
||||
Collection<E> children = childGetter.apply(id);
|
||||
if (CollectionUtils.isEmpty(children)) {
|
||||
return;
|
||||
}
|
||||
for (E child : children) {
|
||||
if (ObjectUtils.isEmpty(path)) {
|
||||
child.setPath(RandomUtil.randomChar(4));
|
||||
} else {
|
||||
child.setPath(path + "-" + RandomUtil.randomChar(4));
|
||||
}
|
||||
pathAccepter.accept(child);
|
||||
this.refactorChildPath(child.getId(), childGetter, child.getPath(), pathAccepter);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Throwable.class,
|
||||
transactionManager = TransactionManagers.reactiveTransactionManager)
|
||||
default Mono<SaveResult> save(Publisher<E> entityPublisher) {
|
||||
return new TreeSortServiceHelper<>(this)
|
||||
return new ReactiveTreeSortServiceHelper<>(this)
|
||||
.prepare(Flux.from(entityPublisher))
|
||||
// .doOnNext(e -> e.tryValidate(CreateGroup.class))
|
||||
.buffer(getBufferSize())
|
||||
@@ -310,7 +216,7 @@ public interface ReactiveTreeSortEntityService<E extends TreeSortSupportEntity<K
|
||||
|
||||
@Deprecated
|
||||
default Flux<E> tryRefactorPath(Flux<E> stream) {
|
||||
return new TreeSortServiceHelper<>(this).prepare(stream);
|
||||
return new ReactiveTreeSortServiceHelper<>(this).prepare(stream);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
package org.hswebframework.web.crud.service;
|
||||
|
||||
import org.hswebframework.web.api.crud.entity.TreeSortSupportEntity;
|
||||
import org.hswebframework.web.id.IDGenerator;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class ReactiveTreeSortServiceHelper<E extends TreeSortSupportEntity<PK>, PK> extends TreeSortServiceHelper<E, PK> {
|
||||
|
||||
private final ReactiveTreeSortEntityService<E, PK> service;
|
||||
|
||||
public ReactiveTreeSortServiceHelper(ReactiveTreeSortEntityService<E, PK> service) {
|
||||
this.service = service;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IDGenerator<PK> getIdGenerator() {
|
||||
return service.getIDGenerator();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applyChildren(E parent, List<E> children) {
|
||||
service.setChildren(parent, children);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isRootNode(E node) {
|
||||
return service.isRootNode(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Flux<E> queryIncludeChildren(Collection<PK> idList) {
|
||||
return service.queryIncludeChildren(idList);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Flux<E> queryById(Collection<PK> idList) {
|
||||
return service.findById(idList);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package org.hswebframework.web.crud.service;
|
||||
|
||||
import org.hswebframework.web.api.crud.entity.TreeSortSupportEntity;
|
||||
import org.hswebframework.web.id.IDGenerator;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class SyncTreeSortServiceHelper<E extends TreeSortSupportEntity<PK>, PK> extends TreeSortServiceHelper<E, PK> {
|
||||
|
||||
private final TreeSortEntityService<E, PK> service;
|
||||
|
||||
public SyncTreeSortServiceHelper(TreeSortEntityService<E, PK> service) {
|
||||
this.service = service;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IDGenerator<PK> getIdGenerator() {
|
||||
return service.getIDGenerator();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applyChildren(E parent, List<E> children) {
|
||||
service.setChildren(parent, children);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isRootNode(E node) {
|
||||
return service.isRootNode(node);
|
||||
}
|
||||
|
||||
public List<E> prepare(Collection<E> source) {
|
||||
return super
|
||||
.prepare(Flux.fromIterable(source))
|
||||
.toStream()
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("all")
|
||||
protected Flux<E> queryIncludeChildren(Collection<PK> idList) {
|
||||
return Flux.fromIterable(service.queryIncludeChildren(idList));
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("all")
|
||||
protected Flux<E> queryById(Collection<PK> idList) {
|
||||
return Flux.fromIterable(service.findById(idList));
|
||||
}
|
||||
}
|
||||
@@ -25,124 +25,98 @@ import java.util.stream.Stream;
|
||||
* @see GenericReactiveTreeSupportCrudService
|
||||
*/
|
||||
public interface TreeSortEntityService<E extends TreeSortSupportEntity<K>, K>
|
||||
extends CrudService<E, K> {
|
||||
extends CrudService<E, K> {
|
||||
|
||||
@Transactional(readOnly = true, transactionManager = TransactionManagers.jdbcTransactionManager)
|
||||
default List<E> queryResultToTree(QueryParamEntity paramEntity) {
|
||||
return TreeSupportEntity
|
||||
.list2tree(query(paramEntity),
|
||||
this::setChildren,
|
||||
this::createRootNodePredicate);
|
||||
.list2tree(query(paramEntity),
|
||||
this::setChildren,
|
||||
this::createRootNodePredicate);
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true, transactionManager = TransactionManagers.jdbcTransactionManager)
|
||||
default List<E> queryIncludeChildrenTree(QueryParamEntity paramEntity) {
|
||||
|
||||
return TreeSupportEntity
|
||||
.list2tree(queryIncludeChildren(paramEntity),
|
||||
this::setChildren,
|
||||
this::createRootNodePredicate);
|
||||
.list2tree(queryIncludeChildren(paramEntity),
|
||||
this::setChildren,
|
||||
this::createRootNodePredicate);
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true, transactionManager = TransactionManagers.jdbcTransactionManager)
|
||||
default List<E> queryIncludeChildren(Collection<K> idList) {
|
||||
return findById(idList)
|
||||
.stream()
|
||||
.flatMap(e -> createQuery()
|
||||
.where()
|
||||
.like$("path", e.getPath())
|
||||
.fetch()
|
||||
.stream())
|
||||
.collect(Collectors.toList());
|
||||
.stream()
|
||||
.flatMap(e -> createQuery()
|
||||
.where()
|
||||
.like$("path", e.getPath())
|
||||
.fetch()
|
||||
.stream())
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true, transactionManager = TransactionManagers.jdbcTransactionManager)
|
||||
default List<E> queryIncludeChildren(QueryParamEntity queryParam) {
|
||||
return query(queryParam)
|
||||
.stream()
|
||||
.flatMap(e -> createQuery()
|
||||
.where()
|
||||
.like$("path", e.getPath())
|
||||
.fetch()
|
||||
.stream())
|
||||
.collect(Collectors.toList());
|
||||
.stream()
|
||||
.flatMap(e -> createQuery()
|
||||
.where()
|
||||
.like$("path", e.getPath())
|
||||
.fetch()
|
||||
.stream())
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Throwable.class, transactionManager = TransactionManagers.jdbcTransactionManager)
|
||||
default void insert(E entityPublisher) {
|
||||
insert(Collections.singletonList(entityPublisher));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Throwable.class, transactionManager = TransactionManagers.jdbcTransactionManager)
|
||||
default int insert(Collection<E> entityPublisher) {
|
||||
return this
|
||||
.getRepository()
|
||||
.insertBatch(entityPublisher
|
||||
.stream()
|
||||
.flatMap(this::applyTreeProperty)
|
||||
.flatMap(e -> TreeSupportEntity
|
||||
.expandTree2List(e, getIDGenerator())
|
||||
.stream())
|
||||
.collect(Collectors.toList())
|
||||
);
|
||||
}
|
||||
|
||||
default Stream<E> applyTreeProperty(E ele) {
|
||||
if (StringUtils.hasText(ele.getPath()) ||
|
||||
ObjectUtils.isEmpty(ele.getParentId())) {
|
||||
return Stream.of(ele);
|
||||
}
|
||||
|
||||
this.checkCyclicDependency(ele.getId(), ele);
|
||||
this.findById(ele.getParentId())
|
||||
.ifPresent(parent -> ele.setPath(parent.getPath() + "-" + RandomUtil.randomChar(4)));
|
||||
return Stream.of(ele);
|
||||
}
|
||||
|
||||
//校验是否有循环依赖,修改父节点为自己的子节点?
|
||||
default void checkCyclicDependency(K id, E ele) {
|
||||
if (ObjectUtils.isEmpty(id)) {
|
||||
return;
|
||||
}
|
||||
for (E e : this.queryIncludeChildren(Collections.singletonList(id))) {
|
||||
if (Objects.equals(ele.getParentId(), e.getId())) {
|
||||
throw new IllegalArgumentException("不能修改父节点为自己或者自己的子节点");
|
||||
}
|
||||
}
|
||||
|
||||
return new SyncTreeSortServiceHelper<>(this)
|
||||
.prepare(Flux.fromIterable(entityPublisher))
|
||||
.buffer(getBufferSize())
|
||||
.map(this.getRepository()::insertBatch)
|
||||
.reduce(Math::addExact)
|
||||
.blockOptional()
|
||||
.orElse(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Throwable.class, transactionManager = TransactionManagers.jdbcTransactionManager)
|
||||
default SaveResult save(List<E> entities) {
|
||||
return this.getRepository()
|
||||
.save(entities
|
||||
.stream()
|
||||
.flatMap(this::applyTreeProperty)
|
||||
//把树结构平铺
|
||||
.flatMap(e -> TreeSupportEntity
|
||||
.expandTree2List(e, getIDGenerator())
|
||||
.stream())
|
||||
.collect(Collectors.toList())
|
||||
);
|
||||
return new SyncTreeSortServiceHelper<>(this)
|
||||
.prepare(Flux.fromIterable(entities))
|
||||
.buffer(getBufferSize())
|
||||
.map(this.getRepository()::save)
|
||||
.reduce(SaveResult::merge)
|
||||
.blockOptional()
|
||||
.orElse(SaveResult.of(0,0));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Throwable.class, transactionManager = TransactionManagers.jdbcTransactionManager)
|
||||
default int updateById(K id, E entity) {
|
||||
entity.setId(id);
|
||||
return this.save(entity).getTotal();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Throwable.class, transactionManager = TransactionManagers.jdbcTransactionManager)
|
||||
default int deleteById(Collection<K> idPublisher) {
|
||||
List<E> dataList = findById(idPublisher);
|
||||
return dataList
|
||||
.stream()
|
||||
.map(e -> createDelete()
|
||||
.where()
|
||||
.like$(e::getPath)
|
||||
.execute())
|
||||
.mapToInt(Integer::intValue)
|
||||
.sum();
|
||||
.stream()
|
||||
.map(e -> createDelete()
|
||||
.where()
|
||||
.like$(e::getPath)
|
||||
.execute())
|
||||
.mapToInt(Integer::intValue)
|
||||
.sum();
|
||||
}
|
||||
|
||||
IDGenerator<K> getIDGenerator();
|
||||
@@ -153,6 +127,10 @@ public interface TreeSortEntityService<E extends TreeSortSupportEntity<K>, K>
|
||||
return entity.getChildren();
|
||||
}
|
||||
|
||||
default int getBufferSize() {
|
||||
return 200;
|
||||
}
|
||||
|
||||
default Predicate<E> createRootNodePredicate(TreeSupportEntity.TreeHelper<E, K> helper) {
|
||||
return node -> {
|
||||
if (isRootNode(node)) {
|
||||
|
||||
@@ -6,6 +6,7 @@ import org.hswebframework.utils.RandomUtil;
|
||||
import org.hswebframework.web.api.crud.entity.TreeSortSupportEntity;
|
||||
import org.hswebframework.web.api.crud.entity.TreeSupportEntity;
|
||||
import org.hswebframework.web.exception.ValidationException;
|
||||
import org.hswebframework.web.id.IDGenerator;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
@@ -16,54 +17,59 @@ import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class TreeSortServiceHelper<E extends TreeSortSupportEntity<PK>, PK> {
|
||||
public abstract class TreeSortServiceHelper<E extends TreeSortSupportEntity<PK>, PK> {
|
||||
|
||||
//包含子节点的数据
|
||||
private Map<PK, E> allData;
|
||||
protected Map<PK, E> allData;
|
||||
|
||||
private Map<PK, E> oldData;
|
||||
protected Map<PK, E> oldData;
|
||||
|
||||
private Map<PK, E> thisTime;
|
||||
protected Map<PK, E> thisTime;
|
||||
|
||||
private Map<PK, E> readyToSave;
|
||||
protected Map<PK, E> readyToSave;
|
||||
|
||||
private final Map<PK, Map<PK, E>> childrenMapping = new LinkedHashMap<>();
|
||||
protected final Map<PK, Map<PK, E>> childrenMapping = new LinkedHashMap<>();
|
||||
|
||||
private final ReactiveTreeSortEntityService<E, PK> service;
|
||||
protected abstract IDGenerator<PK> getIdGenerator();
|
||||
|
||||
TreeSortServiceHelper(ReactiveTreeSortEntityService<E, PK> service) {
|
||||
this.service = service;
|
||||
}
|
||||
protected abstract void applyChildren(E parent, List<E> children);
|
||||
|
||||
Flux<E> prepare(Flux<E> source) {
|
||||
protected abstract boolean isRootNode(E node);
|
||||
|
||||
protected abstract Flux<E> queryIncludeChildren(Collection<PK> idList);
|
||||
|
||||
protected abstract Flux<E> queryById(Collection<PK> idList);
|
||||
|
||||
|
||||
public Flux<E> prepare(Flux<E> source) {
|
||||
Flux<E> cache = source
|
||||
.flatMapIterable(e -> TreeSupportEntity.expandTree2List(e, service.getIDGenerator()))
|
||||
.collectList()
|
||||
.flatMapIterable(list -> {
|
||||
.flatMapIterable(e -> TreeSupportEntity.expandTree2List(e, getIdGenerator()))
|
||||
.collectList()
|
||||
.flatMapIterable(list -> {
|
||||
|
||||
Map<PK, E> map = list
|
||||
.stream()
|
||||
.filter(e -> e.getId() != null)
|
||||
.collect(Collectors.toMap(
|
||||
TreeSupportEntity::getId,
|
||||
Function.identity(),
|
||||
(a, b) -> a
|
||||
));
|
||||
//重新组装树结构
|
||||
TreeSupportEntity.list2tree(list,
|
||||
service::setChildren,
|
||||
(Predicate<E>) e -> service.isRootNode(e) || map.get(e.getParentId()) == null);
|
||||
Map<PK, E> map = list
|
||||
.stream()
|
||||
.filter(e -> e.getId() != null)
|
||||
.collect(Collectors.toMap(
|
||||
TreeSupportEntity::getId,
|
||||
Function.identity(),
|
||||
(a, b) -> a
|
||||
));
|
||||
//重新组装树结构
|
||||
TreeSupportEntity.list2tree(list,
|
||||
this::applyChildren,
|
||||
(Predicate<E>) e -> isRootNode(e) || map.get(e.getParentId()) == null);
|
||||
|
||||
return list;
|
||||
})
|
||||
.cache();
|
||||
return list;
|
||||
})
|
||||
.cache();
|
||||
|
||||
return init(cache)
|
||||
.then(Mono.defer(this::checkParentId))
|
||||
.then(Mono.fromRunnable(this::checkCyclicDependency))
|
||||
.then(Mono.fromRunnable(this::refactorPath))
|
||||
.thenMany(Flux.defer(() -> Flux.fromIterable(readyToSave.values())))
|
||||
.doOnNext(this::refactor);
|
||||
.then(Mono.defer(this::checkParentId))
|
||||
.then(Mono.fromRunnable(this::checkCyclicDependency))
|
||||
.then(Mono.fromRunnable(this::refactorPath))
|
||||
.thenMany(Flux.defer(() -> Flux.fromIterable(readyToSave.values())))
|
||||
.doOnNext(this::refactor);
|
||||
}
|
||||
|
||||
private Mono<Void> init(Flux<E> source) {
|
||||
@@ -73,49 +79,49 @@ public class TreeSortServiceHelper<E extends TreeSortSupportEntity<PK>, PK> {
|
||||
readyToSave = new LinkedHashMap<>();
|
||||
|
||||
Mono<Map<PK, E>> allDataFetcher =
|
||||
source
|
||||
.mapNotNull(e -> {
|
||||
source
|
||||
.mapNotNull(e -> {
|
||||
|
||||
if (e.getId() != null) {
|
||||
thisTime.put(e.getId(), e);
|
||||
}
|
||||
|
||||
return e.getId();
|
||||
})
|
||||
.collect(Collectors.toSet())
|
||||
.flatMap(list -> service
|
||||
.queryIncludeChildren(list)
|
||||
.collectMap(TreeSupportEntity::getId, Function.identity()));
|
||||
return allDataFetcher
|
||||
.doOnNext(includeChildren -> {
|
||||
//旧的数据
|
||||
for (E value : thisTime.values()) {
|
||||
E old = includeChildren.get(value.getId());
|
||||
if (null != old) {
|
||||
this.oldData.put(value.getId(), old);
|
||||
}
|
||||
if (e.getId() != null) {
|
||||
thisTime.put(e.getId(), e);
|
||||
}
|
||||
|
||||
readyToSave.putAll(thisTime);
|
||||
|
||||
allData.putAll(includeChildren);
|
||||
allData.putAll(this.thisTime);
|
||||
initChildren();
|
||||
|
||||
return e.getId();
|
||||
})
|
||||
.then();
|
||||
.collect(Collectors.toSet())
|
||||
.flatMap(list ->
|
||||
queryIncludeChildren(list)
|
||||
.collectMap(TreeSupportEntity::getId, Function.identity()));
|
||||
return allDataFetcher
|
||||
.doOnNext(includeChildren -> {
|
||||
//旧的数据
|
||||
for (E value : thisTime.values()) {
|
||||
E old = includeChildren.get(value.getId());
|
||||
if (null != old) {
|
||||
this.oldData.put(value.getId(), old);
|
||||
}
|
||||
}
|
||||
|
||||
readyToSave.putAll(thisTime);
|
||||
|
||||
allData.putAll(includeChildren);
|
||||
allData.putAll(this.thisTime);
|
||||
initChildren();
|
||||
|
||||
})
|
||||
.then();
|
||||
}
|
||||
|
||||
private void initChildren() {
|
||||
childrenMapping.clear();
|
||||
|
||||
for (E value : allData.values()) {
|
||||
if (service.isRootNode(value) || value.getId() == null) {
|
||||
if (isRootNode(value) || value.getId() == null) {
|
||||
continue;
|
||||
}
|
||||
childrenMapping
|
||||
.computeIfAbsent(value.getParentId(), ignore -> new LinkedHashMap<>())
|
||||
.put(value.getId(), value);
|
||||
.computeIfAbsent(value.getParentId(), ignore -> new LinkedHashMap<>())
|
||||
.put(value.getId(), value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,43 +150,40 @@ public class TreeSortServiceHelper<E extends TreeSortSupportEntity<PK>, PK> {
|
||||
}
|
||||
|
||||
Set<PK> readyToCheck = thisTime
|
||||
.values()
|
||||
.stream()
|
||||
.map(TreeSupportEntity::getParentId)
|
||||
.filter(e -> !ObjectUtils.isEmpty(e) && !allData.containsKey(e))
|
||||
.collect(Collectors.toSet());
|
||||
.values()
|
||||
.stream()
|
||||
.map(TreeSupportEntity::getParentId)
|
||||
.filter(e -> !ObjectUtils.isEmpty(e) && !allData.containsKey(e))
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
if (readyToCheck.isEmpty()) {
|
||||
return Mono.empty();
|
||||
}
|
||||
return service
|
||||
.createQuery()
|
||||
.in("id", readyToCheck)
|
||||
.fetch()
|
||||
.doOnNext(e -> {
|
||||
allData.put(e.getId(), e);
|
||||
readyToCheck.remove(e.getId());
|
||||
})
|
||||
.then(Mono.fromRunnable(() -> {
|
||||
if (!readyToCheck.isEmpty()) {
|
||||
throw new ValidationException(
|
||||
return queryById(readyToCheck)
|
||||
.doOnNext(e -> {
|
||||
allData.put(e.getId(), e);
|
||||
readyToCheck.remove(e.getId());
|
||||
})
|
||||
.then(Mono.fromRunnable(() -> {
|
||||
if (!readyToCheck.isEmpty()) {
|
||||
throw new ValidationException(
|
||||
"error.tree_entity_parent_id_not_exist",
|
||||
Collections.singletonList(
|
||||
new ValidationException.Detail(
|
||||
"parentId",
|
||||
"error.tree_entity_parent_id_not_exist",
|
||||
Collections.singletonList(
|
||||
new ValidationException.Detail(
|
||||
"parentId",
|
||||
"error.tree_entity_parent_id_not_exist",
|
||||
readyToCheck))
|
||||
);
|
||||
}
|
||||
initChildren();
|
||||
}));
|
||||
readyToCheck))
|
||||
);
|
||||
}
|
||||
initChildren();
|
||||
}));
|
||||
}
|
||||
|
||||
private void refactorPath() {
|
||||
Function<PK, Collection<E>> childGetter
|
||||
= id -> childrenMapping
|
||||
.getOrDefault(id, Collections.emptyMap())
|
||||
.values();
|
||||
= id -> childrenMapping
|
||||
.getOrDefault(id, Collections.emptyMap())
|
||||
.values();
|
||||
|
||||
for (E data : thisTime.values()) {
|
||||
E old = data.getId() == null ? null : oldData.get(data.getId());
|
||||
@@ -200,7 +203,7 @@ public class TreeSortServiceHelper<E extends TreeSortSupportEntity<PK>, PK> {
|
||||
};
|
||||
|
||||
//变更到了顶级节点
|
||||
if (service.isRootNode(data)) {
|
||||
if (isRootNode(data)) {
|
||||
data.setPath(RandomUtil.randomChar(4));
|
||||
this.refactorChildPath(old.getId(), data.getPath(), childConsumer);
|
||||
//重新保存所有子节点
|
||||
@@ -240,11 +243,11 @@ public class TreeSortServiceHelper<E extends TreeSortSupportEntity<PK>, PK> {
|
||||
|
||||
private void putChildToReadyToSave(Function<PK, Collection<E>> childGetter, E data) {
|
||||
childGetter
|
||||
.apply(data.getId())
|
||||
.forEach(e -> {
|
||||
readyToSave.put(e.getId(), e);
|
||||
putChildToReadyToSave(childGetter, e);
|
||||
});
|
||||
.apply(data.getId())
|
||||
.forEach(e -> {
|
||||
readyToSave.put(e.getId(), e);
|
||||
putChildToReadyToSave(childGetter, e);
|
||||
});
|
||||
}
|
||||
|
||||
private void refactor(E e) {
|
||||
|
||||
@@ -146,31 +146,31 @@ public class DefaultR2dbcExecutor extends R2dbcReactiveSqlExecutor {
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW, transactionManager = TransactionManagers.reactiveTransactionManager)
|
||||
@Transactional(rollbackFor = Throwable.class, propagation = Propagation.REQUIRES_NEW, transactionManager = TransactionManagers.reactiveTransactionManager)
|
||||
public Mono<Void> execute(SqlRequest request) {
|
||||
return super.execute(request);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW, transactionManager = TransactionManagers.reactiveTransactionManager)
|
||||
@Transactional(rollbackFor = Throwable.class, propagation = Propagation.REQUIRES_NEW, transactionManager = TransactionManagers.reactiveTransactionManager)
|
||||
public Mono<Void> execute(Publisher<SqlRequest> request) {
|
||||
return super.execute(request);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(transactionManager = TransactionManagers.reactiveTransactionManager)
|
||||
@Transactional(rollbackFor = Throwable.class, transactionManager = TransactionManagers.reactiveTransactionManager)
|
||||
public Mono<Integer> update(Publisher<SqlRequest> request) {
|
||||
return super.update(request);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(transactionManager = TransactionManagers.reactiveTransactionManager)
|
||||
@Transactional(rollbackFor = Throwable.class, transactionManager = TransactionManagers.reactiveTransactionManager)
|
||||
public Mono<Integer> update(SqlRequest request) {
|
||||
return super.update(request);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(transactionManager = TransactionManagers.reactiveTransactionManager)
|
||||
@Transactional(rollbackFor = Throwable.class, transactionManager = TransactionManagers.reactiveTransactionManager)
|
||||
public Mono<Integer> update(String sql, Object... args) {
|
||||
return super.update(sql, args);
|
||||
}
|
||||
|
||||
@@ -176,7 +176,7 @@ public class CommonErrorControllerAdvice {
|
||||
@ExceptionHandler
|
||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
public Mono<ResponseMessage<?>> handleException(jakarta.validation.ValidationException e) {
|
||||
return Mono.just(ResponseMessage.error(400, CodeConstants.Error.illegal_argument, e.getMessage()));
|
||||
return Mono.just(ResponseMessage.error(400, CodeConstants.Error.illegal_argument, e.getLocalizedMessage()));
|
||||
}
|
||||
|
||||
@ExceptionHandler
|
||||
@@ -196,7 +196,7 @@ public class CommonErrorControllerAdvice {
|
||||
log.warn(e.getLocalizedMessage(), e);
|
||||
return LocaleUtils
|
||||
.resolveMessageReactive("error.internal_server_error")
|
||||
.map(msg -> ResponseMessage.error(500, "internal_server_error", msg));
|
||||
.map(msg -> ResponseMessage.error(500, CodeConstants.Error.internal_server_error, msg));
|
||||
}
|
||||
|
||||
@ExceptionHandler
|
||||
@@ -206,7 +206,7 @@ public class CommonErrorControllerAdvice {
|
||||
|
||||
return LocaleUtils
|
||||
.resolveMessageReactive("error.internal_server_error")
|
||||
.map(msg -> ResponseMessage.error(500, "internal_server_error", msg));
|
||||
.map(msg -> ResponseMessage.error(500, CodeConstants.Error.internal_server_error, msg));
|
||||
}
|
||||
|
||||
@ExceptionHandler
|
||||
|
||||
@@ -14,6 +14,7 @@ import org.hswebframework.web.i18n.LocaleUtils;
|
||||
import org.hswebframework.web.logger.ReactiveLogger;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.converter.HttpMessageNotReadableException;
|
||||
import org.springframework.validation.BindException;
|
||||
import org.springframework.validation.FieldError;
|
||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||
@@ -28,6 +29,7 @@ import org.springframework.web.server.UnsupportedMediaTypeStatusException;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import jakarta.validation.ConstraintViolationException;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -39,7 +41,7 @@ public class CommonWebMvcErrorControllerAdvice {
|
||||
|
||||
private String resolveMessage(Throwable e) {
|
||||
if (e instanceof I18nSupportException) {
|
||||
return LocaleUtils.resolveMessage(((I18nSupportException) e).getI18nCode());
|
||||
return LocaleUtils.resolveMessage(((I18nSupportException) e).getI18nCode(),((I18nSupportException) e).getArgs());
|
||||
}
|
||||
return e.getMessage() == null ? null : LocaleUtils.resolveMessage(e.getMessage());
|
||||
}
|
||||
@@ -63,8 +65,8 @@ public class CommonWebMvcErrorControllerAdvice {
|
||||
@ResponseStatus(HttpStatus.UNAUTHORIZED)
|
||||
public ResponseMessage<TokenState> handleException(UnAuthorizedException e) {
|
||||
return ResponseMessage
|
||||
.<TokenState>error(401, CodeConstants.Error.unauthorized, resolveMessage(e))
|
||||
.result(e.getState());
|
||||
.<TokenState>error(401, CodeConstants.Error.unauthorized, resolveMessage(e))
|
||||
.result(e.getState());
|
||||
|
||||
}
|
||||
|
||||
@@ -85,9 +87,8 @@ public class CommonWebMvcErrorControllerAdvice {
|
||||
public ResponseMessage<List<ValidationException.Detail>> handleException(ValidationException e) {
|
||||
|
||||
return ResponseMessage
|
||||
.<List<ValidationException.Detail>>error(400, CodeConstants.Error.illegal_argument, resolveMessage(e))
|
||||
.result(e.getDetails())
|
||||
;
|
||||
.<List<ValidationException.Detail>>error(400, CodeConstants.Error.illegal_argument, resolveMessage(e))
|
||||
.result(e.getDetails());
|
||||
}
|
||||
|
||||
@ExceptionHandler
|
||||
@@ -100,24 +101,24 @@ public class CommonWebMvcErrorControllerAdvice {
|
||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
public ResponseMessage<List<ValidationException.Detail>> handleException(BindException e) {
|
||||
return handleException(new ValidationException(e.getMessage(), e
|
||||
.getBindingResult().getAllErrors()
|
||||
.stream()
|
||||
.filter(FieldError.class::isInstance)
|
||||
.map(FieldError.class::cast)
|
||||
.map(err -> new ValidationException.Detail(err.getField(), err.getDefaultMessage(), null))
|
||||
.collect(Collectors.toList())));
|
||||
.getBindingResult().getAllErrors()
|
||||
.stream()
|
||||
.filter(FieldError.class::isInstance)
|
||||
.map(FieldError.class::cast)
|
||||
.map(err -> new ValidationException.Detail(err.getField(), err.getDefaultMessage(), null))
|
||||
.collect(Collectors.toList())));
|
||||
}
|
||||
|
||||
@ExceptionHandler
|
||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
public ResponseMessage<List<ValidationException.Detail>> handleException(WebExchangeBindException e) {
|
||||
return handleException(new ValidationException(e.getMessage(), e
|
||||
.getBindingResult().getAllErrors()
|
||||
.stream()
|
||||
.filter(FieldError.class::isInstance)
|
||||
.map(FieldError.class::cast)
|
||||
.map(err -> new ValidationException.Detail(err.getField(), err.getDefaultMessage(), null))
|
||||
.collect(Collectors.toList())));
|
||||
.getBindingResult().getAllErrors()
|
||||
.stream()
|
||||
.filter(FieldError.class::isInstance)
|
||||
.map(FieldError.class::cast)
|
||||
.map(err -> new ValidationException.Detail(err.getField(), err.getDefaultMessage(), null))
|
||||
.collect(Collectors.toList())));
|
||||
}
|
||||
|
||||
|
||||
@@ -125,18 +126,18 @@ public class CommonWebMvcErrorControllerAdvice {
|
||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
public ResponseMessage<List<ValidationException.Detail>> handleException(MethodArgumentNotValidException e) {
|
||||
return handleException(new ValidationException(e.getMessage(), e
|
||||
.getBindingResult().getAllErrors()
|
||||
.stream()
|
||||
.filter(FieldError.class::isInstance)
|
||||
.map(FieldError.class::cast)
|
||||
.map(err -> new ValidationException.Detail(err.getField(), err.getDefaultMessage(), null))
|
||||
.collect(Collectors.toList())));
|
||||
.getBindingResult().getAllErrors()
|
||||
.stream()
|
||||
.filter(FieldError.class::isInstance)
|
||||
.map(FieldError.class::cast)
|
||||
.map(err -> new ValidationException.Detail(err.getField(), err.getDefaultMessage(), null))
|
||||
.collect(Collectors.toList())));
|
||||
}
|
||||
|
||||
@ExceptionHandler
|
||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
public ResponseMessage<?> handleException(jakarta.validation.ValidationException e) {
|
||||
return ResponseMessage.error(400, CodeConstants.Error.illegal_argument, e.getMessage());
|
||||
return ResponseMessage.error(400, CodeConstants.Error.illegal_argument, e.getLocalizedMessage());
|
||||
}
|
||||
|
||||
@ExceptionHandler
|
||||
@@ -150,7 +151,18 @@ public class CommonWebMvcErrorControllerAdvice {
|
||||
@Order
|
||||
public ResponseMessage<Object> handleException(RuntimeException e) {
|
||||
log.warn(e.getLocalizedMessage(), e);
|
||||
return ResponseMessage.error(resolveMessage(e));
|
||||
return ResponseMessage.error(CodeConstants.Error.internal_server_error,
|
||||
LocaleUtils.resolveMessage("error.internal_server_error"));
|
||||
}
|
||||
|
||||
@ExceptionHandler
|
||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
@Order
|
||||
public ResponseMessage<Object> handleException(HttpMessageNotReadableException e) {
|
||||
return ResponseMessage
|
||||
.error(400,
|
||||
"missing_request_body",
|
||||
LocaleUtils.resolveMessage("error.missing_request_body"));
|
||||
}
|
||||
|
||||
@ExceptionHandler
|
||||
@@ -182,8 +194,8 @@ public class CommonWebMvcErrorControllerAdvice {
|
||||
log.warn(e.getLocalizedMessage(), e);
|
||||
|
||||
return ResponseMessage
|
||||
.error(415, "unsupported_media_type", LocaleUtils.resolveMessage("error.unsupported_media_type"))
|
||||
.result(e.getSupportedMediaTypes());
|
||||
.error(415, "unsupported_media_type", LocaleUtils.resolveMessage("error.unsupported_media_type"))
|
||||
.result(e.getSupportedMediaTypes());
|
||||
}
|
||||
|
||||
@ExceptionHandler
|
||||
@@ -192,9 +204,9 @@ public class CommonWebMvcErrorControllerAdvice {
|
||||
log.warn(e.getLocalizedMessage(), e);
|
||||
|
||||
return ResponseMessage
|
||||
.error(406, "not_acceptable_media_type", LocaleUtils
|
||||
.resolveMessage("error.not_acceptable_media_type"))
|
||||
.result(e.getSupportedMediaTypes());
|
||||
.error(406, "not_acceptable_media_type", LocaleUtils
|
||||
.resolveMessage("error.not_acceptable_media_type"))
|
||||
.result(e.getSupportedMediaTypes());
|
||||
}
|
||||
|
||||
@ExceptionHandler
|
||||
@@ -203,8 +215,8 @@ public class CommonWebMvcErrorControllerAdvice {
|
||||
log.warn(e.getLocalizedMessage(), e);
|
||||
|
||||
return ResponseMessage
|
||||
.error(406, "method_not_allowed", LocaleUtils.resolveMessage("error.method_not_allowed"))
|
||||
.result(e.getSupportedMethods());
|
||||
.error(406, "method_not_allowed", LocaleUtils.resolveMessage("error.method_not_allowed"))
|
||||
.result(e.getSupportedMethods());
|
||||
}
|
||||
|
||||
|
||||
@@ -220,7 +232,7 @@ public class CommonWebMvcErrorControllerAdvice {
|
||||
|
||||
} while (exception != null && exception != e);
|
||||
if (exception == null) {
|
||||
return ResponseMessage.error(400, CodeConstants.Error.illegal_argument, e.getMessage());
|
||||
return ResponseMessage.error(400, CodeConstants.Error.illegal_argument, e.getMessage());
|
||||
}
|
||||
return ResponseMessage.error(400, CodeConstants.Error.illegal_argument, resolveMessage(exception));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
package org.hswebframework.web.crud.web;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import org.hswebframework.web.api.crud.entity.QueryOperation;
|
||||
import org.hswebframework.web.api.crud.entity.QueryParamEntity;
|
||||
import org.hswebframework.web.api.crud.entity.TreeSortSupportEntity;
|
||||
import org.hswebframework.web.authorization.annotation.Authorize;
|
||||
import org.hswebframework.web.authorization.annotation.QueryAction;
|
||||
import org.hswebframework.web.crud.service.ReactiveTreeSortEntityService;
|
||||
import org.hswebframework.web.crud.service.TreeSortEntityService;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface TreeServiceQueryController<E extends TreeSortSupportEntity<K>, K> {
|
||||
|
||||
@Authorize(ignore = true)
|
||||
TreeSortEntityService<E, K> getService();
|
||||
|
||||
@GetMapping("/_query/tree")
|
||||
@QueryAction
|
||||
@QueryOperation(summary = "使用GET动态查询并返回树形结构")
|
||||
default List<E> findAllTree(@Parameter(hidden = true) QueryParamEntity param) {
|
||||
return getService().queryResultToTree(param);
|
||||
}
|
||||
|
||||
@GetMapping("/_query/_children")
|
||||
@QueryAction
|
||||
@QueryOperation(summary = "使用GET动态查询并返回子节点数据")
|
||||
default List<E> findAllChildren(@Parameter(hidden = true) QueryParamEntity param) {
|
||||
return getService().queryIncludeChildren(param);
|
||||
}
|
||||
|
||||
@GetMapping("/_query/_children/tree")
|
||||
@QueryAction
|
||||
@QueryOperation(summary = "使用GET动态查询并返回子节点树形结构数据")
|
||||
default List<E> findAllChildrenTree(@Parameter(hidden = true) QueryParamEntity param) {
|
||||
return getService().queryIncludeChildrenTree(param);
|
||||
}
|
||||
|
||||
@PostMapping("/_query/tree")
|
||||
@QueryAction
|
||||
@Operation(summary = "使用POST动态查询并返回树形结构")
|
||||
default List<E> findAllTreePost(@RequestBody QueryParamEntity param) {
|
||||
return getService().queryResultToTree(param);
|
||||
}
|
||||
|
||||
@PostMapping("/_query/_children")
|
||||
@QueryAction
|
||||
@Operation(summary = "使用POST动态查询并返回子节点数据")
|
||||
default List<E> findAllChildrenPost(@RequestBody QueryParamEntity param) {
|
||||
return getService().queryIncludeChildren(param);
|
||||
}
|
||||
|
||||
@PostMapping("/_query/_children/tree")
|
||||
@QueryAction
|
||||
@Operation(summary = "使用POST动态查询并返回子节点树形结构数据")
|
||||
default List<E> findAllChildrenTreePost(@RequestBody QueryParamEntity param) {
|
||||
return getService().queryIncludeChildrenTree(param);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -8,4 +8,5 @@ error.tree_entity_cyclic_dependency=Cannot modify parent node as oneself or one'
|
||||
error.tree_entity_parent_id_not_exist=Parent node does not exist or has been deleted
|
||||
error.resource_not_found=Resource not found
|
||||
error.data.find.not_found=Data not found
|
||||
error.sql.prepare.failed.IndexOutOfBoundsException=Execute SQL failed, try check config: `easyorm.dialect`.
|
||||
error.sql.prepare.failed.IndexOutOfBoundsException=Execute SQL failed, try check config: `easyorm.dialect`.
|
||||
error.missing_request_body=Required request body is missing
|
||||
@@ -7,4 +7,5 @@ error.internal_server_error=\u670D\u52A1\u5668\u5185\u90E8\u9519\u8BEF
|
||||
error.tree_entity_cyclic_dependency=\u4E0D\u80FD\u4FEE\u6539\u7236\u8282\u70B9\u4E3A\u81EA\u5DF1\u6216\u8005\u81EA\u5DF1\u7684\u5B50\u8282\u70B9
|
||||
error.tree_entity_parent_id_not_exist=\u7236\u8282\u70B9\u4E0D\u5B58\u5728\u6216\u5DF2\u88AB\u5220\u9664
|
||||
error.data.find.not_found=\u6570\u636E\u4E0D\u5B58\u5728
|
||||
error.sql.prepare.failed.IndexOutOfBoundsException=SQL\u6267\u884C\u5931\u8D25,\u8BF7\u5C1D\u8BD5\u68C0\u67E5`easyorm.dialect`\u914D\u7F6E.
|
||||
error.sql.prepare.failed.IndexOutOfBoundsException=SQL\u6267\u884C\u5931\u8D25,\u8BF7\u5C1D\u8BD5\u68C0\u67E5`easyorm.dialect`\u914D\u7F6E.
|
||||
error.missing_request_body=\u8BF7\u6C42\u4F53\u7F3A\u5931
|
||||
@@ -12,6 +12,8 @@ public interface CodeConstants {
|
||||
String unauthorized = "unauthorized";
|
||||
|
||||
String not_found="not_found";
|
||||
|
||||
String internal_server_error="internal_server_error";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user