jpa tutorial

Complete and Categorized JPA Notes with Detailed Explanation and Code Examples

🧩 1. Overview of JPA

  • JPA (Java Persistence API) is a specification to manage relational data in Java applications.
  • It provides a bridge between the object-oriented domain model and the relational database.
  • Common implementations: Hibernate, EclipseLink, OpenJPA.

🏷️ 2. Entity Annotations

AnnotationPurpose
@EntityMarks a class as a JPA entity
@Table(name = "table_name")Optional table name
@IdPrimary key
@GeneratedValue(strategy = GenerationType.AUTO)Auto generation of primary key
@Column(name = "col_name")Customize column mapping
@TransientField not persisted
@LobFor large binary/text data (e.g., BLOB)
@EmbeddedFor embeddable classes
@JoinColumn(name = "col")Foreign key column for relationships

🔗 3. Entity Relationships

One-to-One

Example: A user has exactly one profile. Both share a one-to-one relationship.

@Entity
public class User {
    @Id
    @GeneratedValue
    private Long id;

    private String username;

    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "profile_id") // foreign key in User table
    private Profile profile;
}

@Entity
public class Profile {
    @Id
    @GeneratedValue
    private Long id;

    private String address;
    private String phone;
}

One-to-Many

Example: A user can place many orders. This is a one-to-many relationship.

@Entity
public class User {
@Id
@GeneratedValue
private Long id;

private String username;

@OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
private List<Order> orders = new ArrayList<>();
}

@Entity
public class Order {
@Id
@GeneratedValue
private Long id;

private String item;

@ManyToOne
@JoinColumn(name = "user_id") // foreign key in Order table
private User user;
}

Many-to-One

Example: Each order is placed by one user — a many-to-one mapping (inverse of one-to-many).

@ManyToOne
@JoinColumn(name = "user_id")
private User user;

Many-to-Many

Example: A user can have multiple roles and a role can belong to multiple users.

@Entity
public class User {
@Id
@GeneratedValue
private Long id;

private String username;

@ManyToMany
@JoinTable(
name = "user_role",
joinColumns = @JoinColumn(name = "user_id"),
inverseJoinColumns = @JoinColumn(name = "role_id"))
private Set<Role> roles = new HashSet<>();
}

@Entity
public class Role {
@Id
@GeneratedValue
private Long id;

private String name;

@ManyToMany(mappedBy = "roles")
private Set<User> users = new HashSet<>();
}

🔍 4. Queries

JPQL

@Query("SELECT u FROM User u WHERE u.status = 1")
List<User> findAllActiveUsers();

Native Query

@Query(value = "SELECT * FROM users WHERE status = 1", nativeQuery = true)
List<User> findAllActiveUsersNative();

Named Query

@Entity
@NamedQuery(name = "User.findByEmail", query = "SELECT u FROM User u WHERE u.email = ?1")
public class User {}

📚 5. Pagination & Sorting

Page<User> findAll(Pageable pageable);
List<User> findAll(Sort sort);
@Query("SELECT u FROM User u ORDER BY id")
Page<User> findAllWithPagination(Pageable pageable);

Example usage:

@Entity
public class User {
@Id
@GeneratedValue
private Long id;

private String name;
private String email;
private int age;
}

//in repository
public interface UserRepository extends JpaRepository<User, Long> {

// Custom with pagination and sorting
Page<User> findByAgeGreaterThan(int age, Pageable pageable);

// Custom sorting using derived query
List<User> findByNameContaining(String keyword, Sort sort);
}

//in service / controller

@Autowired
private UserRepository userRepository;
public Page<User> getUsersPaged(int page, int size) {
Pageable pageable = PageRequest.of(page, size);
return userRepository.findAll(pageable);
}

//pagination with sorting
public Page<User> getSortedUsersPaged(int page, int size, String sortBy, boolean desc) {
Sort sort = desc ? Sort.by(sortBy).descending() : Sort.by(sortBy).ascending();
Pageable pageable = PageRequest.of(page, size, sort);
return userRepository.findAll(pageable);
}

//example controller
@GetMapping("/users")
public Page<User> getUsers(
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "5") int size,
@RequestParam(defaultValue = "name") String sortBy,
@RequestParam(defaultValue = "false") boolean desc) {

Sort sort = desc ? Sort.by(sortBy).descending() : Sort.by(sortBy).ascending();
Pageable pageable = PageRequest.of(page, size, sort);
return userRepository.findAll(pageable);
}

// sample api call
GET /users?page=0&size=5 → First 5 users
GET /users?page=1&size=5&sortBy=age&desc=true → Second page sorted by age in descending order

🧠 6. Common Query Keywords

KeywordExample
AndfindByFirstNameAndLastName
OrfindByAgeOrName
BetweenfindByAgeBetween(20, 30)
LessThanfindByAgeLessThan(18)
LikefindByEmailLike("%gmail.com")
StartingWithfindByNameStartingWith("A")
InfindByIdIn(List<Long> ids)
IsNullfindByEmailIsNull()
True/FalsefindByActiveTrue()

🛠️ 7. Modifying Queries (Update, Delete)

@Modifying
@Query("UPDATE User u SET u.status = :status WHERE u.name = :name")
int updateStatus(@Param("status") Integer status, @Param("name") String name);

🔁 8. Entity Graphs (For Performance Tuning)

@Entity
@NamedEntityGraph(name = "Group.detail", attributeNodes = @NamedAttributeNode("members"))
public class Group {
@ManyToMany
List<Member> members;
}

Repository usage:

@EntityGraph(value = "Group.detail", type = EntityGraph.EntityGraphType.LOAD)
Group findByName(String name);

🚀 9. Cascade Types

CascadeTypeDescription
PERSISTChild saved automatically
MERGEMerge changes to children
REMOVEDelete children too
REFRESHRefresh child state
DETACHDetach child from session
ALLApplies all of the above
@OneToMany(cascade = CascadeType.ALL)
private List<Order> orders;

🗃️ 10. Fetch Types

TypeDescription
LAZYData loaded on-demand (recommended)
EAGERData loaded immediately
@OneToMany(fetch = FetchType.LAZY)
private List<Order> orders;

🔢 11. Indexed and Named Parameters

Indexed

@Query("SELECT u FROM User u WHERE u.status = ?1 AND u.name = ?2")
User findByStatusAndName(Integer status, String name);

Named

@Query("SELECT u FROM User u WHERE u.status = :status AND u.name = :name")
User findByStatusAndNameNamed(@Param("status") Integer status, @Param("name") String name);

🆔 12. Natural IDs and UUIDs

Natural ID (e.g., Email, SSN)

@NaturalId
@Column(unique = true)
private String email;

UUID as Primary Key

@Id
@GeneratedValue(generator = "uuid")
@GenericGenerator(name = "uuid", strategy = "uuid2")
private String id;

📌 13. Additional Best Practices

  • Use @Repository to enable Spring Data exception translation.
  • Prefer DTOs over exposing entities in REST responses.
  • Use @EntityGraph for optimizing performance instead of EAGER fetch.

Check imporatant Java concepts for crack any interview:

Similar Posts