Home > database >  Spring Boot save nested Entity with JSON RequestBody
Spring Boot save nested Entity with JSON RequestBody

Time:04-01

I'm trying to create a Rest API for a school project.Therefor I'm trying to save/edit a nested Object. I have two bidirectional entities which look like this:

EntityA

 @Entity
    public class EntityA {
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        @Id
        @Column(name = "id", nullable = false)
        @JsonProperty("id")
        private int id;
    
        @Column(name = "field1", nullable = false, length = -1)
        @JsonProperty("field1")
        private String field1;
    
        @Column(name = "field2", nullable = false, length = -1)
        @JsonProperty("field2")
        private String field2;
    
        @OneToMany(mappedBy = "entityA", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
        @JsonProperty("entityB")
        private List<EntityB> entityB;
    
        public EntityA() {
    
        }
        
        //Getter Setter
        
    }

EntityB

@Entity
public class EntityB {
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Id
    @Column(name = "id", nullable = false)
    @JsonProperty("id")
    private int id;

    @Column(name = "field1", nullable = false)
    @JsonProperty("field1")
    private Date field1;

    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JoinColumn(...)
    @JsonProperty("entityA")
    private EntityA entityA;

    public EntityB() {

    }
    
   //Getter Setter
}

As RequestBody I will get JSON which should look like this.

{
     "field1": "Test",
     "field2": "User",
     "entityB": [
            {
                "field1": "30.03.2022"
            }
        ]
}

Right now Spring will automatically map the fields but as soon I try to save it to my DB I will get an error, because the relation in EntityB for EntityA is empty. I've seen a solution, that I should loop through the EntityB list and add EntityA. I tried it with a for-each but it still sais it null.

What am I doing wrong?

public EntityA createEntityA(EntityA entityA) {
        for(EntityB entityB : entityA.getEntityB()){
            entityB.setEntityA(entityA);
        }
        return entityARepository.save(entityA);
    }

Edit:

Controller

@PostMapping(value = {"/json/entitya/"})
@ResponseBody
public EntityA createEntityAJson(@RequestBody EntityA entityA) {
    return entityAService.createEntityA(entityA);
}

Service

@Service
public class EntityAService {

    @Autowired
    private EntityARepository entityARepository;

    public EntityA createEntityA(EntityA entityA) {
        return entityARepository.save(entityA); //in this line the error appears
    }
}

Error message

null value in column "entityA" violates not-null constraint

CodePudding user response:

I'm guessing that what is happening here is that the id fields which are of a non-nullable datatype or some other hidden field from the JPA annotations get set to the wrong value by the json deserialization for JPA to understand that they are new entities. Creating these entities manually in the Java code might solve the issue.

You shouldn't reuse your entity classes as data transfer object for your API. Having classes containing both database-specific annotations and annotations for JSON serialization is a bad idea and it goes against the single-responsibility principle (SRP).

Create separate DTO classes for your API endpoint, then read the entities from the database an copy the values from the DTO object to the entities before saving.

// Receive DTO
// Read entity from DB if update or create new entities if insert
// Copy values from DTO to entitiy
// Save entity

I think your problems will go away if you apply this pattern.

CodePudding user response:

@Service
public class EntityAService {
    
        @Autowired
        private EntityARepository entityARepository;
        @Autowired
        private EntityBRepository entityBRepository;
    
        public EntityA createEntityA(EntityA entityA) {

      // create an empty arrayList to stock the entities B retrieveed from the DB
       List<EnityB> lst = new ArrayList<>();
        
        // get the entities B from the JSON and sabe it to the DB    
        for(EntityB entityB : entityA.getEntityB()){
        entityB.setEntityA(entityA);
        entityBRepository.save(entityB);  // you should save entities B to the DataBase before
        Optional<EntityB > opt = entityBRepository.findById(entityB.getId());
        EntityB b = opt.get();
        
        // add the entities B retrieved from the DB to the arrayList
        lst.add(b);
        }
        
        // set the EntityB list with the new List from the DB ( include ids ..)
        entityA.setEntityB(lst);
         
        // save the entityA to the DB
            return entityARepository.save(entityA); 
        }
    }
  • Related