Spring Data REST
OneToMany
sub-resource
POST request
REST API

POSTing a OneToMany sub-resource association in Spring Data REST

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Spring Data REST is a powerful framework that builds on top of Spring Data, allowing developers to export repositories as RESTful endpoints effortlessly. When dealing with a complex data model in a Spring Data ecosystem, you often encounter @OneToMany relationships. A common need is to persist a @OneToMany sub-resource association using the RESTful approach. In this article, we'll explore how to accomplish that through a POST request in Spring Data REST.

Understanding the Domain Model

To understand how to post a @OneToMany sub-resource association, let's first define a simple domain model with entities that are typically involved in such an association.

Example Entities

Consider two entities: Order and Item. An Order can have multiple Items, but each Item belongs to only one Order.

java
1@Entity
2public class Order {
3    @Id @GeneratedValue
4    private Long id;
5    private String customerName;
6
7    @OneToMany(mappedBy = "order", cascade = CascadeType.ALL)
8    private Set<Item> items = new HashSet<>();
9
10    // Getters and setters
11}
12
13@Entity
14public class Item {
15    @Id @GeneratedValue
16    private Long id;
17    private String productName;
18    private double price;
19
20    @ManyToOne
21    @JoinColumn(name = "order_id")
22    private Order order;
23
24    // Getters and setters
25}

Generated REST Endpoints

With Spring Data REST, all CRUD operations are automatically exported as RESTful endpoints. For the above entities, the following endpoints are generated, among others:

  • /orders - To handle Order resources.
  • /items - To handle Item resources.

Posting an @OneToMany Relationship

To post an @OneToMany relationship, it’s essential to manage both the owner (Order) and the child resources (Items).

Creating an Order with Items

When you want to create an Order that includes Items, you can send a POST request to the /orders endpoint, including the item details in the body as a subresource data:

Example JSON Payload for Creating an Order with Items

This is how a typical JSON payload might look:

json
1{
2  "customerName": "John Doe",
3  "items": [
4    { "productName": "Laptop", "price": 1200.00 },
5    { "productName": "Mouse", "price": 25.00 }
6  ]
7}

POST Request

bash
1POST /orders
2Content-Type: application/json
3
4{
5  "customerName": "John Doe",
6  "items": [
7    { "productName": "Laptop", "price": 1200.00 },
8    { "productName": "Mouse", "price": 25.00 }
9  ]
10}

Handling Cascade Persist

In the entity model above, we use CascadeType.ALL on the @OneToMany relationship. This configuration ensures that when an Order is saved, its associated Items will also be saved automatically.

Alternative: Creating Items Separately

If you prefer to create Items separately and then associate them with an Order, this involves posting to the /items endpoint first and then associating them with an order by updating the order's items relationship using its URI.

Configuring Spring Data REST

By default, Spring Data REST does a remarkable job of handling relationships. However, if you need to customize its behavior, consider extending the RepositoryRestConfigurer to control aspects such as allowed HTTP methods, link exposure, etc.

For example, to disable the DELETE method on the Item resource:

java
1@Configuration
2public class RestConfig extends RepositoryRestConfigurerAdapter {
3    @Override
4    public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
5        config.getExposureConfiguration()
6            .forDomainType(Item.class)
7            .withItemExposure((metadata, httpMethods) ->
8                httpMethods.disable(HttpMethod.DELETE));
9    }
10}

Summary Table

AspectDescription
EntitiesOrder with @OneToMany Set<Item> relationship.
Endpoints/orders and /items default Spring Data REST endpoints.
POST AssociationThrough /orders endpoint with items as sub-resource in JSON payload.
Cascade OperationsUse CascadeType.ALL to automatically persist associated Items.
CustomizationPossible through RepositoryRestConfigurerAdapter for customizing methods.

Additional Considerations

  • Handling Updates: When updating an Order with Items, similar principles apply. Ensure the payload correctly represents the items you intend to maintain or modify.
  • Transactional Boundaries: When dealing with complex associations, consider transactional boundaries to ensure data integrity especially in environments with concurrency.
  • Validation: Implement validation to enforce business rules and entity integrity. Bean validation annotations such as @NotNull or @Size can be leveraged here.

Incorporating @OneToMany associations with Spring Data REST and effectively managing resource creation and association with POST requests allows for a flexible, scalable data management API. The seamless integration ensures that developers can focus more on business logic rather than boilerplate code. By understanding and configuring Spring Data REST appropriately, you can efficiently manage complex data models and their interactions.


Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.