Java JPA在保存到OneToMany关系时未清除集合迭代器
我有一个基本的SpringBoot应用程序。使用Spring初始值设定项、JPA、嵌入式Tomcat、Thymeleaf模板引擎,并将包作为可执行JAR文件 我有这个域类:Java JPA在保存到OneToMany关系时未清除集合迭代器,java,spring,jpa,persistence,javax,Java,Spring,Jpa,Persistence,Javax,我有一个基本的SpringBoot应用程序。使用Spring初始值设定项、JPA、嵌入式Tomcat、Thymeleaf模板引擎,并将包作为可执行JAR文件 我有这个域类: Entity @DiscriminatorValue("sebloc") public class SeblocDevice extends Device { /** * */ private static final long
Entity
@DiscriminatorValue("sebloc")
public class SeblocDevice extends Device {
/**
*
*/
private static final long serialVersionUID = 1L;
public SeblocDevice() {
super();
}
public SeblocDevice(String deviceKey, String devicePAC) {
super(deviceKey, devicePAC);
}
@OneToMany(mappedBy = "device", cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true)
private Set<DeviceDriver> driverDevices = new HashSet<>();
public Set<DeviceDriver> getDriverDevices() {
return driverDevices;
}
public void setDriverDevices(Set<DeviceDriver> driverDevices) {
this.driverDevices = driverDevices;
}
public void clearDriverDevices() {
for (DeviceDriver deviceDriver : deviceDrivers) {
deviceDriver.setDriver(null);
driverDevices.remove(deviceDriver);
}
public void removeDriverDevice(DeviceDriver deviceDriver) {
deviceDriver.setDriver(null);
driverDevices.remove(deviceDriver);
}
}
...
}
这是JUnit测试,在上一次测试中,我排除了1个驱动程序,但得到了2个(清除所有驱动程序,然后添加1个)
我还尝试在服务级别中创建一个方法
public interface DeviceDriverRepository extends CrudRepository<DeviceDriver, Long> {
}
@Transactional
public SeblocDevice cleanDrivers (SeblocDevice seblocDevice) {
deviceDriverRepository.delete(seblocDevice.getDeviceDrivers());
seblocDevice.getDeviceDrivers().clear();
seblocDevice.setDeviceDrivers(null);
return seblocDeviceRepository.save (seblocDevice);
}
public interface DeviceDriverRepository扩展了crudepository{
}
@交易的
公共SeblocDevice清洁驱动程序(SeblocDevice SeblocDevice){
deviceDriverRepository.delete(seblocDevice.getDeviceDrivers());
seblocDevice.getDeviceDrivers().clear();
seblocDevice.setDeviceDrivers(空);
返回SEBLOCDEVICEPOSITORY.save(seblocDevice);
}
然后deviceService.cleanDrivers(seblocDevice)代码>
但是驱动程序再次出现crizzis是正确的,您必须将设备设置为null
保持双向关联一致的最佳方法是创建方便的方法,如:
public void addDriverDevice(DeviceDriver deviceDriver) {
deviceDriver.setDriver(deviceDriver);
driverDevices.add(deviceDriver);
}
public void removeDriverDevice(DeviceDriver deviceDriver) {
deviceDriver.setDriver(null);
driverDevices.remove(deviceDriver);
}
如果你想清除所有的
public void clearDriverDevices() {
for (DeviceDriver deviceDriver : deviceDrivers) {
deviceDriver.setDriver(null);
driverDevices.remove(deviceDriver);
}
}
要使代码按预期工作,您需要在SeblocDevice.driverDevices
属性的@OneToMany
关系中添加orphanRemoving=true
参数,如下所示:
@OneToMany(mappedBy = "device", cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true)
private Set<DeviceDriver> driverDevices = new HashSet<>();
@OneToMany(mappedBy=“device”,cascade=CascadeType.ALL,fetch=FetchType.EAGER,orphandremovation=true)
private Set driverDevices=new HashSet();
清楚地理解JPA映射。你需要记住,在一段关系中,总是有主人的一面。
例如,在@OneToMany
与@ManyToOne
的关系中,@ManyToOne
是所有者,因为它引用了其他实体
基本上,实体管理器只关心所有者端的更改,即如果调用DeviceDriver.setDevice(null)
,将执行删除。但恰恰相反
(SeblocDevice.getDriverDevices().clear()
)不正确
因此,有一个参数,它是不言自明的。分配此参数后,实体管理器现在将作为所有者控制集合的元素,SeblocDevice.getDriverDevices().clear()
将删除数据库中不在SeblocDevice.getDriverDevices
集合中的DeviceDrivers,即使DeviceDriver.device
不为空。您可以发布driverService
字段类型的实现吗?为什么需要一个驱动程序?您创建了一个与SeblocDevice
关联的附加驱动程序,但从未删除已存在的驱动程序。。。我猜在调用SeblocDevice.getDriverDevices().clear()
后,您希望现有的DeviceDriveDriver
不再与SeblocDevice
关联,但要实现这一点,SeblocDevice.driverDevices
必须是关联的拥有方,当您使用双向映射时,必须在两端添加或删除项。而您的设备服务.save
方法必须用@Transactional
进行注释。我尝试了相同的结果,肯定是我做错了我看不到的事情
public void clearDriverDevices() {
for (DeviceDriver deviceDriver : deviceDrivers) {
deviceDriver.setDriver(null);
driverDevices.remove(deviceDriver);
}
}
@OneToMany(mappedBy = "device", cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true)
private Set<DeviceDriver> driverDevices = new HashSet<>();