Java is an object-oriented language, i.e. A Java program deals with the creation of objects, their interaction, etc. We can use Java Database Connectivity (JDBC) API for accessing the database. This approach possesses some challenges.
- We mix database queries with the Java code, which would make it hard to debug.
- We need to convert the SQL result to Java objects explicitly.
- The database transactions need to be handled.
Object Relational Mapping (ORM) technologies help us to overcome these issues, they provide a way to map the Java objects to database tables and vice versa. Java Persistence API (JPA) is a Java specification for ORM. JPA is available for Java SE and Java EE versions. There are many implementations for JPA, namely Hibernate, Toplink, EclipseLink, etc. A JPA implementation is known as a persistence provider. We need to map the Java objects to the database tables using some metadata configurations. These are defined either by using annotations in Java or using the XML files. JPA permits us to work directly with Java objects for database interactions. It also provides SQL-like query language for querying the database. In this tutorial, we will see some terminologies used in JPA.
An entity is a POJO class corresponding to a table in the database. We define an entity for each table. The properties of the entity correspond to the columns in the table, each instance of an entity corresponds to a row in the table. An entity should be annotated with javax.persistence.Entity annotation. An entity class should have a primary key which is defined by using any property annotated with javax.persistence.Id annotation. This property value will uniquely identify the entity. By default, the table name corresponds to the entity name, if we need to map the entity to a different table then the entity needs to be annotated with @Table annotation.
JPA allows entity relationships, which means an entity can contain one or more instances of another entity. Following are the relationship types.
- One-to-one: An entity contains a reference of another entity as its property. So, each entity instance is related to a single instance of another entity. The entity reference needs to be annotated with javax.persistence. OneToOne annotation.
- One-to-many: An entity contains a collection of references of another entity as its property. So, each entity instance is related to multiple instances of another entity. The entity reference needs to be annotated with javax.persistence.OneToMany annotation.
- Many-to-one: Multiple instances of an entity can be related to a single instance of the other entity. The entity reference needs to be annotated with javax.persistence.ManyToOne annotation.
- Many-to-many: The entity instances can be related to multiple instances of each other. The entity reference needs to be annotated with javax.persistence.ManyToMany annotation.
Any Java application development that uses JPA needs to get the details of the databases it should connect to, these are defined in the configuration XML file. The XML also has an additional configuration for the ORM to work. These settings will initialize the persistence context upon application start-up. The persistence context contains a set of all managed entities associates with a database. These entities can be persisted, updated, or can be queried. Entities are managed by the entity manager, which can be accessed using javax.persistence.EntityManager interface. This contains methods to persist, update and delete entity instances.
Each entity in a JPA-enabled application has a life cycle. They could be in a new, managed, detached, or removed state. When a new entity instance is created, it will be in the new state. When an entity is associated with a persistence context, it is managed state. Dethatched entities are not associated with a persistence context. The removed state entities are still associated with persistence context but are marked for removal from database.
Java Persistence query language (JPQL)
Is it a simple language to query entities and their relationships? JPQL allows us to write queries that work across multiple types of databases. JPQL supports the Data Manipulation and data read operations of the database. It is developed based on SQL syntax. While SQL works on the tables and columns, the JPQL deals with entities and their properties. JPQL allows named queries as well, which can be reused in the program. It follows javax.persistence.query package to design a query.
Uses Java API to query entities and their relationships. Criteria query is programmer-friendly, as they don't have any database-specific jargons. The Criteria API provides many classes to achieve the similar behavior of JPQL. It follows javax.persistence.criteria package to design a query.
The persistence providers use caching to improve query performance. Whenever an object is persisted, it is saved into the in-memory cache first and flushed to the database later. Any read operation also from cache first and if not available get from the database. We can also configure third-party caching tools with the persistence frameworks.
In this tutorial, we have seen a high-level overview of Java Persistence API. This API solves the problems that we had with JDBC by abstracting the database interactions, the user can deal with the Java objects themselves while all database conversions are abstracted. We also need not worry about the database-specific syntax as the JPA implementations provide multiple database support. The JPA thereby helps us to minimize the effort required for the development and maintenance of database access modules in our application.