Spring JPA 更新不适用于嵌套对象

Posted

技术标签:

【中文标题】Spring JPA 更新不适用于嵌套对象【英文标题】:Spring JPA Update not working on nested objects 【发布时间】:2018-11-04 14:54:40 【问题描述】:

我在使用 Spring rest JPA(PUT 方法)更新数据库数据时遇到问题。

当我执行 POST 请求以插入数据时,它工作得很好,我的所有数据都以正确的方式插入,但是,当我尝试使用 PUT 更新我的数据时,数据库中的 Name is updated 事件,但不是GeometryBasic,我尝试记录它的值它正确更改但不在数据库中,休眠不会保留新值数据。 我的课程如下:

位置

@Data
@Entity
@Table(name="sw_locations")
public class Location 

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "Location_Generator")
    @SequenceGenerator(name="Location_Generator", sequenceName = "Location_Sequence")
    private Long id;

    @Column(name = "latitude")
    private Double latitude;

    @Column(name = "longitude")
    private Double longitude;

    @Column(name = "x")
    private Double x;

    @Column(name = "y")
    private Double y;


    @ManyToOne @JoinColumn(name="multi_id") @JsonIgnore
    private MultiBasic multi;

    public boolean isEmpty() 
        boolean hasNoPointCoord = (this.getLatitude() ==null && this.getLongitude() == null);
        return  hasNoPointCoord;
    

    @Override
    public String toString() 
        return "Location [point="+this.getX()+" : "+this.getY()+" : "+this.getLatitude() +" : "+ this.getLongitude() + "]";
    


多个

public class Multi extends ArrayList<Location>
//Some methods

几何

public class Geometry extends ArrayList<Multi>
    //Some Methods

几何基础

@Data
@Entity
@Table(name="sw_geometries")
public class GeometryBasic

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "Geometry_Generator")
    @SequenceGenerator(name="Geometry_Generator", sequenceName = "Geometry_Sequence")
    private long id;

    @OneToMany(mappedBy="geometry",
               cascade= CascadeType.ALL, fetch=FetchType.LAZY)
    private List<MultiBasic> multies = new ArrayList<MultiBasic>();

    //some other methods

多基础

@Data
@Entity
@Table(name="sw_multis")
public class MultiBasic

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "Multi_Generator")
    @SequenceGenerator(name="Multi_Generator", sequenceName = "Multi_Sequence")
    private long id;

    @ManyToOne @JoinColumn(name="geometry_id") @JsonIgnore
    private GeometryBasic geometry;


    @OneToMany(mappedBy="multi",
               cascade= CascadeType.ALL,fetch=FetchType.LAZY)
    private List<Location> locations = new ArrayList<Location>();


几何助手

public class GeometryHelper 

     public static Geometry map(GeometryBasic geom) 


         //Check if geometry object is defined and contains multies
        if(geom == null || geom.isEmpty())
            return null;

        Geometry geometry = new Geometry();

        //Map nested collections into 2D Array.
        geom.getMulties().forEach(m->
            Multi multi  = new Multi();
            multi.addAll(m.getLocations());
            geometry.add(multi);
        );

        return geometry;
    

     public static GeometryBasic mapToBasic (Geometry geom) 


         //Check if geometry object is defined and contains multies
        if(geom == null)
                return null;
        GeometryBasic geometry = new GeometryBasic();
        List<MultiBasic> multis = new ArrayList<MultiBasic>();

        //Iterate over multis to add link to geometry 
        geom.forEach(m ->
            MultiBasic multi = new MultiBasic();
            List<Location> locations = new ArrayList<Location>();

            //iterate over locations to add link to Multi
            m.forEach( l -> 
                l.setMulti(multi);
                locations.add(l);
            );

            multi.setLocations(locations);
            multi.setGeometry(geometry);
            multis.add(multi);
        );

        geometry.setMulties(multis);

        return geometry;
     


@MappedSuperclass
public abstract class AbstractEntityWithNameTitleLocation extends AbstractEntityWithNameTitle 

    @Column(name="entity_name")
    private String name;


    @OneToOne(fetch = FetchType.EAGER, cascade= CascadeType.ALL) @JoinColumn(name = "id_geometry")  @JsonIgnore
    private GeometryBasic geometryBasic;

    public GeometryBasic getGeometryBasic() 
        return this.geometryBasic;
    

    public void setBasicGeometry(GeometryBasic geometry) 
        this.geometryBasic = geometry;
    

    @Transient
    Geometry geometry;

    //Return the transformed object basic geometry
    public Geometry getGeometry() 
        return GeometryHelper.map(this.geometryBasic);
    

    //Return the transformed object basic geometry
    public void setGeometry(Geometry geom) 
        this.setBasicGeometry(GeometryHelper.mapToBasic(geom));
    

【问题讨论】:

您的 MultiBasic.geometry 属性上有一个 @JsonIgnore。这意味着它也将被 PUT 请求忽略。 我关闭了@JsonIgnore,但没有任何改变,我在日志控制台上看不到更新查询。 我忘了告诉我我正在使用这个对象 "geometry":[["x":-170341.70902636572,"y":5977585.216564284,"longitude":-1.53​​02056074142456,"latitude":47.217116005214564 ]] 仍然没有答案:/ 【参考方案1】:

我也面临同样的问题。嵌套对象的 PUT 不起作用。但是 POST 和 PATCH 工作正常。

只需将 HTTP 动词从 PUT 替换为 PATCH。修补资源的所有字段(请求正文与使用 PUT 相同)将与 PUT 资源相同。

也许这是 Spring Data Rest 中的一个错误?

可能相关:Spring Data REST - PUT request does not work properly since v.2.5.7

【讨论】:

以上是关于Spring JPA 更新不适用于嵌套对象的主要内容,如果未能解决你的问题,请参考以下文章

存储库注释不适用于 Spring 数据 JPA

Postgres Interval 不适用于本机 Spring 数据 JPA 查询

Spring data jpa 不适用于自动配置的 entityManagerFactory

Spring Boot Autowired 存储库不适用于 SpringRunner 和 JPA 数据

Fetch.lazy 不适用于 spring boot jpa,一定是啥问题?

Spring boot JPA - 延迟加载不适用于一对一映射