【问题标题】:JPA update a object creates a new one in a ManyToMany RelationJPA 更新对象在多对多关系中创建一个新对象
【发布时间】:2021-08-27 08:02:07
【问题描述】:

我在尝试使用 JPA 更新对象时遇到问题。问题不是更新现有对象,而是创建新对象以及新的嵌入数据。

这是我的java代码:

第一个实体

@Entity
@Table(name = "worksite")
public class Worksite {
    private long id;
    private String name;
    private Double longitude;
    private Double latitude;  
 
    private Set<WorksiteDevice> worksiteDevices = new HashSet<WorksiteDevice>();
 
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    @Column(name = "worksite_id")
    public long getId() {
        return id;
    }
 
    public void setId(long id) {
        this.id = id;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public Double getLongitude() {
        return longitude;
    }
 
    public void setLongitude(Double longitude) {
        this.longitude = longitude;
    }
 
    public Double getLatitude() {
        return latitude;
    }
 
    public void setLatitude(String latitude) {
        this.latitude = latitude;
    }
 
    @OneToMany(mappedBy = "worksite", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true )
    public Set<WorksiteDevice> getWorksiteDevices() {
        return worksiteDevices;
    }
 
    public void setWorksiteDevices(Set<WorksiteDevice> worksiteDevices) {
        this.worksiteDevices = worksiteDevices;
    }
      
}

第二个实体: 设备名称在数据库中具有唯一约束。这是为了防止用户多次进入同一个设备

@Entity
@Table(name = "device")
public class Device {
    private long id;
    private String DeviceName;
 
    private Set<WorksiteDevice> worksiteDevices = new HashSet<WorksiteDevice>();
     
         
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    @Column(name = "device_id")
    public long getId() {
        return id;
    }
 
    public void setId(long id) {
        this.id = id;
    }
 
    public String getDeviceName() {
        return name;
    }
 
    public void setName(String name) {
        this.deviceName = name;
    }
 
    @OneToMany(mappedBy = "device", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
    public Set<WorksiteDevice> getWorksiteDevices() {
        return worksiteDevices;
    }
 
    public void setWorksiteDevices(Set<WorksiteDevice> worksiteDevices) {
        this.worksiteDevices = worksiteDevices;
    }

加入表:

@Entity
@Table(name = "worksite_device")
public class WorksiteDevice {
    private long id;
    private Worksite worksite;
    private Device device;
     
    // additional fields
    private Integer deviceCount;

 
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    @Column(name = "worksite_device_id")
    
    public long getId() {
        return id;
    }
 
    public void setId(long id) {
        this.id = id;
    }
 
   @ManyToOne(fetch = FetchType.LAZY)
   @JoinColumn(name = "worksite_id")
   private Worksite worksite;
 
    public void setWorksite(Worksite worksite) {
        this.worksite = worksite;
    }
 
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "device_id")

 
    public void setDevice(Device device) {
        this.device = device;
    }
 
    public Integer getDeviceCount() {
        return deviceCount;
    }
 
    public void setDeviceCount(Integer deviceCount) {
        this.deviceCount = deviceCount;
    }

}

我有一个 DTO 类,我从用户界面中获取设备的名称和工作场所中使用的设备数量。

public class WorksiteDeviceDTO extends  BaseDTO{

    private Long id;
    private int            deviceCount;
    private String         deviceName;
    private Worksite        worksite;


    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public Integer getDeviceCount() {
        return deviceCount;
    }
 
    public void setDeviceCount(Integer deviceCount) {
        this.deviceCount = deviceCount;
    }

    public String getDeviceName() {
        return deviceName;
    }

    public void setDeviceName(String deviceName) {
        deviceName = deviceName;
    }    


}

我将 DTO 对象保存在一个列表中,并在保存到数据库之前对其进行迭代。这是我这样做的方法: 我首先保存工作站点对象,然后保存工作站点中使用的设备数量和名称

worksiteService.saveWorksite(worksite);
final Map<String, Geraete> deviceByName = worksiteDeviceDtos.stream()
        .map(worksiteDeviceDTO::getDeviceName)
        .map(this::getOrSaveDeviceByName)
        .collect(Collectors.toMap(
                Device::getDeviceName,
                Function.identity()));

worksiteDeviceDtos.forEach(worksiteDeviceDTO -> {
    final WorksiteDevice toSave = new WorksiteDevice();
    toSave.setWorksite(worksite);
    toSave.setDevice(deviceByName.get(worksiteDeviceDTO.getDeviceName()));
    toSave.setDeviceCount(worksiteDeviceDTO.getDeviceCount());
    worksiteDeviceService.saveWorksiteDevice(toSave);

我用这个方法检查数据库中是否存在设备名。如果是这样,我会把它拿回来。如果没有,我用新名称创建一个新对象。

@Transactional
public Device getOrSaveDeviceByName(String DeviceName) {
    return DeviceNameService.findByName(DeviceName)
            .orElseGet(() -> geraeteService.saveNewGeraetWithName(DeviceName));
}

当我在用户界面中更改设备名称并保留设备数量时,将使用修改后的名称创建一个新对象。我不知道如何解决这个问题。有人会有想法。我也尝试使用复合键,但我遇到了同样的问题

【问题讨论】:

    标签: java spring-boot hibernate java-8


    【解决方案1】:

    您似乎一直在创建和保存一个新实例,无论您是否“找到”了该名称的设备。您应该过滤掉找到的元素。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-04-04
      • 1970-01-01
      • 1970-01-01
      • 2016-01-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-11
      相关资源
      最近更新 更多