Lab#SB08-4: JPA

Spring Boot Restaurant Management JPA, Queries, Mappings and Relationships

Spring-Boot
lab
Spring Boot
Author

albertprofe

Published

Wednesday, January 10, 2024

Modified

Wednesday, October 16, 2024

📘 Spring Boot Lab#SB00-4: RestaurantManager JPA, Queries, Mappings and Relationships ## Summary

The Spring Boot RestaurantManagement System utilizes JPA to efficiently manage restaurant operations:

  • Key entities include Menu, MenuItem, Table, Order, and Customer, with defined relationships such as one-to-many and many-to-many.
  • The system employs repositories for database H2 access and services for business logic.
  • Custom queries enhance data retrieval, enabling functionalities like fetching recent orders or customer-specific orders.

This architecture not only facilitates effective data management but also provides a robust foundation for building scalable restaurant applications, leveraging the power of Spring Boot and JPA for seamless integration and performance.


1 RestaurantManager Project Summary

Here’s an introduction to Spring Boot Restaurant Management focusing on JPA, queries, mappings and relationships. This project demonstrates how to build a restaurant management system using Spring Boot and JPA. It covers key concepts like entity relationships, JPA mappings, and database queries.

Key Components

  • Entities: Menu, MenuItem, Order, Customer
  • Repositories: JpaRepository interfaces for database access
  • Services: Business logic and database operations
  • Controllers: REST API endpoints
  • Tests: JUnit unitary tests for queries

JPA Mappings

The system uses the following JPA entity relationships:

  • One-to-Many: Menu to MenuItems
  • Many-to-One: Order to Customer
  • Many-to-Many: Order to MenuItems
Example Menu entity:
Menu.java

@Entity
public class Menu {

  @Id
  //@GeneratedValue
  private String id;
  
  private String name;

  @OneToMany(mappedBy = "menu", cascade = CascadeType.ALL)
  private List<MenuItem> items;

}

Sample Queries

Example Sample OrderRepository:
Menu.java

@Repository
public interface OrderRepository extends JpaRepository<Order, Long> {

  List<Order> findByCustomer(Customer customer);
  
  @Query("SELECT o FROM Order o WHERE o.orderDate > :date")
  List<Order> findRecentOrders(@Param("date") LocalDate date);

}

Key Relationships

  • Menu contains many MenuItems
  • Order is placed by one Customer
  • Order contains multiple MenuItems
  • Customer can have multiple Orders

This structure allows for efficient querying and management of restaurant data using Spring Data JPA.

2 Updated UML

This is the updated UML from Lab#SB08-1 UML and DDD correspoing to this commit: TestCreateOrder() with JPA, Customer 1:n TakeAwayOrder unidirectional relationship

classDiagram
    class OrderRestaurant {
        <<Entity>>
        -String id
        -Date date
        -String waiter
        -int peopleQty
        -double totalPayment
        -boolean paid
        -ArrayList<Menu> menus
        +toString()
    }
    class TakeAwayOrder {
        <<Entity>>
        -Customer customerTakeAway
        +toString()
    }
    class TableRestaurant {
        -String name
        -String description
        -int qty
        -boolean busy
        +toString()
    }
    class ShippingOrderRestaurant {
        -String address
        -String city
        -String riderName
        +toString()
    }
    class Customer {
        <<Entity>>
        -String id
        -String name
        -String email
        -String phoneNumber
        -int age
        -boolean vipCustomer
        -boolean deleted
    }
    class EatInOrderRestaurant {
        -ArrayList<TableRestaurant> tableRestaurants
        +toString()
    }
    class Menu {
        <<Serializable>>
        -String name
        -Double price
        -String content
        -boolean active
        -boolean water
    }
    class Booking {
        -String name
        -String phoneNumber
        -int peopleQty
        -LocalDateTime date
        -TableRestaurant tableRestaurant
        -boolean confirmed
        +toString()
    }

    OrderRestaurant <|-- TakeAwayOrder
    OrderRestaurant <|-- ShippingOrderRestaurant
    OrderRestaurant <|-- EatInOrderRestaurant
    OrderRestaurant "1" *-- "*" Menu
    TakeAwayOrder "*" -- "1" Customer
    EatInOrderRestaurant "1" *-- "*" TableRestaurant
    Booking "1" -- "1" TableRestaurant

3 JPA Relationships

JPA (Java Persistence API) provides several types of relationships to model associations between entities :

  1. OneToOne: Represents a single-valued association where an instance of one entity is related to a single instance of another entity.

  2. OneToMany: Represents a multi-valued association where an instance of one entity can be related to multiple instances of another entity.

  3. ManyToOne: The inverse of OneToMany, where multiple instances of an entity can be related to a single instance of another entity.

  4. ManyToMany: Represents a multi-valued association where multiple instances of one entity can be related to multiple instances of another entity.

These relationships can be either unidirectional or bidirectional:

  • Unidirectional: Only one entity has a reference to the other.
  • Bidirectional: Both entities have references to each other.

Relationships are typically annotated in entity classes using @OneToOne, @OneToMany, @ManyToOne, or @ManyToMany. Additional annotations like @JoinColumn and mappedBy are used to specify the joining strategy and the owning side of the relationship.

3.1 OneToMany and ManyToOne

Entity @oneToMany

Entity @oneToMany

OneToMany Unidirectional

  • One entity has a collection of another entity
  • Only the owning side (the “One” side) has a reference to the other entity
  • Example: One Department has many Employees
@Entity
public class Department {
    @OneToMany
    private List<Employee> employees;
}

@Entity
public class Employee {
    // No reference to Department
}

ManyToOne Unidirectional

ManyToOne Unidirectional example: Order and Customer

  • Many entities are associated with one entity
  • Only the owning side (the “Many” side) has a reference to the other entity
  • Example: Many Employees belong to one Department
@Entity
public class Employee {
    @ManyToOne
    private Department department;
}

@Entity
public class Department {
    // No reference to Employee
}

Bidirectional Relationships

  • Both entities have references to each other
  • The “Many” side is usually the owning side
  • Example: One Department has many Employees, and each Employee belongs to one Department
@Entity
public class Department {
    @OneToMany(mappedBy = "department")
    private List<Employee> employees;
}

@Entity
public class Employee {
    @ManyToOne
    private Department department;
}

In bidirectional relationships, use mappedBy on the non-owning side to indicate the owning side’s field name.

Why Serialization is Needed?

Serialization is the process of converting an object or class into a byte stream. This byte stream can then be easily saved to a file, sent over a network, or stored in a database.

Hibernate uses serialization to create deep copies of entity objects for various purposes, such as detached entities, Session Management or caching.

For example: Collections within entities (like an ArrayList<Menu> menus within a Order entity ) are often serialized to store them efficiently in the database or to manage state changes.

Implementing Serializable is not always the best solution. In some cases, it might be better to adjust your entity relationships (@OneToMany) or use different mapping strategies (@ElementCollection for simple collections).

3.2 ManyToMany

ManyToMany Unidirectional

  • Multiple entities are associated with multiple entities of another type
  • Only one side has a reference to the other entity
  • Example: Many Students can enroll in many Courses
@Entity
public class Student {
    @ManyToMany
    @JoinTable(name = "student_course",
               joinColumns = @JoinColumn(name = "student_id"),
               inverseJoinColumns = @JoinColumn(name = "course_id"))
    private Set<Course> courses;
}

@Entity
public class Course {
    // No reference to Student
}

ManyToMany Bidirectional

  • Both entities have references to each other
  • One side is designated as the owning side
  • Example: Many Students can enroll in many Courses, and each Course can have many Students
@Entity
public class Student {
    @ManyToMany
    @JoinTable(name = "student_course",
               joinColumns = @JoinColumn(name = "student_id"),
               inverseJoinColumns = @JoinColumn(name = "course_id"))
    private Set<Course> courses;
}

@Entity
public class Course {
    @ManyToMany(mappedBy = "courses")
    private Set<Student> students;
}

In bidirectional ManyToMany relationships, use mappedBy on the non-owning side to indicate the owning side’s field name. The @JoinTable annotation is used to specify the join table details.

ManyToMany Considerations
  • ManyToMany relationships often require a join table in the database
  • Consider using an intermediate entity for complex relationships or when additional attributes are needed for the relationship
  • Be cautious of performance implications with large datasets

4 Inherence and JPA

// to do

5 Queries

// to do

6 Code