Ошибка JPA: InvalidDataAccessApiUsageException: отдельная сущность передана для сохранения - PullRequest
0 голосов
/ 28 января 2019

У меня есть две сущности, сопоставленные друг с другом с помощью аннотации oneToMany.Одна сущность - bookedBus, а вторая - drivers. В сущность драйверов уже будет вставлена ​​строка, которая впоследствии станет внешней ссылкой (FK) на сущность bookedBus (PK).Ниже для краткости пропущены две сущности: сеттеры и геттеры.

Первая сущность

@Entity
@Table(name = "bookedBuses")
public class BookedBuses implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JoinColumn(name = "driver_id")
    private Drivers driver;
}

Вторая сущность

@Entity
public class Drivers implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "driver")
    private List<BookedBuses> bookedBus;
}

Теперь, когда я пытаюсь сохранить всущность забронированной шины выдает следующее исключение

org.springframework.dao.InvalidDataAccessApiUsageException: отдельная сущность, переданная в persist: com.bus.api.entity.Drivers;вложенное исключение - org.hibernate.PersistentObjectException: отдельная сущность передана в постоянное хранилище: com.bus.api.entity.Drivers

Ниже описано, как я пытался сохранить сущность bookedBus

BookedBuses bookedRecord = new BookedBuses();
bookedRecord.setBookedSeats(1);
bookedRecord.setBookedBusState(BookedBusState.LOADING);
      bookedRecord.setBus(busService.getBusByPlateNumber(booking.getPlateNumber()));
bookedRecord.setRoute(booking.getRoute());
 infoLogger.info("GETTING DRIVER ID ======= " +    booking.getDriver().getId());
 Drivers drivers = new Drivers(booking.getDriver().getId());
 List<BookedBuses> d_bu = new ArrayList<>();
 drivers.setBooked(d_bu);
 drivers.addBooked(bookedRecord);
 bookedRecord.setDriver(drivers);
 bookedBusService.save(bookedRecord);

Метод сохранения My BookBusService по запросу

@Autowired
private BookedBusRepository bookedBusRepo;
public boolean save(BookedBuses bookedRecord) {
    try {
        bookedBusRepo.save(bookedRecord);
        return true;
    } catch (DataIntegrityViolationException ex) {
        System.out.println(ex);
        AppConfig.LOGGER.error(ex);
        return false;
        // Log error message
    }
}

Ответы [ 2 ]

0 голосов
/ 29 января 2019

Эта строка

Drivers drivers = new Drivers(booking.getDriver().getId());

Если у вас уже есть идентификатор драйвера, то вам не нужно снова извлекать идентификатор драйвера из БД.

После удаления атрибута Cascade из @OneToMany & @ManyToOne ваш код должен работать.

@Entity
@Table(name = "bookedBuses")
public class BookedBuses implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
`
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "driver_id")
    private Drivers driver;
}

@Entity
public class Drivers implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @OneToMany(fetch = FetchType.LAZY)
    @JoinColumn(name = "driver_id")
    private List<BookedBuses> bookedBus;
}
0 голосов
/ 28 января 2019

1-й у вас есть путаница в именах: у вас есть Driver & Drivers.Например:

private Drivers driver;

Выбор имен переменных, например:

BookedBuses bookedRecord = new BookedBuses();

, может привести к путанице.Не смешивайте множественное число и единственное число между типами и, предпочтительно, также не вводите имена, которые не могут быть легко связаны, как записьТакже это:

private List<BookedBuses> bookedBus;

, что скорее должно быть похоже на:

private List<BookedBus> bookedBuses;

(а также потребуется изменить имя вашего класса BookedBuses -> BookedBus)

В любом случаеЗдесь, похоже, реальная проблема:

Drivers drivers = new Drivers(booking.getDriver().getId());

Вам нужно извлечь существующую сущность по идентификатору с помощью репозитория, а не создавать новую с идентификатором существующего.Так что-то вроде:

Drivers drivers = driverRepo.findOne(booking.getDriver().getId()); // or findById(..)

Кажется, у вас есть конструктор (который вы не показали), который позволяет создать драйвер с идентификатором.То, что не удалось, считается отстраненным.(У вас также есть drivers.addBooked(bookedRecord);, которым вы не поделились, но, возможно, это тривиально)

Обратите внимание также В некоторых сообщениях предлагается изменить CascadeType.ALL на CascadeType.MERGE, зависит ли это от вашей работынеобходимо.Данные Spring могут объединяться в save(..) на основе идентификатора сущности, но не обязательно в этом случае.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...