One-to-Many Relationship Spring Data JPA

One-to-Many Relationship Spring Data JPA

Play this article

In this article, we will continue our learning about implementing relationships between entities in Spring Boot JPA. Today we will learn about implementing One-to-Many relationship.

One-to-Many Relationship

A one-to-many relationship is a type of cardinality that refers to the relationship between two entities A and B in which an element of A may be linked to many elements of B, but a member of B is linked to only one element of A.

Let's take an example of person and credit card, a person may have more than one credit card but one credit card is linked with only one person.

The person and passport classes are using Lombok to reduce boilerplate code, I suggest you to go through Lombok article .

Person.java

@Entity
@Table(name = "person")
@Getter @Setter @Builder
@NoArgsConstructor
@AllArgsConstructor
public class Person {

    @Id
    @Column(name = "person_id")
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer personId;

    @Column(name = "person_name")
    private String personName;    

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @JoinTable(name = "person_card_mapping",
                joinColumns = @JoinColumn(name = "person_id"),
                inverseJoinColumns = @JoinColumn(name = "card_id"))
    private List<Card> cards;

}

Card.java

@Entity
@Table(name = "card")
@Getter @Setter @Builder
@NoArgsConstructor
@AllArgsConstructor
public class Card {

    @Id
    @Column(name = "card_id")
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer cardId;

    @Column(name = "card_no")
    private String cardNo;

    @Column(name = "cardholder_name")
    private String cardholderName;

    @Column(name = "expiry_month")
    private String expiryMonth;

    @Column(name = "expiry_year")
    private String expiryYear;    
}

The relationship in the ER diagram is represented as follow:

image.png

The mapping is implemented in database using a mapping table which stores the primary key or identifying column from both the entities.

@JoinTable is used to specify the name of mapping table and joining column details.

name = "person_card_mapping" specifies the mapping table name where the primary keys will be stored.

joinColumns = @JoinColumn(name = "person_id") specifies that from person table person_id column will be used to implement mapping.

inverseJoinColumns = @JoinColumn(name = "card_id")) specifies that from card table card_id column will be used to implement mapping.

Testing

Let's see a test case to test the unidirectional one-to-many relationship between Person and Cards.

@SpringBootTest
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class OneToManyMappingTests {

    @Autowired
    private PersonRepository personRepo;

    private Person person = null;
    private Card card1 = null;
    private Card card2 = null;

    private Integer personId;

    @BeforeAll
    public void setup() {

        card1 = Card.builder()
                .cardholderName("John Doe")
                .cardNo("4578963214502354")
                .expiryMonth("12")
                .expiryYear("2022")
                .build();

        card2 = Card.builder()
                .cardholderName("John Doe")
                .cardNo("4111111111111111")
                .expiryMonth("02")
                .expiryYear("2025")
                .build();

        List<Card> cards = new ArrayList<>();
        cards.add(card1);
        cards.add(card2);

        person =  Person.builder()
                .personName("John Doe")
                .cards(cards)
                .build();

        person = personRepo.save(person);
        personId = person.getPersonId();
    }


    @Test
    public void testOneToMany() {

        Person person  = personRepo.findById(personId).orElse(null);

        assertNotNull(person.getCards());
        assertEquals("4578963214502354", person.getCards().get(0).getCardNo());
        assertEquals("4111111111111111", person.getCards().get(1).getCardNo());

    }

}

On running this test case, we will find all these test cases runs successfully and verifies that our implementation is correct.

Summary

In this article, we learnt about implementation of one-to-many mapping relationship in Spring Data JPA. The other mapping relationship in Spring Data JPA will be discussed in further post.

Check this article for implementing One-to-One mapping.

Check this article for implementing Many-to-Many mapping.

You can find the source code of this post @ Github