Skip to content

Commit

Permalink
feat-IChildrenAbility-实现子表批量编辑,主子表级联删除
Browse files Browse the repository at this point in the history
  • Loading branch information
aruis committed Sep 10, 2024
1 parent ee3a71f commit f34e93e
Show file tree
Hide file tree
Showing 9 changed files with 275 additions and 44 deletions.
118 changes: 108 additions & 10 deletions my-boot/src/test/java/net/ximatai/muyun/core/TestMainAndChildren.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import net.ximatai.muyun.database.IDatabaseAccess;
import net.ximatai.muyun.database.builder.Column;
import net.ximatai.muyun.database.builder.TableWrapper;
import net.ximatai.muyun.model.BatchResult;
import net.ximatai.muyun.model.ChildTableInfo;
import net.ximatai.muyun.model.QueryItem;
import net.ximatai.muyun.testcontainers.PostgresTestResource;
Expand Down Expand Up @@ -85,10 +86,8 @@ void testInsertOK() {
@Test
void testGetChildTableList() {
List<Map> response = given()
.contentType("application/json")
.queryParam("noPage", true)
.when()
.get("%s/view/%s/children/%s".formatted(mainPath, idMain, testChildren.getMainTable()))
.get("%s/view/%s/child/%s".formatted(mainPath, idMain, testChildren.getMainTable()))
.then()
.statusCode(200)
.extract()
Expand All @@ -104,7 +103,7 @@ void testChildCRUD() {
.contentType("application/json")
.body(Map.of("v_name", "child2"))
.when()
.post("%s/update/%s/children/%s/create".formatted(mainPath, idMain, testChildren.getMainTable()))
.post("%s/update/%s/child/%s/create".formatted(mainPath, idMain, testChildren.getMainTable()))
.then()
.statusCode(200)
.extract()
Expand All @@ -113,7 +112,7 @@ void testChildCRUD() {
assertNotNull(child2);

Map child2Map = given()
.get("%s/view/%s/children/%s/view/%s".formatted(mainPath, idMain, testChildren.getMainTable(), child2))
.get("%s/view/%s/child/%s/view/%s".formatted(mainPath, idMain, testChildren.getMainTable(), child2))
.then()
.statusCode(200)
.extract()
Expand All @@ -127,7 +126,7 @@ void testChildCRUD() {
.contentType("application/json")
.body(Map.of("v_name", "child22"))
.when()
.post("%s/update/%s/children/%s/update/%s".formatted(mainPath, idMain, testChildren.getMainTable(), child2))
.post("%s/update/%s/child/%s/update/%s".formatted(mainPath, idMain, testChildren.getMainTable(), child2))
.then()
.statusCode(200)
.extract()
Expand All @@ -136,7 +135,7 @@ void testChildCRUD() {
assertEquals("1", editCount);

Map child2Map2 = given()
.get("%s/view/%s/children/%s/view/%s".formatted(mainPath, idMain, testChildren.getMainTable(), child2))
.get("%s/view/%s/child/%s/view/%s".formatted(mainPath, idMain, testChildren.getMainTable(), child2))
.then()
.statusCode(200)
.extract()
Expand All @@ -147,7 +146,7 @@ void testChildCRUD() {
assertEquals("child22", child2Map2.get("v_name"));

String delCount = given()
.get("%s/update/%s/children/%s/delete/%s".formatted(mainPath, idMain, testChildren.getMainTable(), child2))
.get("%s/update/%s/child/%s/delete/%s".formatted(mainPath, idMain, testChildren.getMainTable(), child2))
.then()
.statusCode(200)
.extract()
Expand All @@ -156,11 +155,108 @@ void testChildCRUD() {
assertEquals("1", delCount);

given()
.get("%s/view/%s/children/%s/view/%s".formatted(mainPath, idMain, testChildren.getMainTable(), child2))
.get("%s/view/%s/child/%s/view/%s".formatted(mainPath, idMain, testChildren.getMainTable(), child2))
.then()
.statusCode(404);

}

@Test
void testBatch() {
System.out.println(idMain);
System.out.println(idChild);

List children = List.of(
Map.of("id", idChild, "v_name", "child1"),
Map.of("v_name", "child2"),
Map.of("v_name", "child3")
);

BatchResult result = given()
.contentType("application/json")
.body(children)
.when()
.post("%s/update/%s/child/%s".formatted(mainPath, idMain, testChildren.getMainTable()))
.then()
.statusCode(200)
.extract()
.as(new TypeRef<>() {
});

assertEquals(2, result.getCreate());
assertEquals(1, result.getUpdate());
assertEquals(0, result.getDelete());

List children2 = List.of(
Map.of("id", idChild, "v_name", "child1")
);

BatchResult result2 = given()
.contentType("application/json")
.body(children2)
.when()
.post("%s/update/%s/child/%s".formatted(mainPath, idMain, testChildren.getMainTable()))
.then()
.statusCode(200)
.extract()
.as(new TypeRef<>() {
});

assertEquals(0, result2.getCreate());
assertEquals(1, result2.getUpdate());
assertEquals(2, result2.getDelete());

//这种情况会直接清空子表数据
BatchResult result3 = given()
.contentType("application/json")
.body(List.of())
.when()
.post("%s/update/%s/child/%s".formatted(mainPath, idMain, testChildren.getMainTable()))
.then()
.statusCode(200)
.extract()
.as(new TypeRef<>() {
});

assertEquals(0, result3.getCreate());
assertEquals(0, result3.getUpdate());
assertEquals(1, result3.getDelete());
}

@Test
void testDeleteMainTable() {
String mainID = testMain.create(Map.of("v_name", "main"));

BatchResult result = given()
.contentType("application/json")
.body(List.of(
Map.of("v_name", "child1"),
Map.of("v_name", "child2"),
Map.of("v_name", "child3")
))
.when()
.post("%s/update/%s/child/%s".formatted(mainPath, mainID, testChildren.getMainTable()))
.then()
.statusCode(200)
.extract()
.as(new TypeRef<>() {
});

assertEquals(3, result.getCreate());

List rows = (List) databaseAccess.query("select * from test.testchildren where id_at_testmain = ? ", mainID);

assertEquals(3, rows.size());

given()
.get("%s/delete/%s".formatted(mainPath, mainID))
.then()
.statusCode(200);

List rows2 = (List) databaseAccess.query("select * from test.testchildren where id_at_testmain = ? ", mainID);

assertEquals(0, rows2.size());
}
}

@Path("/testmain")
Expand Down Expand Up @@ -199,7 +295,9 @@ public List<QueryItem> queryItemList() {

@Override
public List<ChildTableInfo> getChildren() {
return List.of(testChildren.toChildTable("id_at_testmain"));
return List.of(
testChildren.toChildTable("id_at_testmain").setAutoDelete()
);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,8 @@ default ChildTableInfo toChildTable(String foreignKey) {
}
}

default String getChildAlias() {
return getMainTable();
}

}
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
package net.ximatai.muyun.ability;

import jakarta.transaction.Transactional;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.QueryParam;
import net.ximatai.muyun.model.BatchResult;
import net.ximatai.muyun.model.ChildTableInfo;
import net.ximatai.muyun.model.QueryItem;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
Expand All @@ -17,52 +20,101 @@ public interface IChildrenAbility {
List<ChildTableInfo> getChildren();

@GET
@Path("/view/{id}/children/{childTable}")
default List getChildTableList(@PathParam("id") String id, @PathParam("childTable") String childTable, @QueryParam("sort") List<String> sort) {
ChildTableInfo ct = getChildTable(childTable);
@Path("/view/{id}/child/{childAlias}")
default List<Map> getChildTableList(@PathParam("id") String id, @PathParam("childAlias") String childAlias, @QueryParam("sort") List<String> sort) {
ChildTableInfo ct = getChildTable(childAlias);
String foreignKey = ct.getForeignKey();
return ct.getCtrl().view(null, null, true, sort, Map.of(foreignKey, id), List.of(QueryItem.of(foreignKey))).getList();
}

@GET
@Path("/view/{id}/children/{childTable}/view/{childId}")
default Map<String, ?> getChild(@PathParam("id") String id, @PathParam("childTable") String childTable, @PathParam("childId") String childId) {
ChildTableInfo ct = getChildTable(childTable);
@Path("/view/{id}/child/{childAlias}/view/{childId}")
default Map<String, ?> getChild(@PathParam("id") String id, @PathParam("childAlias") String childAlias, @PathParam("childId") String childId) {
ChildTableInfo ct = getChildTable(childAlias);
Map<String, ?> child = ct.getCtrl().view(childId);
if (!child.get(ct.getForeignKey()).equals(id)) {
throw new RuntimeException("child id not match");
throw new RuntimeException("子表数据匹配不到当前主表");
}
return child;
}

@POST
@Path("/update/{id}/children/{childTable}/create")
default String createChild(@PathParam("id") String id, @PathParam("childTable") String childTable, Map body) {
ChildTableInfo ct = getChildTable(childTable);
@Path("/update/{id}/child/{childAlias}")
@Transactional
default BatchResult putChildTableList(@PathParam("id") String id, @PathParam("childAlias") String childAlias, List body) {
ChildTableInfo ct = getChildTable(childAlias);
String childPK = ct.getCtrl().getPK();

body.forEach(item -> {
if (item instanceof Map map) {
if (map.containsKey(ct.getForeignKey())
&& map.get(ct.getForeignKey()) != null
&& !map.get(ct.getForeignKey()).equals(id)) { // 说明存在要编辑的数据不是当前主表的对应子表
throw new RuntimeException("子表数据超出对应主表管辖范围,请检查「%s」的内容".formatted(ct.getForeignKey()));
}
}
});

int update = 0;
int create = 0;
int delete = 0;

List<String> idsAlreadyHere = new ArrayList<>(getChildTableList(id, childAlias, null).stream().map(it -> it.get(childPK).toString()).toList());

System.out.println(idsAlreadyHere);

for (Object o : body) {
if (o instanceof Map map) {
String childId = (String) map.get(ct.getCtrl().getPK());
if (childId != null && idsAlreadyHere.contains(childId)) { //说明有id,走编辑
ct.getCtrl().update(childId, map);
idsAlreadyHere.remove(childId);
update++;
} else { //新增
Map newMap = new HashMap(map);
newMap.put(ct.getForeignKey(), id);
String newId = ct.getCtrl().create(newMap);
idsAlreadyHere.remove(newId);
create++;
}
}
}

for (String s : idsAlreadyHere) {
delete += ct.getCtrl().delete(s);
}

return new BatchResult(create, update, delete);
}

@POST
@Path("/update/{id}/child/{childAlias}/create")
default String createChild(@PathParam("id") String id, @PathParam("childAlias") String childAlias, Map body) {
ChildTableInfo ct = getChildTable(childAlias);
String foreignKey = ct.getForeignKey();
Map map = new HashMap(body);
map.put(foreignKey, id);
return ct.getCtrl().create(map);
}

@POST
@Path("/update/{id}/children/{childTable}/update/{childId}")
default Integer updateChild(@PathParam("id") String id, @PathParam("childTable") String childTable, @PathParam("childId") String childId, Map body) {
getChild(id, childTable, childId);
ChildTableInfo ct = getChildTable(childTable);
@Path("/update/{id}/child/{childAlias}/update/{childId}")
default Integer updateChild(@PathParam("id") String id, @PathParam("childAlias") String childAlias, @PathParam("childId") String childId, Map body) {
getChild(id, childAlias, childId);
ChildTableInfo ct = getChildTable(childAlias);
return ct.getCtrl().update(childId, body);
}

@GET
@Path("/update/{id}/children/{childTable}/delete/{childId}")
default Integer deleteChild(@PathParam("id") String id, @PathParam("childTable") String childTable, @PathParam("childId") String childId) {
getChild(id, childTable, childId);
ChildTableInfo ct = getChildTable(childTable);
@Path("/update/{id}/child/{childAlias}/delete/{childId}")
default Integer deleteChild(@PathParam("id") String id, @PathParam("childAlias") String childAlias, @PathParam("childId") String childId) {
getChild(id, childAlias, childId);
ChildTableInfo ct = getChildTable(childAlias);
return ct.getCtrl().delete(childId);
}

default ChildTableInfo getChildTable(String childTable) {
return getChildren().stream().filter(c -> c.getCtrl().getMainTable().equals(childTable)).findFirst().orElseThrow();
default ChildTableInfo getChildTable(String childAlias) {
return getChildren().stream().filter(c -> c.getChildAlias().equals(childAlias)).findFirst().orElseThrow();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,41 @@
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import net.ximatai.muyun.ability.IChildrenAbility;
import net.ximatai.muyun.ability.IDatabaseAbilityStd;
import net.ximatai.muyun.ability.IMetadataAbility;
import net.ximatai.muyun.ability.ISoftDeleteAbility;
import net.ximatai.muyun.model.ChildTableInfo;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;

public interface IDeleteAbility extends IDatabaseAbilityStd, IMetadataAbility {

@GET
@Path("/delete/{id}")
@Transactional
default Integer delete(@PathParam("id") String id) {
int result;

if (this instanceof IChildrenAbility ability) { // 如果带子表,考虑级联删除
ability.getChildren().stream().filter(ChildTableInfo::isAutoDelete).forEach(childTableInfo -> {
ability.putChildTableList(id, childTableInfo.getChildAlias(), List.of()); //对应即可清空子表
});
}

if (this instanceof ISoftDeleteAbility ability) {
HashMap map = new HashMap();
map.put(getPK(), id);
map.put(ability.getSoftDeleteColumn().getName(), true);
map.put("t_delete", LocalDateTime.now());

return getDatabase().updateItem(getSchemaName(), getMainTable(), map);
result = getDatabase().updateItem(getSchemaName(), getMainTable(), map);
} else {
return getDatabase().deleteItem(getSchemaName(), getMainTable(), id);
result = getDatabase().deleteItem(getSchemaName(), getMainTable(), id);
}

return result;
}
}
Loading

0 comments on commit f34e93e

Please sign in to comment.