Данные Spring - другой объект с тем же идентификатором, даже если объекты равны - PullRequest
1 голос
/ 20 апреля 2020

У меня есть проект, созданный с использованием весенней загрузки 2.2.6, и я пытаюсь вставить / обновить запись ( Parent ) в базе данных и выполнить каскадную операцию для ее дочерних элементов, если дочерний элемент не существует, это должно быть вставлено, иначе это должно быть обновлено. У меня есть следующие классы:

@Entity
@Data
public class Parent {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
    List<Child> children1;

    @ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
    List<Child> children2;
}
@Entity
@Data
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode(of = {"id"})
public class Child {
    @Id
    private Long id;

    private String name;
}
public interface ParentRepository extends JpaRepository<Parent, Long> {
}

@Service
public class TestService {

    private ParentRepository parentRepository;

    public TestService(ParentRepository parentRepository) {
        this.parentRepository = parentRepository;
    }

    @Transactional
    public void save() {
        Parent parent = new Parent();
        Child c1 = new Child(1L, "c1");
        Child c2 = new Child(1L, "c1");
        List<Child> children1 = new ArrayList<>();
        children1.add(c1);
        List<Child> children2 = new ArrayList<>();
        children1.add(c2);

        parent.setChildren1(children1);
        parent.setChildren2(children2);

        parentRepository.save(parent);
    }
}

У меня нет другой конфигурации, и с этим я получаю следующую ошибку:

A different object with the same identifier value was already associated with the session : [Child#1]

Я не понимаю, почему я получаю эту ошибку, потому что c1.equals (c2) оценивается как true.

Если я изменяю тип children1 и children2 на Set, я получаю следующая ошибка:

Unique index or primary key violation: "PRIMARY KEY ON PUBLIC.CHILD(ID) [1, 'c1']"

Теперь я не понимаю, почему я получаю эту ошибку, потому что я ожидаю, что каскадный тип слияния будет обрабатывать эту проблему, делать обновления вместо вставок .

Можете ли вы помочь мне понять, что я упускаю? Можете ли вы дать мне несколько советов о том, как лучше вставлять / обновлять объекты в такой ситуации?

1 Ответ

0 голосов
/ 20 апреля 2020

Хотя объекты равны Java, это не значит, что они являются одним и тем же объектом в контексте постоянства. Как только вы выполните:

Child c1 = new Child(1L, "c1");
Child c2 = new Child(1L, "c1");

... и сохраните их с помощью каскада PERSIST, оба объекта будут сохранены, и, поскольку их идентификаторы равны, ограничение уникального идентификатора нарушается. Решение состоит в том, чтобы использовать один и тот же объект, поэтому объект будет создан только один раз:

Child c = new Child(1L, "c1");

List<Child> children = new ArrayList<>();
children.add(c);

parent.setChildren1(children);
parent.setChildren2(children);
...