使用 Spring 数据 JDBC 挑战持久性复杂实体
Challenge Persisting Complex Entity using Spring Data JDBC
考虑到 JPA 中涉及的复杂性,我们计划为我们的实体使用 Spring 数据 JDBC 以实现其简单性。下面是示例结构,我们有多达 6 个子实体。我们能够使用适当的外键映射将数据成功插入到这些实体中。
挑战:- 我们在这个应用程序之外有一个工作流程,它会定期更新“请求”实体中的“requestStatus”,这是创建请求后唯一更新的字段。与 spring 数据 JDBC 一样,在更新期间它会删除所有引用的实体并再次重新创建(插入)它。考虑到 6 个子实体,这是一种繁重的操作。关于如何处理这些情况,是否有任何解决方法或建议
@Table("Request")
public class Request {
private String requestId; // generated in the Before Save Listener .
private String requestStatus;
@Column("requestId")
private ChildEntity1 childEntity1;
public void addChildEntity1(ChildEntity1 childEntityobj) {
this.childEntity1 = childEntityobj;
}
}
@Table("Child_Entity1")
public class ChildEntity1 {
private String entity1Id; // Auto increment on DB
private String name;
private String SSN;
private String requestId;
@MappedCollection(column = "entity1Id", keyColumn = "entity2Id")
private ArrayList<ChildEntity2> childEntity2List = new ArrayList<ChildEntity2>();
@MappedCollection(column = "entity1Id", keyColumn = "entity3Id")
private ArrayList<ChildEntity3> childEntity3List = new ArrayList<ChildEntity3>();
public void addChildEntity2(ChildEntity2 childEntity2obj) {
childEntity2List.add(childEntity2obj);
}
public void addChildEntity3(ChildEntity3 childEntity3obj) {
childEntity3List.add(childEntity3obj);
}
}
@Table("Child_Entity2")
public class ChildEntity2 {
private String entity2Id; // Auto increment on DB
private String partyTypeCode;
private String requestId;
}
@Table(Child_Entity3)
public class ChildEntity3 {
private String entity3Id; // Auto increment on DB
private String PhoneCode;
private String requestId;
}
@Test
public void createandsaveRequest() {
Request newRequest = createRequest(); // using builder to build the object
newRequest.addChildEntity1(createChildEntity1());
newRequest.getChildEntity1().addChildEntity2(createChildEntity2());
newRequest.getChildEntity1().addChildEntity3(createChildEntity3());
requestRepository.save(newRequest);
}
您在评论中描述的方法:
有一个专门的方法来执行 update-statement 是正确的方法。
你应该知道这确实忽略了乐观锁定。
因此存在以下可能发生的风险
Thread/Session 1: 读取聚合。
Thread/Session 2:根据您的问题更新单个字段。
Thread/Session 1:写入聚合,可能还有其他更改,覆盖会话 2 所做的更改。
要避免此问题或类似问题,您需要
检查聚合根的版本与加载时的版本是否相同,以保证该方法不会写入冲突的更改。
增加版本以保证没有其他任何东西覆盖在此方法中所做的更改。
这可能意味着您需要两个或更多 SQL 语句,这可能意味着您必须更多地回退到实现它的完整自定义方法,可能使用注入的 JdbcTemplate
。
考虑到 JPA 中涉及的复杂性,我们计划为我们的实体使用 Spring 数据 JDBC 以实现其简单性。下面是示例结构,我们有多达 6 个子实体。我们能够使用适当的外键映射将数据成功插入到这些实体中。
挑战:- 我们在这个应用程序之外有一个工作流程,它会定期更新“请求”实体中的“requestStatus”,这是创建请求后唯一更新的字段。与 spring 数据 JDBC 一样,在更新期间它会删除所有引用的实体并再次重新创建(插入)它。考虑到 6 个子实体,这是一种繁重的操作。关于如何处理这些情况,是否有任何解决方法或建议
@Table("Request")
public class Request {
private String requestId; // generated in the Before Save Listener .
private String requestStatus;
@Column("requestId")
private ChildEntity1 childEntity1;
public void addChildEntity1(ChildEntity1 childEntityobj) {
this.childEntity1 = childEntityobj;
}
}
@Table("Child_Entity1")
public class ChildEntity1 {
private String entity1Id; // Auto increment on DB
private String name;
private String SSN;
private String requestId;
@MappedCollection(column = "entity1Id", keyColumn = "entity2Id")
private ArrayList<ChildEntity2> childEntity2List = new ArrayList<ChildEntity2>();
@MappedCollection(column = "entity1Id", keyColumn = "entity3Id")
private ArrayList<ChildEntity3> childEntity3List = new ArrayList<ChildEntity3>();
public void addChildEntity2(ChildEntity2 childEntity2obj) {
childEntity2List.add(childEntity2obj);
}
public void addChildEntity3(ChildEntity3 childEntity3obj) {
childEntity3List.add(childEntity3obj);
}
}
@Table("Child_Entity2")
public class ChildEntity2 {
private String entity2Id; // Auto increment on DB
private String partyTypeCode;
private String requestId;
}
@Table(Child_Entity3)
public class ChildEntity3 {
private String entity3Id; // Auto increment on DB
private String PhoneCode;
private String requestId;
}
@Test
public void createandsaveRequest() {
Request newRequest = createRequest(); // using builder to build the object
newRequest.addChildEntity1(createChildEntity1());
newRequest.getChildEntity1().addChildEntity2(createChildEntity2());
newRequest.getChildEntity1().addChildEntity3(createChildEntity3());
requestRepository.save(newRequest);
}
您在评论中描述的方法:
有一个专门的方法来执行 update-statement 是正确的方法。
你应该知道这确实忽略了乐观锁定。 因此存在以下可能发生的风险
Thread/Session 1: 读取聚合。
Thread/Session 2:根据您的问题更新单个字段。
Thread/Session 1:写入聚合,可能还有其他更改,覆盖会话 2 所做的更改。
要避免此问题或类似问题,您需要
检查聚合根的版本与加载时的版本是否相同,以保证该方法不会写入冲突的更改。
增加版本以保证没有其他任何东西覆盖在此方法中所做的更改。
这可能意味着您需要两个或更多 SQL 语句,这可能意味着您必须更多地回退到实现它的完整自定义方法,可能使用注入的 JdbcTemplate
。