Table of Content
What is JPA?
What is ORM?
Why use JPA?
JPA Relationship Types
Use of EntityManager and Spring Data JPA
What is JPA?
The Java Persistence API (JPA) is the Java standard for mapping Java objects to a relational database.
JPA is one possible approach to ORM. Via JPA, the developer can map, store, update, and retrieve data from relational databases to Java objects and vice versa.
JPA can be used in Java-EE and Java-SE applications. JPA is a specification and several implementations are available.
Objet Relational Mapping (ORM)
The Object Relational Mapping is the base of JPA, which is all about representing and accessing data in the form of plain Java Objects – called Entities.
Hibernate, EclipseLink, and Apache OpenJPA are some of the JPA implementations, out of which, Hibernate is more popular and widely used.
Why use JPA?
To reduce the burden of writing codes for relational object management of an enterprise application, a programmer follows the JPA Provider framework (an implementation of JPA), which allows easy interaction with the database instance.
JPA Relationship Types
In a relational database, the relationships between the two tables are defined by foreign keys. Typically, one table has a column that contains the primary key of another table’s row.
In JPA, we deal with entity objects that are Java representations of database tables. So we need a different way of establishing a relationship between two entities.
JPA entity relationships define how these entities refer to each other.
One-to-one relationships
The @OneToOne annotation is used to define a one-to-one relationship between two entities.
For example, you may have a User entity that contains a user's name, email, and password, but you may want to maintain additional information about a user (such as age, gender, and favorite color) in a separate UserProfile entity.
The @OneToOne annotation facilitates breaking down your data and entities this way.
The User class below has a single UserProfile instance. The UserProfile maps to a single User instance.
@Entity
public class User {
@Id
private Integer id;
private String email;
private String name;
private String password;
@OneToOne(mappedBy = "user")
private UserProfile profile;
...
}
@Entity
public class UserProfile {
@Id
private Integer id;
private int age;
private String gender;
private String favoriteColor;
@OneToOne
private User user;
...
}
The JPA provider uses UserProfile's user field to map UserProfile to User.
The mapping is specified in the mappedBy attribute in the @OneToOne annotation.
One-to-many and many-to-one relationships
The @OneToMany and @ManyToOne annotations facilitate both sides of the same relationship.
Consider an example where a Book can have only one Author, but an Author may have many books.
The Book entity would define a @ManyToOne relationship with Author and the Author entity would define a @OneToMany
relationship with Book.
@Entity
public class Book {
@Id
private Integer id;
private String name;
@ManyToOne
@JoinColumn(...)
...
}
@Entity
public class Author {
@Id
@GeneratedValue
private Integer id;
private String name;
@OneToMany(mappedBy = "author")
private List<Book> books = new ArrayList<>();
...
}
In this case, the Author class maintains a list of all of the books written by that author, and the Book class maintains a reference to its single author.
Additionally, the @JoinColumn specifies the name of the column in the Book table to store the ID of the Author.
Many-to-many relationships
Finally, the @ManyToMany annotation facilitates a many-to-many relationship between entities. Here's a case where a Book entity has multiple Authors:
@Entity
public class Book {
@Id
private Integer id;
private String name;
@ManyToMany
@JoinTable(name = "BOOK_AUTHORS",
joinColumns = @JoinColumn(name = "BOOK_ID"),
inverseJoinColumns = @JoinColumn(name = "AUTHOR_ID"))
private List<Author> authors = new ArrayList<>();
...
}
@Entity
public class Author {
@Id
@GeneratedValue
private Integer id;
private String name;
@ManyToMany(mappedBy = "author")
private List<Book> books = new ArrayList<>();
...
}
In this example, we create a new table, BOOK_AUTHORS, with two columns: BOOK_ID and AUTHOR_ID.
Using the joinColumns and inverseJoinColumns attributes tell your JPA framework how to map these classes in a many-to-many relationship.
The @ManyToMany annotation in the Author class references the field in the Book class that manages the relationship; namely the Author's property.
Use of Entity Manager and Spring Data JPA
Entity Manager is a component in JPA specifications which is a front face of the framework. Entity Manager is responsible for storing and retrieving entities.
Let’s look at a sample code below.
@Component
public class BookDao {
@Autowired
EntityManager entityManager;
public void addUser(Book book) {
entityManager.persist(book);
}
public void updateUser(Book book) {
Book dbBook = entityManager.find(Book.class, book.getId());
dbBook.setAutherName(book.getAutherName());
entityManager.persist(dbBook);
}
public Book getBookById(Long id) {
return entityManager.find(Book.class, id);
}
public void deleteBook(Long id) {
Book book = entityManager.find(Book.class, id);
entityManager.remove(book);
}
}
Let’s rewrite the same CRUD example for Book table. There is no need to write the methods addUser(), updateUser(), etc.. because the methods already exist in JpaRepository interface.
@Repository
public interface BookRepository extends JpaRepository<Book, Long> {
Book save(Book book);
Optional<Book> findById(Long id);
void deleteById(Long id);
}
You don’t have to provide any implementation because Spring provides implementation at runtime.
The methods declared in repository interfaces are called query methods.
Based on the name, parameters, and return types of the methods, Spring knows what you want to do, and prepares actual SQL statements under the hood.
I will show you a full project example in the next article.
Top comments (0)