односторонние вызовы «один ко многим» Hibernate Невозможно добавить или обновить дочернюю строку: ограничение внешнего ключа не выполнено - PullRequest
0 голосов
/ 02 июня 2018

У меня есть приложение, которое учит пользователя, как играть в различные карточные игры.Сохраняемая модель данных состоит из TrainingSession с однонаправленным отношением один-ко-многим с Hands.

[ EDIT ] Для пояснения, Hand не существует вне контекста TrainingSession (то есть они создаются / уничтожаются, когда TrainingSession).Следуя принципам Data Driven Design, TrainingSession обрабатывается как агрегированный корень, и поэтому используются единственные пружинные данные CrudRepository (т. Е. Репозиторий для Hand не создается)

Когда я пытаюсьсохраняя TrainingSession с помощью CrudRepository, я получаю: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: невозможно добавить или обновить дочернюю строку: ограничение внешнего ключа не выполняется (blackjack. hand, CONSTRAINT FKrpuxac6b80xc7rc98vt1euc3n FOREIGN KEY(id) ССЫЛКИ training_session (tsid))

Моя проблема - операция 'save (trainingSession)' через экземпляр CrudRepository.Я не понимаю, почему в сообщении об ошибке указано, что FOREIGN KEY (id) REFERENCES training_session (tsid)).Кажется, это является причиной проблемы, но я не могу понять, почему это так или как это исправить.Отношения являются однонаправленными, и ничто в классе Hand не относится к TrainingSession.

Код, за исключением всех методов получения и установки:

@Entity
public class TrainingSession {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer tsid;
private String strategy;

@OneToMany(cascade=CascadeType.ALL)
@JoinColumn(name="id")
private List<Hand> hands;

private int userId;

protected TrainingSession() {
}

public TrainingSession(int userId, Strategy strategy, List<Hand> hands) {
    this.strategy = strategy.getClass().getSimpleName();
    this.hands = hands;
    this.userId = userId;
}

, тогда как Hand -

@Entity // This tells Hibernate to make a table out of this class
public class Hand {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
private int p1;
private String p1s;
private int p2;
private String p2s;
private int d1;
private String d1s;
private int trials;
private int score;

public Hand() {
}

Ответы [ 2 ]

0 голосов
/ 05 июня 2018

Нашел проблему.Я предполагал, что, когда spring-data настроил таблицы БД, он смог выяснить и установить однонаправленное отношение 1-ко-многим.Видимо, это не так.Когда я настраиваю отношения как двунаправленные, кажется, что все работает.

Чтобы исправить вещи, я:

  • убрал из TrainingSession аннотацию @joincolumn для рук
  • в Hands Я добавил поле TrainingSession с аннотацией @ManyToOne:

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "tsid", nullable = false)
    @OnDelete(action = OnDeleteAction.CASCADE)
    private TrainingSession tsession;
    
  • Я также добавил в класс Hand метод получения / установки для tsession

Теперь я могу сохранить всю совокупную конструкцию, используя только TrainingSessionRepository.

0 голосов
/ 02 июня 2018

Вам необходимо сначала сохранить объекты TrainingSession и Hand перед сохранением добавления объектов руки в TrainingSession.

TrainingSession ts1 = new TrainingSession();
trainingSessionManager.save(ts1);

Hand hand1 = new Hand();
handManager.save(hand1);

Hand hand2 = new Hand();
handManager.save(hand2);

ts1.gethands().add(hand1);
ts1.gethands().add(hand2)

trainingSessionManager.save(ts1);

Если вы проверите свою базу данных, вы найдете 3 таблицы TrainingSession, Hand and TrainingSession_Hand, TrainingSession_Handссылки на таблицы как на TrainingSession, так и на Hand.Поэтому вам нужно сохранить TrainingSession и руку перед сохранением отношений.

...