#java #multithreading #spring-boot #hibernate #jpa
Вопрос:
У меня есть 2 объекта, сопоставленные с JPA
@Entity
class Table_A {
@Id
private Integer id;
@Enumerated(EnumType.STRING)
private ModuleType module;
private String name;
private Instant lastModifiedDate;
private String creator;
@NotNull
@Enumerated(EnumType.STRING)
private State state;
@OneToMany(fetch = FetchType.LAZY)
@JoinColumns( value = {
@JoinColumn(name="id_object", referencedColumnName = "id_entity", insertable = false, updatable = false),
@JoinColumn(name="object_sub_type", referencedColumnName = "object_sub_type", insertable = false, updatable = false),
}, foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))
private List<AttributeValue> attributes;
}
@Entity
Class Table B {
@Id
private Integer id;
@Column(name = "id_create_user", insertable = false, updatable = false)
private String createUser;
@Column(name = "type_object", insertable = false, updatable = false)
private String typeObject;
@Column(name = "id_object", insertable = false, updatable = false)
private Integer idTable_A;
@Column(name = "name")
private String name;
private Boolean hasCombination;
}
Эти сущности не связаны между собой. А также у меня есть интерфейс JpaRepository для каждого из них.
@Repository
public interface Table_A_Repository extends JpaRepository<Table_A, Integer>
@Repository
public interface Table_B_Repository extends JpaRepository<Table_B, Integer>
Когда у меня есть 2 темы.
Первый Thread_1 считывает объект «Table_A», выполняет некоторые операции и изменяет одно поле объекта table_A
Второй Thread_2 считывает тот же объект из Table_A и вносит изменения в разные строки Table_B ( Table_B_Repository.saveAll( listOfTable_Bobjects) ) до завершения Thread_1.
Я вижу, что than Thread_2 переопределяет изменение Thread_1 в объекте Table_A.
Чего я не понимаю, так это почему вызов Table_B_Repository.saveAll делает и обновляет в table_A переопределяет значение, установленное в первом потоке, оставляя его таким, каким оно было.
спасибо за ваши ответы или комментарии.
Ответ №1:
Проблема с этой реализацией заключается в том, что при попытке обновления методом saveall у вас будут все данные в объектах.
Поэтому, если вы читаете данные по имени, то для некоторого имени существует около 4 объектов, и вы обновляете только последний объект, но во время сохранения вы сохраняете не только этот объект, но и все объекты, которые вы прочитали ранее.
В режиме гибернации, если в данных произошли какие-либо изменения, только это приведет к обновлению данных в базе данных, поэтому объекты, которые были обновлены потоком A, будут рассматриваться для обновления потоком B, и все изменения, внесенные потоком A, будут переопределены.
Комментарии:
1. но разве Table_B_Repository не должен обновлять только объекты, связанные с Table_B ? Меня это немного смущает. Будет способ добиться только обновления элементов table_B.
2. можете ли вы поделиться своим кодом репозитория и кодом сущности здесь.
3. Я только что обновил информацию о сущностях @Pirate
4. можете ли вы также поделиться кодом для потока B? Также вы можете проверить, обновляет ли поток A значение или нет. Глядя на вашу сущность, она не должна обновляться, как вы упомянули в вопросе.
5. Из того, что я понимаю, Jparepository обновляет только свой класс, связанный с ним, и возможные отношения этого класса(много всего…..), верно? Я не могу поделиться кодом, потому что он огромен и имеет множество связанных классов (устаревший код), но я уверен, что Table_B не имеет никакого отношения к базе данных.
Ответ №2:
Метод saveAll в репозитории сохранит запись, если она новая, и объединит, если она не новая. Поэтому, если вы сохраните все записи, записи, измененные потоком 1, будут перезаписаны в контексте сохранения путем слияния().