Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Save an entity and all its related entities in a single save in spring boot

I'm using Spring Boot,REST and JPA to build my application. In app, there are 2 entities with one to many relationship.

Entity 1 :

@Entity
@Table( name = "report")
@JsonIgnoreProperties(ignoreUnknown = true)
public class CustomReport {

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

private String name;
private Long createdBy;
private Timestamp lastModifiedTimestamp;


@OneToMany(mappedBy = "customReport", cascade = CascadeType.ALL)
private Set<CustomReportActivity> customReportActivitySet;



public Set<CustomReportActivity> getCustomReportActivitySet() {
    return customReportActivitySet;
}

public void setCustomReportActivitySet(Set<CustomReportActivity> customReportActivitySet) {
    this.customReportActivitySet = customReportActivitySet;
}



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 Long getCreatedBy() {
    return createdBy;
}

public void setCreatedBy(Long createdBy) {
    this.createdBy = createdBy;
}

public Timestamp getLastModifiedTimestamp() {
    return lastModifiedTimestamp;
}

public void setLastModifiedTimestamp(Timestamp lastModifiedTimestamp) {
    this.lastModifiedTimestamp = lastModifiedTimestamp;
}

}

Entity 2:

@Entity
@Table( name = "report_activity")
public class CustomReportActivity {

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

String activityName;

@ManyToOne
@JoinColumn( name="report_id" )
@JsonBackReference
private CustomReport customReport;

public Long getId() {
    return id;
}

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

public String getActivityName() {
    return activityName;
}

public void setActivityName(String activityName) {
    this.activityName = activityName;
}

public CustomReport getCustomReport() {
    return customReport;
}

public void setCustomReport(CustomReport customReport) {
    this.customReport = customReport;
}

}

And my request JSON is as follows :

{
   "name": "test report",
   "createdBy" : 129,
   "customReportActivitySet": [
        {"activityName":"a"},
        {"activityName":"b"},
        {"activityName":"c"},
        {"activityName":"d"},
        {"activityName":"e"}
    ]  
}

I want to save both entities in one shot. I've implemented the save functionality in following way:

@RequestMapping(value="/save", method = RequestMethod.POST)
public ResponseEntity<?> addReport(@RequestBody CustomReport customReport) {
    return new ResponseEntity<>(customReportService.createCustomReport(customReport), HttpStatus.CREATED);

}

CustomReportService method:

 public CustomReport createCustomReport(CustomReport customReport) {
    return customReportRepository.save(customReport);
}

CustomRepository:

public interface CustomReportRepository extends CrudRepository<CustomReport, Long> {

}

But I'm getting the constraint violation exception with this:

java.sql.SQLIntegrityConstraintViolationException: ORA-01400: cannot insert NULL into ("REPORT_ACTIVITY"."REPORT_ID")

Is it possible to save both entities in one save operation?

Please help!

like image 846
Manisha Avatar asked May 30 '17 13:05

Manisha


People also ask

How do you save a list of entities in Spring data JPA?

For SpringData Jpa, a cleaner approach will be to use repository. saveAll instead of a for loop with repository. save . saveAll will automatically iterate through the list and save it.

What is the use of @table annotation in spring boot?

The @Table annotation allows you to specify the details of the table that will be used to persist the entity in the database. The @Table annotation provides four attributes, allowing you to override the name of the table, its catalog, and its schema, and enforce unique constraints on columns in the table.

What is the use of @entity annotation in spring boot?

The @Entity annotation specifies that the class is an entity and is mapped to a database table. The @Table annotation specifies the name of the database table to be used for mapping.

What is difference between save and Saveflush?

Both methods are used to save entities to the database. Flushing is the process of synchronizing the state of the persistence context with the underlying database. When using saveAndFlush method, data immediately flush to the database and to do it with the save method we need to call flush() method explicitly.


1 Answers

You would have to add a small piece of code which would populate each CustomReportActivity within the CustomReport instance. Only then the persistence provide can successfully perform the cascade save operation:

public CustomReport createCustomReport(CustomReport customReport) {
   customReport.getCustomReportActivitySet.forEach((activity) -> {
      activity.setCustomReport(customReport);
   });

   return customReportRepository.save(customReport);
}

The bottom line is that the dependencies have to be set on both sides of the relationship.

like image 193
Maciej Kowalski Avatar answered Sep 18 '22 23:09

Maciej Kowalski