Modelling Applications with JPA & Spring Boot

A short prelude
I recently attended a bootcamp where we needed to setup an API for an e-commerce store using Spring Boot. The API itself was fairly straightforward — a list of books that can be purchased and a cart to hold a bunch of books — your typical e-commerce application.
I, like most of my teammates during the bootcamp, were very new to Spring Boot and relied heavily on documentation to get up and running. Most of us came from rich ecosystems like Ruby on Rails, Laravel, Express etc… where setting up an API is a fairly quick task and the ORM generally is very quick to setup and start using.
Unfortunately, things aren’t that straight forward with Spring Boot. The go-to ORM when using Spring Boot, from my limited experience, is JPA. If you’ve done it long enough, you’re probably at home working with it, but since you’re reading this post, I presume you’re in a situation where you just can’t figure out how the pieces fit together.
This blog post, hopefully will give you an overview of accomplishing the most common tasks using JPA and Spring Boot -
- Creating Model classes
- Customising model attributes (columns and tables)
- Creating relationships between models (tables)
What is JPA
JPA or Java Persistence API is a layer of abstraction for interacting with SQL databases. It is an ORM.
Creating and Customising Models
The basic unit of persistence in JPA is the Entity, which is nothing but a Java class with annotations. This class describes the database table. Every Entity class must have an @Entity
annotation and @Id
annotation, which maps to the primary key of the table.
The @Table
annotation is optional. By default, JPA will use the Java class name as the table name. In this case, my table name is books
while my class is named Book
Similarly, let’s create a Customer
entity.
Continuing with our e-commerce use case, we need to create an orders
table that will generate an order id and have a reference to the customer who placed the order.
Relationships
One of the major advantages SQL databases provide is relationships and integrity constraints. Our book store allows a customer to order many books. In our current schema, a customer can create an order but there is no table to hold the line items for that order. Since each order
contains many line items we need to create a new table order_line_items
that can hold this information. This is a one-to-many relationship where each order has many line items.
A few new annotations are used:
@Column
is similar to@Table
It allows us to break out of the default behaviour of JPA and specify a custom column name.@ManyToOne
is the glue that specifies the relationship between the two tables. This allows us to dolineItem.order.id
in our code to fetch the related model.@JoinColumn
informs JPA about the column (foreign key) that is used to form this relationship in our table.
Also, notice that we added 2 more properties to the class without any annotations — Double price
and Double quantity
. JPA, by default, will look for columns by this name.
Now that we have setup the @ManyToOne
relationship, let’s do the inverse, ie create a @OneToMany
relationship from Order
entity to OrderLineItem
. Additionally, we will define the relationship between aCustomer
and Order
.
In a bidirectional relationship pair, such as the @OneToMany
relationship fromOrder
to OrderLineItem
and the @ManyToOne
relationship back from OrderLineItem
to Order
, only one foreign key is required in one of the entities to manage both sides of the relationship. As a general rule, the side that does not have the foreign key (in our case Order
) specifies a mappedBy
attribute in the relationship annotation and specifies the field in the related entity (in our case OrderLineItem
) that maps the foreign key.
Finally, we’ll define the relationship from Customer
to Order
. We know that a customer can place multiple orders, so our relationship here is @OneToMany
from Customer
to Order
And that’s it! With this, you should have the minimum setup required to get up and running using JPA as your ORM.
If this post helped you, I’d love a 👏
PS: If I made any mistakes please let me know in the comments. I’m new to Java and would love to better my understanding.
PPS: Here’s the code!