Мне нужно использовать столбец @JoinColumn @ManyToOne как часть составного первичного ключа (с предпочтительным вариантом определения составного ключа @IdClass, а не @EmbeddedId).
Участвующие субъекты являются родителями и детьми - отношения вроде как для сотрудников и отделов, с той лишь разницей, что мне нужно только получить доступ к дочерним («отделенным») полям из родительского («сотрудника»), а не порока.наоборот.Поэтому я использую однонаправленный @ManyToOne в родительской сущности.
В настоящее время у меня есть проблема с обновлением родительской таблицы - при обновлении родительской сущности hibernate пытается вставить запись в дочернюю таблицу и по понятным причинам терпит неудачу с нарушением первичного ключа,Мне нужно подавить вставки к дочернему столу.Я надеялся, что «вставляемый = ложный, обновляемый = ложный» в аннотации решит проблему, но это не так.
Я использовал эти руководства для настройки составного первичного ключа: https://www.baeldung.com/jpa-composite-primary-keys,https://dwuysan.wordpress.com/2012/02/22/joincolumn-is-part-of-the-composite-primary-keys/, https://vladmihalcea.com/the-best-way-to-map-a-composite-primary-key-with-jpa-and-hibernate/
Мой код приведен ниже.Родительский объект:
@Data
@Builder
@Entity
@Table(name = "Parent", schema = "dbo")
@IdClass(value = ParentPrimaryKey.class)
public class Parent {
@Id
@Column(name = "dateTime", insertable = false, updatable = false)
private Timestamp dateTime;
@Id
@MapsId("child")
@ManyToOne
@JoinColumn(name = "child", insertable = false, updatable = false)
private Child child;
@Column(name = "status")
private Integer status;
}
Объект первичного ключа родителя:
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ParentPrimaryKey implements Serializable {
private static final long serialVersionUID = 1;
private Timestamp dateTime;
private String child;
}
Дочерний объект:
@Data
@Entity(name = "Child")
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "Child", schema = "dbo")
public class Location implements Serializable {
private static final long serialVersionUID = 1;
@Id
@Column(name = "child")
private String child;
@Column(name = "param")
private String param;
// some other child param fields
}
Интеграционное тестирование в памяти H2 с некоторыми записями в TestTableдоступно:
@Test
public void shouldSaveRecord() {
Parent selectedRecord = parentRepository.findAll().get(0);
selectedRecord.setStatus(9);
parentRepository.save(selectedRecord);
}
Журналы, сгенерированные при выполнении теста:
2019-07-01 09:52:20.547 [main] DEBUG org.hibernate.SQL - select parent0_.dateTime as dateTime1_15_, parent0_.child as child 3_15_, parent0_.status as status4_15_ from dbo.Parent parent0_
2019-07-01 09:52:20.555 [main] DEBUG org.hibernate.SQL - select child0_.child as child1_5_0_, child0_.param as param3_5_0_ from dbo.Child child0_ where child0_.child=?
2019-07-01 09:52:20.602 [main] DEBUG org.hibernate.SQL - select parent0_.dateTime as dateTime1_15_0_, parent0_.child as child3_15_0_, parent0_.status as status4_15_0_ from dbo.Parent parent0_ where parent0_.dateTime=? and parent0_.child=?
2019-07-01 09:52:20.630 [main] DEBUG org.hibernate.SQL - insert into dbo.child (child, param) values (?, ?)
2019-07-01 09:52:20.636 [main] WARN o.h.e.jdbc.spi.SqlExceptionHelper - SQL Error: 23505, SQLState: 23505
2019-07-01 09:52:20.636 [main] ERROR o.h.e.jdbc.spi.SqlExceptionHelper - Unique index or primary key violation: "PRIMARY_KEY_81 ON DBO.CHILD(CHILD) VALUES ('MTS_0102_010R4', 8)"; SQL statement:
insert into dbo.child (child, param) values (?, ?) [23505-197]
org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint ["PRIMARY_KEY_81 ON DBO.CHILD(CHILD) VALUES ('MTS_0102_010R4', 8)"; SQL statement:
insert into dbo.child (child, param) values (?, ?) [23505-197]]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement
Мне нужно запретить нежелательную вставку в дочернюю таблицу.Любая помощь будет принята с благодарностью.
Upd 2019-07-02.Текущее решение: пришлось переключиться на @EmbeddedId.Вроде боли, так как мне приходилось обновлять все неродные запросы.Все еще задаюсь вопросом, можно ли было управлять этим с помощью @ IdClass.