Anatomy | Jokes | Intro | UI | API | JPA | POJO | Hacks |
Java Persistent API (JPA)
Define the JPA layer. The JPA enables frontend to query backend and returns a list.
Java Persistence API (JPA)
JPA (Java Persistence API) is a specification for accessing, persisting, and managing data between Java objects and a relational database.
- Persistence: Refers to the capability of an object to be stored in a database and retrieved later.
- API: Provides methods to perform operations such as storing, retrieving, updating, and deleting objects from the database.
JPA simplifies database programming by allowing developers to work with Java objects rather than SQL statements. It abstracts the database interactions and provides a standardized way to manage relational data in Java applications.
JokesJpaRepository Example
The JokesJpaRepository
interface extends the JpaRepository
. This allows the developer to access JPA predefined methods as well as enable the developer to create custom interfaces on persistent storage.
JPA extracts many layers of complexity (hibernate, ORM) from the developer and provides built-in and extensible ways to interact with the database through objects.
- Built-in Methods: Provided by
JpaRepository
to cover common CRUD operations and more. - Derived Queries: Simplify the process of writing database queries by using method naming conventions.
- JPQL Queries: Provide more flexibility than derived queries and are based on entities and attributes.
- Native Queries: Allow the execution of raw SQL queries, providing more control and flexibility.
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
/**
* JPA is an object-relational mapping (ORM) to persistent data.
* Originally, it was used for relational databases (SQL).
* Now, JPA implementations have been extended for NoSQL.
*/
public interface JokesJpaRepository extends JpaRepository<Jokes, Long> {
// JPA has many built-in methods.
// The below methods have been prototyped to extend built-ins
// Save method for a Jokes object.
// Used for Create and Update operations in CRUD.
void save(Jokes joke);
// Accessors, Read operations in CRUD.
// Returns a List of Jokes in ascending order.
List<Jokes> findAllByOrderByJokeAsc();
// Checks if a joke exists, ignoring case.
List<Jokes> findByJokeIgnoreCase(String joke);
}
JPA Repository Interface
Observe the generic data type in the JpaRepository
definition: public interface JokesJpaRepository extends JpaRepository<Jokes, Long>
.
Jokes
, the first entity, is the name of the POJO.Long
is the data type of the ID found in the POJO’s definition.
Built-in Methods in JpaRepository
The JpaRepository interface provides several built-in methods that cover common CRUD operations and more. Here are some of the most commonly used built-in methods:
Save and Update
Jokes joke = new Jokes();
joke.setJoke("Why did the chicken cross the road?");
// Saves a given entity. Use this method for both creating and updating records.
jokesJpaRepository.save(joke);
Find by ID
// Retrieves an entity by its ID.
Optional<Jokes> joke = jokesJpaRepository.findById(1L);
Retrieve all
List<Jokes> allJokes = jokesJpaRepository.findAll();
JPA Methods Return a List
List
is a super class toArrayList
. In this JPA code, you can see that aList
ofJokes
is the result from these JPA derived query accessor methods. JPA is extracting data from persistent storage.
- Review List and ArrayList from GeeksForGeeks to understand their relationship.
Delete by ID
jokesJpaRepository.deleteById(1L);
Count
long count = jokesJpaRepository.count();
Exists
boolean exists = jokesJpaRepository.existsById(1L);
Derived Queries
Derived queries are simple methods such as findBy
, readBy
, getBy
, etc. Spring Data translates these derived queries into JPQL (Java Persistence Query Language) queries, which are then translated into SQL, making things easier for you.
findBy<Attribute>
finds the column in the table that is associated with the Attribute
.
findByJoke
will look for thejoke
attribute in the table.private String joke
is the definition of the attribute in the POJO.
Note that SQL tables and Java naming conventions are mapped for compatibility with SQL. For example, chatMessage
in Java class will become chat_message
in the SQL table.
JPQL Query
JPQL (Java Persistence Query Language) provides a query language that looks similar to SQL. One important thing to note is that JPQL is based on entities, so JPQL queries are based on classes and attributes. JPQL queries are not based on the database tables, which makes it different from SQL. JPA implementations like Hibernate translate the JPQL query into SQL to work with the database.
Entity
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String firstName;
private String lastName;
private String email;
// Getters and setters
}
JPQL Sample
@Query("SELECT u FROM User u WHERE u.lastName = ?1")
List<User> findByLastNameQuery(String lastName);
JPQL Sample description
Use the @Query
annotation, and then define the query in JPQL.
- This is a SELECT statement from the User entity.
- The u works like an alias in SQL, representing the User entity.
- The ?1 is a parameter placeholder for the lastName parameter from the method
Here is an interace with two paramters.
@Query("SELECT u FROM User u WHERE u.lastName = ?1 AND u.firstName = ?2")
List<User> findByName(String lastName, String firstName);
Since this is based on the entity, the query follows the camelCase of POJO definitions
Native Queries
While JPQL provides more flexibility than derived queries, it doesn’t have all of the features of SQL. Native queries allow the programmer to execute SQL queries directly.
@Query(
value = "SELECT * FROM user WHERE last_name = ?1 AND first_name = ?2",
nativeQuery = true
)
List<User> findByNameNative(String lastName, String firstName);
Native Query Description
- Annotation: Use the @Query annotation with the nativeQuery attribute set to true to define a native SQL query.
- SQL Query: The query is written in SQL and follows the snake_case conventions of SQL table and column names.
- Parameters: The ?1 and ?2 placeholders correspond to the lastName and firstName parameters from the method.
This query retrieves a list of User entities where the last_name and first_name columns match the provided parameters.