Оспаривать сохраняющуюся сложную сущность, используя Spring Data JDBC

#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.

Чтобы избежать этой или подобных проблем, вам необходимо

  1. убедитесь, что версия корня aggregate не изменилась с момента ее загрузки, чтобы гарантировать, что метод не записывает конфликтующие изменения.

  2. увеличьте версию, чтобы гарантировать, что ничто другое не перезаписывает изменения, внесенные в этом методе.

Это может означать, что вам нужны два или более SQL-оператора, что, вероятно, означает, что вам придется еще больше отказаться от полноценного пользовательского метода, в котором вы это реализуете, вероятно, используя внедренный JdbcTemplate .

Комментарии:

1. Спасибо за подробный ответ . Мы будем использовать представленный здесь подход для оптимистичной блокировки. Я думаю, что это хороший компромисс — иметь 2 или более sql-оператора, чем накладные расходы JPA, поскольку мы уже используем JdbcTemplate в нашем приложении для некоторых других функций.