2


I have a problem with updating my database data with Spring rest JPA (PUT Method).

When I do a POST request to insert data, It works perfectly, I have all my data inserted in the right way, however, when I try to update my data with a PUT, the Name is updated event in the database, but not GeometryBasic, I tried to log its value It changes correctly but not in the database, hibernate doesn't persist new values data. I have my classes as following:

Location

@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() + "]";
    }

}

Multi

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

}

Geometry

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

GeometryBasic

@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
}

MultiBasic

@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>();

}

GeometryHelper

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;
     }

}

Class

@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));
    }
}
TobiP
  • 43
  • 7

1 Answers1

0

I was facing the same issue. PUT for nested objects does not work. However POST and PATCH worked fine.

Just replace your HTTP verb from PUT to PATCH. Patching all fields of your resource (request body will be the same as if you were using PUT) will do the same as if you were to PUT the resource.

Maybe this is a bug in Spring Data Rest?

Maybe related: Spring Data REST - PUT request does not work properly since v.2.5.7

TobiP
  • 43
  • 7