为了账号安全,请及时绑定邮箱和手机立即绑定

JPA 错误:InvalidDataAccessApiUsageException:

JPA 错误:InvalidDataAccessApiUsageException:

小唯快跑啊 2022-05-25 16:42:37
我有两个实体使用oneToMany注释相互映射。一个实体是bookedBus,第二个是drivers驱动程序实体已经插入了一行,该行稍后将成为bookedBus 实体(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;}第二实体@Entitypublic 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:分离的实体传递给坚持: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 按要求保存方法@Autowiredprivate 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 回答

?
慕桂英546537

TA贡献1848条经验 获得超10个赞

第一个你在命名上有一些混淆:你有DriverDrivers。像这样:

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 数据能够save(..)基于实体 id 进行一些合并,但在这种情况下不一定。


查看完整回答
反对 回复 2022-05-25
?
幕布斯7119047

TA贡献1794条经验 获得超8个赞

这条线


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


如果您已经拥有可用的驱动程序 ID,则无需再次从数据库中提取驱动程序 ID。


从&中删除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;

}


查看完整回答
反对 回复 2022-05-25
  • 2 回答
  • 0 关注
  • 296 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号