Spring Data JPA: Mapping Objects and Databases

Spring Data JPA

  • JPA (Jakarta Persistence API) is an official Java persistence specification, not a concrete implementation framework. Spring Data JPA is an implementation that builds on top of JPA, with Hibernate as the underlying engine.
  • It eliminates the need to repeatedly write CRUD code; simple operations require no SQL statements. Furthermore, it provides a unified interface across different databases, reducing database migration costs.
  • During development, you only need to extend the corresponding interface to get all the relevant functionality. The hierarchy is: Repository<T, ID> (marker interface, cannot be extended) → CrudRepository (basic CRUD) → PagingAndSortingRepository (+ pagination and sorting) → JpaRepository (+ JPA-specific features, the mainstream choice). On the repository layer, simply write an interface that extends JpaRepository to use the pre-defined methods. T represents the entity class, and ID represents the primary key type.
public interface UserRepository extends JpaRepository<User, Long> {
    Optional<User> findByUsername(String username);
}
  • The core implementation uses dynamic proxies: a proxy class is created that binds the corresponding method to its default SQL statement.
  • You can also define custom SQL, but it must be written in JPQL (Java Persistance Query Language) targeting entity objects, not native SQL.
@Query("select u from User u where u.username = ?1 and u.nickname like ?2")
Optional<User> findByUsernameAndNicknameLike(String username, String nicknamePattern);

Mapping Between Objects and Data base Tables

  • A notable JPA feature: when a user registers, a personal user tag may be created. This tag requires the user's ID, but the ID is auto-generated. Therefore, two save() calls are needed: the first save() only sets simple parameters – at this point JPA executes an INSERT operation, and the primary key is automatically generated. Once the UserID exists, you can set the personal organization tag. The second call to save() performs an UPDATE operation, effectively persisting the user twice.
// When setting this object, we don't need to manually get the ID;
// we simply pass the entire User object.
privateTag.setCreatedBy(owner);

// @ManyToOne declares a [many-to-one] relationship:
// one user can create many organization tags,
// but each organization tag belongs to exactly one user.
@ManyToOne
// @JoinColumn specifies the foreign key field name in the database table
// which is 'created_by'. This foreign key references the User entity
// and must store the primary key (ID). So although we pass a User object,
// only the UserId is stored in the database.
@JoinColumn(name = "created_by", nullable = false)
private User createdBy; // creator ID

Tags: jpa Spring Data JPA hibernate java ORM

Posted on Sun, 20 Sep 2026 16:55:24 +0000 by FVxSF