REQ-3540: 备份

This commit is contained in:
yanglin 2025-03-17 10:43:35 +08:00
parent 7cbb6fd549
commit 91747f3eea
5 changed files with 26 additions and 26 deletions

View File

@ -60,7 +60,7 @@ public class IndexNodeDao extends ServiceImpl<IndexNodeMapper, IndexNode> {
}
public IndexNode findValidChildByName(IndexNodeParentScope parentNode, IndexNodeType nodeType, String name) {
return parentOrScopeQuery(parentNode) //
return parentOrScopeRootQuery(parentNode) //
.eq(IndexNode::getName, name) //
.eq(IndexNode::getNodeType, nodeType) //
.eq(IndexNode::getState, IndexNodeState.VALID) //
@ -70,7 +70,7 @@ public class IndexNodeDao extends ServiceImpl<IndexNodeMapper, IndexNode> {
public List<IndexNode> findValidChildrenNameRightLike(IndexNodeParentScope parentNode, IndexNodeType nodeType,
String name) {
return parentOrScopeQuery(parentNode) //
return parentOrScopeRootQuery(parentNode) //
.likeRight(IndexNode::getName, name) //
.eq(IndexNode::getNodeType, nodeType) //
.eq(IndexNode::getState, IndexNodeState.VALID) //
@ -140,9 +140,9 @@ public class IndexNodeDao extends ServiceImpl<IndexNodeMapper, IndexNode> {
.update();
}
private LambdaQueryChainWrapper<IndexNode> parentOrScopeQuery(IndexNodeParentScope parentScope) {
private LambdaQueryChainWrapper<IndexNode> parentOrScopeRootQuery(IndexNodeParentScope parentScope) {
if (StringUtils.isBlank(parentScope.parentCode()))
return scopeQuery(parentScope.nodeScope());
return scopeQuery(parentScope.nodeScope()).eq(IndexNode::getParentCode, "");
return lambdaQuery().eq(IndexNode::getParentCode, parentScope.parentCode());
}

View File

@ -148,6 +148,10 @@ public class IndexNode extends BaseEntity<IndexNode> implements NodeValue, Index
return Path.wrap(path);
}
public static boolean idEquals(IndexNode n1, IndexNode n2) {
return Objects.equals(n1.getId(), n2.getId());
}
@JsonIgnore
@JSONField(serialize = false, deserialize = false)
public boolean isFile() {

View File

@ -172,7 +172,6 @@ public class IndexManager {
BizAssertions.assertFalse(srcNode.isDirectory() && destParentNode.isFile(), "不能移动文件夹到文件下");
return async(() -> {
RootNode<IndexNode> moveRoot = TreeBuilder.build(collectValidSubtreeAsValueRoot(srcNode));
//noinspection SpringTransactionalMethodCallsInspection
return transaction.execute(unused -> connectNodes(moveRoot, destParentNode));
});
}
@ -181,8 +180,7 @@ public class IndexManager {
public IndexNode copySubTree(IndexNode src, @Nullable IndexNode destParent, CopyNodeVisitor copyNodeVisitor) {
RootNode<IndexNode> srcRoot = TreeUtils.transform(collectValidSubtreeAsValueRoot(src), IndexNode.class);
srcRoot.walkDown(copyNodeVisitor);
List<IndexNode> copiedNodes = TreeUtils.collectValues(srcRoot);
indexNodeDao.saveBatch(copiedNodes);
indexNodeDao.saveBatch(TreeUtils.collectValues(srcRoot));
return connectNodes(srcRoot, destParent);
}
@ -197,20 +195,14 @@ public class IndexManager {
/**
* connect tree nodes and resolve name issue
*/
@BizTransactional
public IndexNode connectNodes(RootNode<IndexNode> connectRoot, @Nullable IndexNode destParent) {
private IndexNode connectNodes(RootNode<IndexNode> connectRoot, @Nullable IndexNode destParent) {
// rebuild parent id, parent code and the most important path
connectRoot.walkDown(new ConnectNodeVisitor(destParent));
indexNodeDao.connectNodes(TreeUtils.collectValues(connectRoot));
IndexNode copiedRoot = connectRoot.getChildren().get(0).<IndexNode> asValueNode().getValue();
// resolve the name issue
if (destParent != null) {
String newName = indexSupport.lockAndMaybeIncrChildName(destParent, copiedRoot.getNodeType(),
copiedRoot.getName());
// don't update if the name is good
if (!copiedRoot.getName().equals(newName))
indexNodeDao.rename(copiedRoot.getCode(), newName);
}
if (destParent != null)
indexSupport.incrNameIfDuplicate(destParent, copiedRoot.getNodeType(), copiedRoot);
// get the coped root with full props
return indexNodeDao.findOrNull(copiedRoot.getCode());
}

View File

@ -14,7 +14,6 @@ import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import cn.axzo.nanopart.doc.file.index.copy.SetScopeProcessor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.transaction.support.TransactionSynchronizationManager;
@ -31,6 +30,7 @@ import cn.axzo.nanopart.doc.dao.DocLockDao;
import cn.axzo.nanopart.doc.dao.IndexNodeDao;
import cn.axzo.nanopart.doc.entity.IndexNode;
import cn.axzo.nanopart.doc.entity.domain.Path;
import cn.axzo.nanopart.doc.file.index.copy.SetScopeProcessor;
import cn.axzo.nanopart.doc.file.index.domain.NameUsedException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@ -97,15 +97,17 @@ class IndexSupport {
BizAssertions.assertFalse(parent.isFile(), "不能在文件下建立文件夹");
}
String lockAndMaybeIncrChildName(IndexNode parentNode, IndexNodeType nodeType, String name) {
void incrNameIfDuplicate(IndexNode parentNode, IndexNodeType nodeType, IndexNode rename) {
lockParentAndReleaseOnCommit(parentNode);
IndexNode sameName = indexNodeDao.findValidChildByName(parentNode, nodeType, name);
if (sameName == null)
return name;
List<IndexNode> nameLikeNodes = indexNodeDao.findValidChildrenNameRightLike(parentNode, nodeType, name);
Pattern pattern = Pattern.compile(Pattern.quote(name) + "\\((\\d+)\\)");
List<IndexNode> nameLikeNodes = indexNodeDao.findValidChildrenNameRightLike(parentNode, nodeType,
rename.getName());
if (nameLikeNodes.size() == 1 && IndexNode.idEquals(rename, nameLikeNodes.get(0)))
return;
Pattern pattern = Pattern.compile(Pattern.quote(rename.getName()) + "\\((\\d+)\\)");
int maxSeq = 0;
for (IndexNode indexNode : nameLikeNodes) {
if (indexNode.getId().equals(rename.getId()))
continue;
Matcher matcher = pattern.matcher(indexNode.getName());
if (matcher.matches()) {
int seq = Integer.parseInt(matcher.group(1));
@ -114,7 +116,8 @@ class IndexSupport {
}
}
maxSeq = maxSeq == 0 ? 1 : maxSeq + 1;
return String.format("%s(%d)", name, maxSeq);
String newName = String.format("%s(%d)", rename.getName(), maxSeq);
indexNodeDao.rename(rename.getCode(), newName);
}
void ensureChildNameNotUsed(NodeCreate create, IndexNodeType nodeType) {

View File

@ -17,10 +17,11 @@ import cn.axzo.nanopart.doc.entity.IndexNode;
@Mapper
public interface IndexNodeMapper extends BaseMapper<IndexNode> {
@Insert("<script>\n" + "INSERT INTO doc_index_node (code, parent_id, root_code, path)\n" + "VALUES\n"
@Insert("<script>\n" + "INSERT INTO doc_index_node (code, parent_id, parent_code, root_code, path)\n" + "VALUES\n"
+ " <foreach collection='nodes' item='node' separator=','>\n"
+ " (#{node.code}, #{node.parentId}, #{node.rootCode}, #{node.path})\n" + "</foreach>\n"
+ " (#{node.code}, #{node.parentId}, #{node.parentCode}, #{node.rootCode}, #{node.path})\n" + "</foreach>\n"
+ " ON DUPLICATE KEY UPDATE parent_id = values(parent_id),\n"
+ " parent_code = values(parent_code),\n"
+ " root_code = values(root_code),\n"
+ " path = values(path)\n" + "</script>")
void connectNodes(@Param("nodes") List<IndexNode> nodes);