У меня есть простая модель. Объект A имеет отношение «один ко многим» с объектом B. Они связаны с использованием таблицы ассоциаций. Мой вариант использования - выборка/вставка/обновление объекта в простой веб-приложении:Вставить вместо обновления с помощью данных Spring JPA
- Извлечь сущность A как JSON.
- Поместить объект A (даже без изменений) для сохранения.
- Нарушение ограничений: hibernate пытается вставить уже существующую строку в таблицу объединений.
Почему это происходит? В Hibernate есть все, что необходимо для определения того, следует ли выполнять слияние или сохранение на родителях и их дочерних элементах. Почему он не проверяет, связаны ли дети с родителем?
Parent.java:
package com.example;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Version;
import lombok.EqualsAndHashCode;
@Entity
@EqualsAndHashCode(exclude = { "id" })
public class Parent {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
private Set<Child> children = new HashSet<>();
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Set<Child> getChildren() {
return children;
}
public void setChildren(Set<Child> children) {
this.children = children;
}
}
Child.java
package com.example;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Version;
import lombok.EqualsAndHashCode;
@Entity
@EqualsAndHashCode(exclude = { "id" })
public class Child {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private Long value;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getValue() {
return value;
}
public void setValue(Long value) {
this.value = value;
}
}
ParentService.java:
package com.example;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.persistence.EntityManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class ParentService {
@Autowired
private ParentRepository parentRepository;
@Transactional
public Parent save(Parent parent) {
return parentRepository.save(parent);
}
}
ParentRepository.java:
package com.example;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface ParentRepository extends JpaRepository<Parent, Long>{
}
Что интересно, когда я добавляю свойства @Version, тогда все работает, но я не могу найти объяснение, почему. Другим решением является выбор oldParent по id, только ради извлечения - тогда он также работает даже без @Version, но когда я получу oldParent-детей и инициализирую его с помощью size(), то снова появятся нежелательные вставки. Почему эти вещи даже работают? Это что-то связано с хранилищами Hibernate или Spring Data JPA?
Вы реализовали 'equals' и' hashCode' на 'B'? –
Можете ли вы предоставить некоторый код Java? – ByeBye
@AliDehgani да, я сделал – Hooberd