JPA Persistence
Java Persistence API standard
📊 What is JPA?
Java Persistence API (JPA) is a specification for managing relational data in Java applications. It provides a standard approach for ORM, allowing developers to work with databases using object-oriented programming concepts.
// JPA Repository interface
public interface UserRepository extends JpaRepository<User, Long> {
List<User> findByLastName(String lastName);
User findByEmail(String email);
}
JPA Core Features
Entity Manager
Manages entity lifecycle and persistence
@PersistenceContext
private EntityManager em;
JPQL
Java Persistence Query Language
@Query("SELECT u FROM User u WHERE u.age > ?1")
List<User> findUsersOlderThan(int age);
Repositories
Data access layer abstraction
interface UserRepo extends
JpaRepository<User, Long> {}
Transactions
Automatic transaction management
@Transactional
public void saveUser(User user) {}
🔹 JPA Entity Example
Create a JPA entity with standard annotations:
@Entity
@Table(name = "customers")
public class Customer {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "first_name", nullable = false)
private String firstName;
@Column(name = "last_name", nullable = false)
private String lastName;
@Column(name = "email", unique = true)
private String email;
@Column(name = "phone")
private String phone;
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "created_at")
private Date createdAt;
@PrePersist
protected void onCreate() {
createdAt = new Date();
}
// Constructors
public Customer() {}
public Customer(String firstName, String lastName, String email) {
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
}
// Getters and setters...
}
JPA Features Used:
@Entity - Marks as JPA entity
@PrePersist - Lifecycle callback
@Temporal - Date/time handling
🔹 Spring Data JPA Repository
Create repositories with minimal code:
// Basic repository interface
public interface CustomerRepository extends JpaRepository<Customer, Long> {
// Query methods by naming convention
List<Customer> findByFirstName(String firstName);
List<Customer> findByLastNameContaining(String lastName);
Customer findByEmail(String email);
List<Customer> findByCreatedAtAfter(Date date);
// Custom JPQL queries
@Query("SELECT c FROM Customer c WHERE c.firstName = ?1 AND c.lastName = ?2")
List<Customer> findByFullName(String firstName, String lastName);
@Query("SELECT c FROM Customer c WHERE c.email LIKE %:domain%")
List<Customer> findByEmailDomain(@Param("domain") String domain);
// Native SQL queries
@Query(value = "SELECT * FROM customers WHERE phone IS NOT NULL",
nativeQuery = true)
List<Customer> findCustomersWithPhone();
// Modifying queries
@Modifying
@Query("UPDATE Customer c SET c.email = :email WHERE c.id = :id")
int updateCustomerEmail(@Param("id") Long id, @Param("email") String email);
}
🔹 Using JPA Repository
Service layer using JPA repository:
@Service
@Transactional
public class CustomerService {
@Autowired
private CustomerRepository customerRepository;
// Create
public Customer saveCustomer(Customer customer) {
return customerRepository.save(customer);
}
// Read
public Optional<Customer> findCustomerById(Long id) {
return customerRepository.findById(id);
}
public List<Customer> findAllCustomers() {
return customerRepository.findAll();
}
// Update
public Customer updateCustomer(Customer customer) {
return customerRepository.save(customer);
}
// Delete
public void deleteCustomer(Long id) {
customerRepository.deleteById(id);
}
// Custom queries
public List<Customer> findCustomersByName(String firstName) {
return customerRepository.findByFirstName(firstName);
}
public Customer findCustomerByEmail(String email) {
return customerRepository.findByEmail(email);
}
}
Benefits:
No SQL code needed
Automatic transaction management
Type-safe queries
🔹 JPA Configuration
Configure JPA in Spring Boot:
# application.properties
spring.datasource.url=jdbc:mysql://localhost:3306/mydb
spring.datasource.username=root
spring.datasource.password=password
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# JPA/Hibernate properties
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.database-platform=org.hibernate.dialect.MySQL8Dialect
# Connection pool
spring.datasource.hikari.maximum-pool-size=20
🔸 Java Configuration
@Configuration
@EnableJpaRepositories(basePackages = "com.example.repository")
public class JpaConfig {
@Bean
@Primary
public DataSource dataSource() {
HikariDataSource dataSource = new HikariDataSource();
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/mydb");
dataSource.setUsername("root");
dataSource.setPassword("password");
return dataSource;
}
}