Есть 2 объекта (скажем, Rule и Label) с отношением «многие ко многим», использующих связанные объекты.
согласно справочной документации по спящему режиму
Правило enity:
@Entity
@Table(name = "rule")
@JsonIdentityInfo(
generator = ObjectIdGenerators.PropertyGenerator.class,
property = "name")
public class Rule implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@NaturalId
@NotBlank
@Column(unique = true)
private String name;
@Lob
@Column(columnDefinition = "TEXT")
private String content;
@OneToMany(mappedBy = "rule", cascade = {CascadeType.PERSIST,
CascadeType.MERGE})
private List<RuleLabel> labels = new ArrayList<>();
...
Метка сущности:
@Entity
@Table(name = "label")
@JsonIdentityInfo(
generator = ObjectIdGenerators.PropertyGenerator.class,
property = "id")
public class Label implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@NotBlank
private String name;
@OneToMany(mappedBy = "label", cascade = {CascadeType.PERSIST,
CascadeType.MERGE})
private List<RuleLabel> rules = new ArrayList<>();
...
Ссылка на объект:
@Entity
public class RuleLabel implements Serializable {
@Id
@ManyToOne
private Rule rule;
@Id
@ManyToOne
private Label label;
...
Хранилища:
@Repository
public interface LabelRepository extends JpaRepository<Label, Long>
...
@Repository
public interface RuleRepository extends JpaRepository<Rule, Long>
...
Создание новой сущности с помощью RuleRepository.save (Rule) работает нормально, но когда я пытаюсь обновить существующую сущность (тот же метод RuleRepository.save (Rule) , но сущность должна быть сохраненный содержит id поле) это приводит к бесконечному циклу Hibernate: выберите ... запросов:
Hibernate: select rule0_.id as id1_7_1_, rule0_.is_active as is_activ2_7_1_, rule0_.content as content3_7_1_, rule0_.is_deleted as is_delet4_7_1_, rule0_.import_section as import_s5_7_1_, rule0_.name as name6_7_1_, rule0_.rule_configuration as rule_con7_7_1_, labels1_.rule_id as rule_id1_8_3_, labels1_.label_id as label_id2_8_3_, labels1_.rule_id as rule_id1_8_0_, labels1_.label_id as label_id2_8_0_ from rule rule0_ left outer join rule_label labels1_ on rule0_.id=labels1_.rule_id where rule0_.id=?
и StackOverflowError в результате
java.lang.StackOverflowError: null
at com.mysql.jdbc.ServerPreparedStatement.getInstance(ServerPreparedStatement.java:332)
...
(LabelRepository действует таким же образом)
Как это можно исправить?
Обновление:
После изменения стратегии получения на Lazy
@Id
@ManyToOne(fetch = FetchType.LAZY)
private Rule rule;
@Id
@ManyToOne(fetch = FetchType.LAZY)
private Label label;
Проблема с бесконечным циклом исчезла, но появилась новая - связанные сущности не заполняются, и когда Hibernate пытается вставить значения в таблицу ссылок
Hibernate: insert into rule_label (rule_id, label_id) values (?, ?)
получаем
org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement
...
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Column 'rule_id' cannot be null