Так что после помощи от @K.Nicholas
и исследования, я думаю, что мне удалось решить проблему и узнать о ней новые вещи.
@K.Nicholas
был прав насчет настройки полей для людей и статистики, но этоизначально мне было не совсем понятно.Как бы то ни было, позже мне это удалось.
В принципе, все остальные классы остаются почти такими же, за исключением People
класса.
@Data
@Entity
@Builder
@Table(name = "PEOPLE")
public class People implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@SequenceGenerator(name = "people", sequenceName = "people_id_seq", allocationSize = 1)
@GeneratedValue(strategy = GenerationType.AUTO, generator = "people")
private long peopleId;
private String peopleName;
@ToString.Exclude
@EqualsAndHashCode.Exclude
@OneToMany(
mappedBy = "people",
cascade = CascadeType.ALL,
orphanRemoval = true
)
private List<PeopleStats> peopleStats;
// Maintain the state of objects association
public void addStats(Stats stats) {
if (this.peopleStats == null) {
this.peopleStats = new ArrayList<>();
}
// Important to ensure that a new instance of PeopleStatsId is being passed into the field
// otherwise, PropertyAccessException will be encountered
PeopleStats pStats = PeopleStats.builder()
.people(this)
.stats(stats)
.peopleStatsId(new PeopleStatsId(this.getPeopleId(), stats.getStatsId()))
.build();
this.peopleStats.add(pStats);
}
}
Обратите внимание на комментарий в addStats
метод, в котором мне нужно передать новый экземпляр объекта PeopleStatsId
для инициализации объекта PeopleStatsId
, который должен был быть сделан в первую очередь, за исключением того, что это не так.Извлеченный урок.
Я также упомянул, что ранее сталкивался с вопросом об отделенной сущности.Это было потому, что я пытался установить в поле идентификатора Stats, когда это не требовалось.
В соответствии с Hibernate Guide ,
отсоединено
объект имеет связанный идентификатор, но больше не связан с контекстом постоянства (обычно потому, что контекст постоянства был закрыт или экземпляр был исключен из контекста)
В своем посте я пытался установить в «Статистика» значение «Люди», а затем сохранить его.
@Test
public void testSavePeople() {
// People object created
people.addStats(Stats.builder().statsId(new Long(1)).statsName("a").statsDescription("b").build());
this.entityManager.persistAndFlush(people);
}
Проблема была .statsId(new Long(1))
, поскольку она рассматривалась как отдельная сущность, поскольку существовал идентификатор.CascadeType.MERGE
будет работать в этом случае, потому что я думаю, из-за функции saveOrUpdate?В любом случае, без установки statsId, CascadeType.ALL
будет работать нормально.
Пример модульного теста (работает):
@Test
public void testSavePeopleWithOneStats() {
// Creates People entity
People people = this.generatePeopleWithoutId();
// Retrieve existing stats from StatsRepository
Stats stats = this.statsRepository.findById(new Long(1)).get();
// Add Stats to People
people.addStats(stats);
// Persist and retrieve
People p = this.entityManager.persistFlushFind(people);
assertThat(p.getPeopleStats().size()).isEqualTo(1);
}
У меня был скрипт data-h2.sql
, загруженный в Statsданные при запуске модульного теста, поэтому я могу получить их из statsRepository
.
Я также обновил свой документ в github .
Надеюсь, это поможет любому, кто будет следующим.