我使用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;
}
第二个实体
@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:传递给持久对象的分离实体: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);
我的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
}
}
答案 0 :(得分: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());
您需要借助存储库通过id来获取现有实体,而不是创建一个具有id的新实体。像这样:
Drivers drivers = driverRepo.findOne(booking.getDriver().getId()); // or findById(..)
似乎您有一个未显示的构造函数,可以使用id创建驱动程序。如果不进行管理,则认为已分离。 (您还有drivers.addBooked(bookedRecord);
,但您没有分享,但也许微不足道)
请注意,有些帖子建议将CascadeType.ALL
更改为CascadeType.MERGE
是否有效取决于您的需求。 Spring数据可以基于实体ID在save(..)
上进行一些合并,但在这种情况下不一定如此。
答案 1 :(得分:1)
此行
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;
}