#spring-boot #spring-data #spring-data-jdbc
#пружинный ботинок #spring-данные #spring-data-jdbc
Вопрос:
Учитывая сложности, связанные с JPA, мы планируем использовать Spring Data JDBC для наших сущностей из-за его простоты. Ниже приведена примерная структура, и у нас есть до 6 дочерних сущностей. Мы можем успешно вставлять данные в различные из этих сущностей с надлежащими сопоставлениями внешнего ключа.
Проблема: — У нас есть рабочий процесс вне этого приложения, который периодически обновляет «RequestStatus» в сущности «Запрос», и это единственное поле, которое обновляется после создания запроса. Как и в случае с spring data 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);
}
Комментарии:
1. Всем привет, это мой первый пост в SO. Пожалуйста, дайте мне знать, если мне нужно внести больше ясности в вопрос. Возвращаясь к моему вопросу, поскольку обновляется только один столбец, на данный момент я использовал @Query () для прямого запуска запроса на ОБНОВЛЕНИЕ, и это не привело к повторному запуску операций удаления и вставки . Тем не менее, я действительно хочу получить ваш отзыв, если это правильный подход или есть какие-либо обходные пути. Ценю ваш ответ.
Ответ №1:
Подход, который вы описываете в своем комментарии:
Иметь специальный метод, выполняющий именно этот оператор update, — правильный способ сделать это.
Однако вы должны знать, что это игнорирует оптимистическую блокировку. Таким образом, существует риск того, что может произойти следующее
Поток / сессия 1: считывает совокупный файл.
Поток / сессия 2: обновляет одно поле в соответствии с вашим вопросом.
Поток / сеанс 1: записывает совокупность, возможно, с другими изменениями, перезаписывая изменение, внесенное сеансом 2.
Чтобы избежать этой или подобных проблем, вам необходимо
-
убедитесь, что версия корня aggregate не изменилась с момента ее загрузки, чтобы гарантировать, что метод не записывает конфликтующие изменения.
-
увеличьте версию, чтобы гарантировать, что ничто другое не перезаписывает изменения, внесенные в этом методе.
Это может означать, что вам нужны два или более SQL-оператора, что, вероятно, означает, что вам придется еще больше отказаться от полноценного пользовательского метода, в котором вы это реализуете, вероятно, используя внедренный JdbcTemplate
.
Комментарии:
1. Спасибо за подробный ответ . Мы будем использовать представленный здесь подход для оптимистичной блокировки. Я думаю, что это хороший компромисс — иметь 2 или более sql-оператора, чем накладные расходы JPA, поскольку мы уже используем JdbcTemplate в нашем приложении для некоторых других функций.