avatarIvan Franchin

Summary

The provided content discusses the implementation of a one-to-many relationship between Restaurant and Dish entities using Spring Data JPA with a simple primary key strategy.

Abstract

The article delves into the intricacies of JPA relationships, specifically focusing on the one-to-many association between Restaurant and Dish entities. It provides a detailed explanation of how to map these entities using Spring Data JPA annotations, such as @OneToMany and @ManyToOne, to create a bidirectional relationship where a restaurant can have multiple dishes, but a dish belongs to only one restaurant. The author, Ivan Franchin, illustrates the use of the @Entity annotation to map classes to database tables, the @Id and @GeneratedValue annotations for primary key generation, and the @JoinColumn annotation to specify the foreign key relationship. The article also covers the use of cascading operations and the orphanRemoval attribute to manage the lifecycle of related entities. Additionally, the author has created a GitHub repository with examples for each relationship type to aid developers in understanding JPA relationships. The article concludes by showing the resulting table structures in a PostgreSQL database, emphasizing the importance of these relationships in application development.

Opinions

  • The author expresses personal difficulty in correctly implementing JPA relationships, which motivated the creation of the article and the accompanying GitHub repository.
  • Ivan Franchin believes that the examples and explanations provided will be beneficial for developers looking to enhance their understanding of JPA relationships.
  • The use of a GitHub repository with simple examples for each relationship type is presented as a valuable resource for learning and reference.
  • The author encourages reader engagement through clapping, sharing, following on social media, and subscribing to a newsletter, indicating a desire for community interaction and feedback.
  • The article promotes the idea that understanding JPA relationships is crucial for developers working with Spring Data JPA in their applications.

Spring Boot | Spring Data JPA

Understanding Relationships in JPA: One-to-Many with Simple Primary Key

Discussing “One-to-Many with Simple Primary Key” and examining how JPA/Hibernate generates the corresponding tables

Photo by Alex Haney on Unsplash

As mentioned in the introductory article of this series, I’ve faced difficulties in implementing JPA relationships correctly in my applications.

To enhance my understanding of them, I developed a GitHub repository called ivangfr/spring-data-jpa-relationships, containing simple examples for each relationship type.

In this series of articles, we will demonstrate each JPA relationship type by presenting the necessary code to map the entities and examining how JPA/Hibernate generates the tables.

I hope you find these articles and the GitHub repository helpful.

Today, we will talk about “One-to-Many with Simple Primary Key”. So, let’s get started!

One-to-Many with Simple Primary Key

In this example, we will associate Restaurant and Dish entities. A restaurant can have zero, one, or more dishes, and a dish can only be present in the menu of one restaurant. Additionally, the Dish entity will have its own auto-increment ID.

Below is the desired database model we aim to achieve.

This is the complete and final code. Next, we will explain it in detail.

@Entity
@Table(name = "restaurants")
public class Restaurant {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    private Long id;

    @OneToMany(mappedBy = "restaurant", cascade = CascadeType.ALL, orphanRemoval = true)
    private Set<Dish> dishes = new LinkedHashSet<>();

    @Column(nullable = false)
    private String name;

    // getters and setters
}

@Entity
@Table(name = "dishes")
public class Dish {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "restaurant_id")
    private Restaurant restaurant;

    @Column(nullable = false)
    private String name;

    // getters and setters
}

We create two classes, Restaurant and Dish, and use the @Entity annotation to indicate that these classes correspond to database tables.

By default, the table name would be the same as the entity name, but we want them to be in plural form. We can achieve this by using the @Table annotation, where we specify the desired table name. For the Restaurant entity, we use “restaurants”, and for the Dish entity, we use “dishes”.

Next, we add the id field of type Long and the name field of type String to both Restaurant and Dish classes.

To ensure that the name field in the Person and Dish entities cannot have null values, we add the @Column(nullable = false) annotation to it. This annotation tells JPA that the corresponding database column should be defined as NOT NULL.

For theid field in both Restaurant and Dish entities, we add the annotations: @Id and @GeneratedValue(strategy = GenerationType.SEQUENCE). The @Id annotation indicates that the field is the primary key for the entity, while the @GeneratedValue annotation specifies the strategy for generating the ID.

In the Restaurant class, we create a dishes field that contains a Set of Dish objects. In the Dish class, we create a restaurant field that contains a Restaurant object.

To establish the relationship between these entities, we use the @OneToMany annotation on the dishes field in the Restaurant class and the @ManyToOne annotation on the restaurant field in the Dish class.

The mappedBy used in the @OneToMany annotation on the dishes field in the Restaurant class indicates that the relationship between Restaurant and Dish is bidirectional, and that the owning side of the relationship is the Dish entity. The mappedBy attribute specifies the name of the field in the Dish class that owns the relationship, which in this case is the restaurant field.

The cascade = CascadeType.ALL is used to specify that all cascading operations should be applied to the Dish entity when the Restaurant entity is persisted, updated, or deleted. This means that if a Restaurant is deleted, the associated Dish will also be deleted.

The orphanRemoval = true means that when a dish is removed from the Set of dishes in the Restaurant entity, it will also be deleted from the database.

The fetch = FetchType.LAZY parameter, specified in the @ManyToOne annotation of the Dish class, indicates that the associated restaurant should be loaded lazily only when necessary to enhance performance.

We use the @JoinColumn annotation on the restaurant field in the Dish class to specify that this field is the join column for the relationship between the Dish entity and the Restaurant entity. The name attribute in the @JoinColumn annotation specifies the name of the foreign key column in the Dish table. In our example, the foreign key column’s name is restaurant_id.

Lastly, let’s describe the tables in PostgreSQL terminal.

jparelationshipsdb=# \d restaurants
                    Table "public.restaurants"
 Column |          Type          | Collation | Nullable | Default
--------+------------------------+-----------+----------+---------
 id     | bigint                 |           | not null |
 name   | character varying(255) |           | not null |
Indexes:
    "restaurants_pkey" PRIMARY KEY, btree (id)
Referenced by:
    TABLE "dishes" CONSTRAINT "fkpslsa9mci7gsfhwukb3mx7s6n" FOREIGN KEY (restaurant_id) REFERENCES restaurants(id)



jparelationshipsdb=# \d dishes
                          Table "public.dishes"
    Column     |          Type          | Collation | Nullable | Default
---------------+------------------------+-----------+----------+---------
 id            | bigint                 |           | not null |
 name          | character varying(255) |           | not null |
 restaurant_id | bigint                 |           |          |
Indexes:
    "dishes_pkey" PRIMARY KEY, btree (id)
Foreign-key constraints:
    "fkpslsa9mci7gsfhwukb3mx7s6n" FOREIGN KEY (restaurant_id) REFERENCES restaurants(id)

The restaurants and dishes tables both have their own id column as the Primary Key. Additionally, the dishes table has a restaurant_id column which acts as a Foreign Key referencing the id column in the restaurants table.

Conclusion

In this series of articles, we are exploring the four different types of relationships in JPA: one-to-one, one-to-many / many-to-one, and many-to-many. By presenting simple examples for each type of relationship and providing necessary code to map the entities, we hope to help developers to gain a better understanding of the JPA relationships.

Support and Engagement

If you enjoyed this article and would like to show your support, please consider taking the following actions:

  • 👏 Engage by clapping, highlighting, and replying to my story. I’ll be happy to answer any of your questions;
  • 🌐 Share my story on Social Media;
  • 🔔 Follow me on: Medium | LinkedIn | Twitter | GitHub;
  • ✉️ Subscribe to my newsletter, so you don’t miss out on my latest posts.
Jpa
Spring Data Jpa
Technology
Database
Relational Databases
Recommended from ReadMedium