我有两个使用 oneToMany
注释相互映射的实体。第一个实体是 bookedBus
,第二个实体是 drivers
驱动程序实体中已经插入了一行,该行稍后将成为 bookingBus 实体 (PK) 的外部引用 (FK)。下面是两个实体,为简洁起见,已跳过 setter 和 getter。
第一个实体
@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: detached entity passed to persist: com.bus.api.entity.Drivers; nested exception is org.hibernate.PersistentObjectException: detached entity passed to persist: com.bus.api.entity.Drivers
下面是我尝试保存到 bookingBus 实体的方法
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);
根据要求我的 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
}
}
最佳答案
首先,您的命名有些困惑:您有 Driver
和 Drivers
。像这样:
private Drivers driver;
还选择这样的变量名称:
BookedBuses bookedRecord = new BookedBuses();
会引起很多困惑。不要在类型之间混合复数和单数,最好也不要引入可能不容易关联的名称(如记录)。还有这个:
private List<BookedBuses> bookedBus;
应该是这样的:
private List<BookedBus> bookedBuses;
(并且还需要更改您的类名 BookedBus -> BookedBus)
无论如何,实际问题似乎出在这里:
Drivers drivers = new Drivers(booking.getDriver().getId());
您需要在存储库的帮助下通过 id 获取现有实体,而不是使用现有 id 创建一个新实体。所以类似:
Drivers drivers = driverRepo.findOne(booking.getDriver().getId()); // or findById(..)
您似乎有一个构造函数(您没有显示)可以使用 id 创建驱动程序。不受管理的它被认为是分离的。 (您还有 drivers.addBooked(bookedRecord);
您没有共享它,但也许它是微不足道的)
另请注意一些帖子建议将CascadeType.ALL
更改为CascadeType.MERGE
是否有效取决于您的需求。 Spring data 能够根据实体 id 对 save(..)
进行一些合并,但在本例中不一定如此。
关于java - JPA错误: InvalidDataAccessApiUsageException: detached entity passed to persist,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54405522/