Spring Data JPA: Implementing OneToMany Association

  • Post last modified:August 6, 2023
  • Reading time:3 mins read

Learn one-to-many associations it’s and implementation

Introduction

  • In this article, we will learn about the one-to-many association, when to use them, and implement them using Spring data JPA using one example.

One to Many Association

  • Let’s understand the one-to-many association with a simple example. We have two entities/tables in the database. One is Customer and another is CreditCard.
  • A Customer can have one or more CreditCard which defines the relationship between one to many.
  • One-to-many relationships exist in the database when one row in the table has a relation with many rows in another table.

Entities

  • Let’s define the necessary entities for our use case.

Customer

  • In the customer entity, we need to define the @OneToMany relation where we define the List of CreditCard as a child association.
  • This association will basically allow us access to all the CreditCard belonging to a given Customer entity.
@Entity
@Table(name="customer")
public class Customer {
    @Id
    @GeneratedValue(strategy= GenerationType.SEQUENCE, generator = "customer_id_seq")
    @SequenceGenerator(name = "customer_id_seq", sequenceName = "customer_id_seq", allocationSize = 1)
    private Long id;
    private String name;

    @OneToMany(mappedBy = "customer")
    private List<CreditCard> creditCard = new ArrayList<>();
    
   // getters and setters
}
  • In our database, we have one customer for this use case.

Credit Card

  • For the CreditCard entity we need to define @ManyToOne association with parent so that we can set up bidirectional relation.
  • This will allow us to find the parent entity from the child entity. Basically, if we have a CreditCard entity we can get a Customer entity from it.
@Entity
@Table(name="credit_card")
public class CreditCard {
    @Id
    @GeneratedValue(strategy= GenerationType.SEQUENCE, generator = "credit_card_id_seq")
    @SequenceGenerator(name = "credit_card_id_seq", sequenceName = "credit_card_id_seq", allocationSize = 1)
    private Long id;
    private String cardNumber;
    private String expiryDate;

    @ManyToOne
    @JoinColumn(name="customer_id")
    @JsonIgnore
    private Customer customer;
}
  • For our use case, we have two credit cards for the customer with id 10;

Business Logic

Repository

  • For CustomerRepository and CreditCardRepository, All we need is to extend from JpaRepository.
  • This will provide basic methods to execute queries on the database.
public interface CustomerRepository extends JpaRepository<Customer,Long> {
}

public interface CreditCardRepository extends JpaRepository<CreditCard,Long> {
}

Controller

  • We have a rest endpoint that accepts the request param of customerId and returns the List of CreditCard as a response.
@RestController
@RequestMapping("/customer")
public class CustomerController {

  @Autowired
  private CustomerLogic customerLogic;

  @GetMapping("/credit-card")
  @ResponseBody()
  private List<CreditCard> getAllCards(@RequestParam long customerId){
      return customerLogic.getAllCards(customerId);
  }

}

Logic

  • Our logic gets the customer entity from customerId. Since we have a relation setup in the entity we can get the list of CreditCard for that customer.
public List<CreditCard> getAllCards(Long customerId){
    Optional<Customer> customer = customerRepository.findById(customerId);
    return customer.map(Customer::getCreditCard).orElse(null);
}

Result

  • Let’s access the rest endpoint from the postman. We are passing customerId 10 as the request param.
  • We received a list of CreditCard as a response.

Conclusion

  • In this article, we learned about the one-to-many association with simple use cases.
  • JPA provides abstractions that help in setting up unidirectional and bi-directional relationships.

Before You Leave

Leave a Reply