Skip to main content

Command Palette

Search for a command to run...

Bài 5: Query Methods và JPQL/HQL trong Spring Data JPA

Published
6 min read

1. Định nghĩa các phương thức truy vấn dựa trên tên phương thức

Spring Data JPA cung cấp khả năng tạo các phương thức truy vấn tự động bằng cách định nghĩa tên phương thức theo các quy tắc đặt tên nhất định.

Quy tắc đặt tên phương thức Spring Data JPA sử dụng một bộ quy tắc đặt tên phương thức để tự động tạo các truy vấn. Các quy tắc này bao gồm:

  • findBy: Truy vấn dựa trên các thuộc tính của entity.

  • countBy: Đếm số lượng entity thỏa mãn điều kiện.

  • deleteBy: Xóa các entity thỏa mãn điều kiện.

  • existsBy: Kiểm tra sự tồn tại của các entity thỏa mãn điều kiện.

Ví dụ:

package com.example.demo.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import com.example.demo.entity.User;
import java.util.List;

public interface UserRepository extends JpaRepository<User, Long> {
    List<User> findByUsername(String username);
    List<User> findByUsernameAndPassword(String username, String password);
    List<User> findByUsernameOrPassword(String username, String password);
    Long countByUsername(String username);
    void deleteByUsername(String username);
    boolean existsByUsername(String username);
}

Giải thích các phương thức:

  • findByUsername: Truy vấn các User có thuộc tính username là giá trị được cung cấp.

  • findByUsernameAndPassword: Truy vấn các User có thuộc tính usernamepassword là các giá trị được cung cấp.

  • findByUsernameOrPassword: Truy vấn các User có thuộc tính username hoặc password là các giá trị được cung cấp.

  • countByUsername: Đếm số lượng User có thuộc tính username là giá trị được cung cấp.

  • deleteByUsername: Xóa các User có thuộc tính username là giá trị được cung cấp.

  • existsByUsername: Kiểm tra sự tồn tại của các User có thuộc tính username là giá trị được cung cấp.

2. Sử dụng JPQL/HQL trong Spring Data JPA

JPQL (Java Persistence Query Language) và HQL (Hibernate Query Language) là các ngôn ngữ truy vấn hướng đối tượng, cho phép chúng ta viết các truy vấn trên các entity thay vì các bảng cơ sở dữ liệu.

Sử dụng annotation @Query để viết truy vấn JPQL/HQL Annotation @Query trong Spring Data JPA cho phép chúng ta viết các truy vấn JPQL/HQL tùy chỉnh.

Ví dụ:

package com.example.demo.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import com.example.demo.entity.User;
import java.util.List;

public interface UserRepository extends JpaRepository<User, Long> {
    @Query("SELECT u FROM User u WHERE u.username = :username")
    List<User> findByUsernameCustom(@Param("username") String username);

    @Query("SELECT u FROM User u WHERE u.username = :username AND u.password = :password")
    List<User> findByUsernameAndPasswordCustom(@Param("username") String username, @Param("password") String password);

    @Query("SELECT COUNT(u) FROM User u WHERE u.username = :username")
    Long countByUsernameCustom(@Param("username") String username);
}

Giải thích các truy vấn:

  • findByUsernameCustom: Truy vấn các User có thuộc tính username là giá trị được cung cấp.

  • findByUsernameAndPasswordCustom: Truy vấn các User có thuộc tính usernamepassword là các giá trị được cung cấp.

  • countByUsernameCustom: Đếm số lượng User có thuộc tính username là giá trị được cung cấp.

3. Native Queries

Native Queries là các truy vấn SQL thuần, cho phép chúng ta viết các truy vấn SQL phức tạp mà JPQL/HQL không thể hỗ trợ.

Sử dụng annotation @Query với thuộc tính nativeQuery Annotation @Query với thuộc tính nativeQuery cho phép chúng ta viết các truy vấn SQL thuần.

Ví dụ:

package com.example.demo.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import com.example.demo.entity.User;
import java.util.List;

public interface UserRepository extends JpaRepository<User, Long> {
    @Query(value = "SELECT * FROM users WHERE username = :username", nativeQuery = true)
    List<User> findByUsernameNative(@Param("username") String username);

    @Query(value = "SELECT * FROM users WHERE username = :username AND password = :password", nativeQuery = true)
    List<User> findByUsernameAndPasswordNative(@Param("username") String username, @Param("password") String password);

    @Query(value = "SELECT COUNT(*) FROM users WHERE username = :username", nativeQuery = true)
    Long countByUsernameNative(@Param("username") String username);
}

Giải thích các truy vấn:

  • findByUsernameNative: Truy vấn các User có thuộc tính username là giá trị được cung cấp sử dụng SQL thuần.

  • findByUsernameAndPasswordNative: Truy vấn các User có thuộc tính usernamepassword là các giá trị được cung cấp sử dụng SQL thuần.

  • countByUsernameNative: Đếm số lượng User có thuộc tính username là giá trị được cung cấp sử dụng SQL thuần.

4. Sử dụng EntityManager để thực thi các truy vấn tùy chỉnh

EntityManager là gì? EntityManager là một API cung cấp bởi JPA để quản lý các entity và thực hiện các truy vấn tùy chỉnh. Nó cho phép chúng ta thực hiện các truy vấn phức tạp mà Spring Data JPA không thể hỗ trợ.

Ví dụ sử dụng EntityManager

package com.example.demo.repository;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import org.springframework.stereotype.Repository;
import com.example.demo.entity.User;
import java.util.List;

@Repository
public class UserRepositoryCustomImpl implements UserRepositoryCustom {

    @PersistenceContext
    private EntityManager entityManager;

    @Override
    public List<User> findUsersWithCustomQuery(String username) {
        TypedQuery<User> query = entityManager.createQuery("SELECT u FROM User u WHERE u.username = :username", User.class);
        query.setParameter("username", username);
        return query.getResultList();
    }
}

Interface UserRepositoryCustom

package com.example.demo.repository;

import com.example.demo.entity.User;
import java.util.List;

public interface UserRepositoryCustom {
    List<User> findUsersWithCustomQuery(String username);
}

Kết hợp UserRepositoryCustom với UserRepository

package com.example.demo.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import com.example.demo.entity.User;

public interface UserRepository extends JpaRepository<User, Long>, UserRepositoryCustom {
    // Các phương thức truy vấn tùy chỉnh sẽ được định nghĩa ở đây
}

5. Paging và Sorting

Spring Data JPA hỗ trợ phân trang và sắp xếp một cách dễ dàng thông qua các interface PageableSort.

Sử dụng PageableSort

package com.example.demo.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import com.example.demo.entity.User;

public interface UserRepository extends JpaRepository<User, Long> {
    Page<User> findByUsername(String username, Pageable pageable);
}

Ví dụ cụ thể về sử dụng phân trang và sắp xếp trong service

package com.example.demo.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import com.example.demo.repository.UserRepository;
import com.example.demo.entity.User;

@Service
public class UserService {

    @Autowired
    private UserRepository userRepository;

    public Page<User> getUsersByUsername(String username, int page, int size) {
        Pageable pageable = PageRequest.of(page, size, Sort.by("username").ascending());
        return userRepository.findByUsername(username, pageable);
    }
}

Controller sử dụng phân trang và sắp xếp

package com.example.demo.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.web.bind.annotation.*;
import com.example.demo.entity.User;
import com.example.demo.service.UserService;

@RestController
@RequestMapping("/api/users")
public class UserController {

    @Autowired
    private UserService userService;

    @GetMapping
    public Page<User> getUsersByUsername(@RequestParam String username, @RequestParam int page, @RequestParam int size) {
        return userService.getUsersByUsername(username, page, size);
    }
}

Kết luận

Bài viết này đã giới thiệu chi tiết về cách định nghĩa các

phương thức truy vấn trong Spring Data JPA, sử dụng JPQL/HQL, Native Queries, và EntityManager để thực hiện các truy vấn tùy chỉnh, cũng như cách sử dụng phân trang và sắp xếp. Những kiến thức này sẽ giúp bạn xây dựng các ứng dụng Spring Boot với khả năng truy xuất và quản lý dữ liệu mạnh mẽ, linh hoạt. Các bài viết tiếp theo sẽ tiếp tục đi sâu vào các khía cạnh nâng cao hơn của Spring Data JPA như caching, tối ưu hóa hiệu suất, và xử lý các vấn đề phổ biến.

More from this blog

Untitled Publication

218 posts