{"id":91205,"date":"2025-11-24T14:43:02","date_gmt":"2025-11-24T07:43:02","guid":{"rendered":"https:\/\/itviec.com\/blog\/?p=91205"},"modified":"2025-11-24T14:43:05","modified_gmt":"2025-11-24T07:43:05","slug":"spring-data-jpa-la-gi","status":"publish","type":"post","link":"https:\/\/itviec.com\/blog\/spring-data-jpa-la-gi\/","title":{"rendered":"Spring Data JPA: H\u01b0\u1edbng d\u1eabn to\u00e0n t\u1eadp t\u1eeb c\u01a1 b\u1ea3n \u0111\u1ebfn n\u00e2ng cao"},"content":{"rendered":"<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_84 counter-hierarchy ez-toc-counter ez-toc-grey ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">N\u1ed9i dung b\u00e0i vi\u1ebft<\/p>\n<span class=\"ez-toc-title-toggle\"><a href=\"#\" class=\"ez-toc-pull-right ez-toc-btn ez-toc-btn-xs ez-toc-btn-default ez-toc-toggle\" aria-label=\"Toggle Table of Content\"><span class=\"ez-toc-js-icon-con\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/span><\/a><\/span><\/div>\n<nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/itviec.com\/blog\/spring-data-jpa-la-gi\/#Spring_Data_JPA_la_gi\" >Spring Data JPA l\u00e0 g\u00ec?<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/itviec.com\/blog\/spring-data-jpa-la-gi\/#Cach_thiet_lap_va_cai_dat_Spring_Data_JPA\" >C\u00e1ch thi\u1ebft l\u1eadp v\u00e0 c\u00e0i \u0111\u1eb7t Spring Data JPA<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/itviec.com\/blog\/spring-data-jpa-la-gi\/#Cac_thanh_phan_chinh_cua_Spring_Data_JPA\" >C\u00e1c th\u00e0nh ph\u1ea7n ch\u00ednh c\u1ee7a Spring Data JPA<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/itviec.com\/blog\/spring-data-jpa-la-gi\/#Huong_dan_khai_thac_cac_phuong_thuc_truy_van_trong_Spring_Data_JPA\" >H\u01b0\u1edbng d\u1eabn khai th\u00e1c c\u00e1c ph\u01b0\u01a1ng th\u1ee9c truy v\u1ea5n trong Spring Data JPA<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/itviec.com\/blog\/spring-data-jpa-la-gi\/#Cac_ky_thuat_nang_cao_voi_Spring_Data_JPA\" >C\u00e1c k\u1ef9 thu\u1eadt n\u00e2ng cao v\u1edbi Spring Data JPA<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/itviec.com\/blog\/spring-data-jpa-la-gi\/#Cac_cach_toi_uu_hieu_nang_khi_lam_viec_voi_Spring_Data_JPA\" >C\u00e1c c\u00e1ch t\u1ed1i \u01b0u hi\u1ec7u n\u0103ng khi l\u00e0m vi\u1ec7c v\u1edbi Spring Data JPA<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/itviec.com\/blog\/spring-data-jpa-la-gi\/#Cac_loi_thuong_gap_voi_Spring_Data_JPA_va_cach_khac_phuc\" >C\u00e1c l\u1ed7i th\u01b0\u1eddng g\u1eb7p v\u1edbi Spring Data JPA v\u00e0 c\u00e1ch kh\u1eafc ph\u1ee5c<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/itviec.com\/blog\/spring-data-jpa-la-gi\/#Cac_cau_hoi_thuong_gap_ve_Spring_Data_JPA\" >C\u00e1c c\u00e2u h\u1ecfi th\u01b0\u1eddng g\u1eb7p v\u1ec1 Spring Data JPA<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-9\" href=\"https:\/\/itviec.com\/blog\/spring-data-jpa-la-gi\/#Tong_ket\" >T\u1ed5ng k\u1ebft<\/a><\/li><\/ul><\/nav><\/div>\n\n<p><strong><em>S\u1ef1 ra \u0111\u1eddi c\u1ee7a Spring Data JPA \u0111\u00e3 th\u1ef1c s\u1ef1 thay \u0111\u1ed5i c\u00e1ch l\u1eadp tr\u00ecnh vi\u00ean ti\u1ebfp c\u1eadn t\u1ea7ng d\u1eef li\u1ec7u. Spring Data JPA l\u00e0 m\u1ed9t module c\u1ee7a Spring Data framework, \u0111\u01b0\u1ee3c x\u00e2y d\u1ef1ng \u0111\u1ec3 \u0111\u01a1n gi\u1ea3n h\u00f3a t\u1ea7ng truy c\u1eadp d\u1eef li\u1ec7u v\u00e0 gi\u1ea3m thi\u1ec3u m\u00e3 boilerplate, gi\u00fap t\u0103ng n\u0103ng su\u1ea5t v\u00e0 gi\u1ea3m thi\u1ec3u l\u1ed7i.<\/em><\/strong><\/p>\n\n\n\n<p>\u0110\u1ecdc b\u00e0i vi\u1ebft n\u00e0y \u0111\u1ec3 \u0111\u01b0\u1ee3c gi\u1ea3i \u0111\u00e1p v\u1ec1:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Vai tr\u00f2 c\u1ee7a Spring Data JPA l\u00e0 g\u00ec? C\u00f3 g\u00ec kh\u00e1c JPA, Hibernate<\/li>\n\n\n\n<li>C\u00e1ch thi\u1ebft l\u1eadp v\u00e0 c\u00e0i \u0111\u1eb7t Spring Data JPA<\/li>\n\n\n\n<li>C\u00e1c th\u00e0nh ph\u1ea7n ch\u00ednh c\u1ee7a Spring Data JPA<\/li>\n\n\n\n<li>C\u00e1ch khai th\u00e1c c\u00e1c ph\u01b0\u01a1ng th\u1ee9c truy v\u1ea5n trong Spring Data JPA<\/li>\n\n\n\n<li>C\u00e1c k\u1ef9 thu\u1eadt n\u00e2ng cao v\u1edbi Spring Data JPA<\/li>\n\n\n\n<li>C\u00e1c c\u00e1ch t\u1ed1i \u01b0u hi\u1ec7u n\u0103ng khi l\u00e0m vi\u1ec7c v\u1edbi Spring Data JPA<\/li>\n\n\n\n<li>C\u00e1ch kh\u1eafc ph\u1ee5c c\u00e1c l\u1ed7i th\u01b0\u1eddng g\u1eb7p v\u1edbi Spring Data JPA<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-spring-data-jpa-la-gi\"><span class=\"ez-toc-section\" id=\"Spring_Data_JPA_la_gi\"><\/span><strong>Spring Data JPA l\u00e0 g\u00ec?<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p><strong>Spring Data JPA<\/strong> l\u00e0 m\u1ed9t module thu\u1ed9c d\u1ef1 \u00e1n Spring Data, \u0111\u01b0\u1ee3c thi\u1ebft k\u1ebf \u0111\u1ec3 \u0111\u01a1n gi\u1ea3n h\u00f3a vi\u1ec7c truy c\u1eadp d\u1eef li\u1ec7u trong c\u00e1c \u1ee9ng d\u1ee5ng Spring s\u1eed d\u1ee5ng JPA (Java Persistence API).<\/p>\n\n\n\n<p>V\u1ecb tr\u00ed c\u1ee7a Spring Data JPA l\u00e0 n\u1eb1m gi\u1eefa t\u1ea7ng Business Logic c\u1ee7a \u1ee9ng d\u1ee5ng v\u00e0 t\u1ea7ng Persistence (c\u1ee5 th\u1ec3 l\u00e0 Implementation c\u1ee7a JPA). N\u00f3 cung c\u1ea5p m\u1ed9t m\u00f4 h\u00ecnh l\u1eadp tr\u00ecnh d\u1ef1a tr\u00ean Repository (kho ch\u1ee9a), cho ph\u00e9p l\u1eadp tr\u00ecnh vi\u00ean \u0111\u1ecbnh ngh\u0129a c\u00e1c interface truy v\u1ea5n d\u1eef li\u1ec7u m\u00e0 kh\u00f4ng c\u1ea7n vi\u1ebft m\u00e3 tri\u1ec3n khai. Spring Data JPA s\u1ebd t\u1ef1 \u0111\u1ed9ng t\u1ea1o ra c\u00e1c c\u00e0i \u0111\u1eb7t c\u1ea7n thi\u1ebft l\u00fac runtime.<\/p>\n\n\n\n<p>V\u1ec1 c\u01a1 b\u1ea3n, n\u00f3 kh\u00f4ng ph\u1ea3i l\u00e0 m\u1ed9t tr\u00ecnh tri\u1ec3n khai JPA (nh\u01b0 Hibernate) m\u00e0 l\u00e0 m\u1ed9t <strong>l\u1edbp tr\u1eebu t\u01b0\u1ee3ng (abstraction layer)<\/strong> n\u1eb1m ph\u00eda tr\u00ean JPA Provider. M\u1ee5c ti\u00eau ch\u00ednh c\u1ee7a Spring Data JPA l\u00e0 gi\u1ea3m thi\u1ec3u \u0111\u00e1ng k\u1ec3 m\u00e3 boilerplate (m\u00e3 l\u1eb7p \u0111i l\u1eb7p l\u1ea1i) c\u1ea7n thi\u1ebft \u0111\u1ec3 th\u1ef1c hi\u1ec7n c\u00e1c thao t\u00e1c truy v\u1ea5n d\u1eef li\u1ec7u, \u0111\u1eb7c bi\u1ec7t l\u00e0 c\u00e1c thao t\u00e1c CRUD (Create, Read, Update, Delete).<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-phan-bi\u1ec7t-vai-tro-c\u1ee7a-jpa-hibernate-va-spring-data-jpa\"><strong>Ph\u00e2n bi\u1ec7t vai tr\u00f2 c\u1ee7a JPA, Hibernate v\u00e0 Spring Data JPA<\/strong><\/h3>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"212\" height=\"238\" src=\"https:\/\/itviec.com\/blog\/wp-content\/uploads\/2025\/09\/image-11.png\" alt=\"\" class=\"wp-image-91206\" srcset=\"https:\/\/itviec.com\/blog\/wp-content\/uploads\/2025\/09\/image-11.png 212w, https:\/\/itviec.com\/blog\/wp-content\/uploads\/2025\/09\/image-11-178x200.png 178w\" sizes=\"auto, (max-width: 212px) 100vw, 212px\" \/><\/figure>\n\n\n\n<p class=\"has-text-align-center\"><em>V\u1ecb tr\u00ed c\u1ee7a 3 th\u00e0nh ph\u1ea7n n\u00e0y trong c\u1ea5u tr\u00fac c\u1ee7a 1 \u1ee9ng d\u1ee5ng<\/em><\/p>\n\n\n\n<p><strong>1. <\/strong><a href=\"https:\/\/www.oracle.com\/java\/technologies\/persistence-jsp.html\" target=\"_blank\" rel=\"noreferrer noopener\"><strong>JPA (Java Persistence API)&nbsp;<\/strong><\/a><\/p>\n\n\n\n<p>JPA l\u00e0 m\u1ed9t <strong>b\u1ed9 ti\u00eau chu\u1ea9n k\u1ef9 thu\u1eadt (specification)<\/strong> c\u1ee7a Java, \u0111\u1ecbnh ngh\u0129a m\u1ed9t t\u1eadp h\u1ee3p c\u00e1c API, annotation v\u00e0 quy t\u1eafc \u0111\u1ec3 qu\u1ea3n l\u00fd d\u1eef li\u1ec7u quan h\u1ec7 trong c\u00e1c \u1ee9ng d\u1ee5ng Java. N\u00f3 ch\u1ec9 l\u00e0 m\u1ed9t b\u1ea3n thi\u1ebft k\u1ebf, \u0111\u01b0a ra c\u00e1c kh\u00e1i ni\u1ec7m nh\u01b0 EntityManager, Entity, @Id, @Table, v\u00e0 ng\u00f4n ng\u1eef truy v\u1ea5n JPQL (Java Persistence Query Language).<\/p>\n\n\n\n<p><strong>2. <\/strong><a href=\"https:\/\/docs.spring.io\/spring-framework\/reference\/data-access\/orm\/hibernate.html\" target=\"_blank\" rel=\"noreferrer noopener\"><strong>Hibernate<\/strong><\/a><\/p>\n\n\n\n<p>Hibernate l\u00e0 m\u1ed9t <strong>tr\u00ecnh tri\u1ec3n khai (implementation)<\/strong> c\u1ee5 th\u1ec3 v\u00e0 ph\u1ed5 bi\u1ebfn nh\u1ea5t c\u1ee7a JPA. N\u00f3 hi\u1ec7n th\u1ef1c h\u00f3a c\u00e1c ti\u00eau chu\u1ea9n m\u00e0 JPA \u0111\u00e3 \u0111\u1ec1 ra. Hibernate cung c\u1ea5p EntityManager th\u1ef1c t\u1ebf, x\u1eed l\u00fd vi\u1ec7c \u00e1nh x\u1ea1 \u0111\u1ed1i t\u01b0\u1ee3ng Java (Object) sang c\u00e1c b\u1ea3n ghi trong c\u01a1 s\u1edf d\u1eef li\u1ec7u (Relational) &#8211; g\u1ecdi l\u00e0 ORM (Object-Relational Mapping). Ngo\u00e0i JPA, Hibernate c\u00f2n cung c\u1ea5p nhi\u1ec1u t\u00ednh n\u0103ng m\u1edf r\u1ed9ng c\u1ee7a ri\u00eang n\u00f3.<\/p>\n\n\n\n<p><strong>3. Spring Data JPA<\/strong><\/p>\n\n\n\n<p>Spring Data JPA l\u00e0 m\u1ed9t <strong>l\u1edbp tr\u1eebu t\u01b0\u1ee3ng<\/strong> n\u1eb1m tr\u00ean c\u00f9ng, gi\u00fap vi\u1ec7c t\u01b0\u01a1ng t\u00e1c v\u1edbi d\u1eef li\u1ec7u tr\u1edf n\u00ean d\u1ec5 d\u00e0ng h\u01a1n r\u1ea5t nhi\u1ec1u. Thay v\u00ec ph\u1ea3i t\u1ef1 tay vi\u1ebft c\u00e1c c\u00e2u l\u1ec7nh truy v\u1ea5n ph\u1ee9c t\u1ea1p b\u1eb1ng JPQL ho\u1eb7c Criteria API, b\u1ea1n ch\u1ec9 c\u1ea7n \u0111\u1ecbnh ngh\u0129a c\u00e1c interface Repository. Spring Data JPA s\u1ebd t\u1ef1 \u0111\u1ed9ng sinh ra c\u00e1c ph\u01b0\u01a1ng th\u1ee9c CRUD c\u01a1 b\u1ea3n (save(), findById(), findAll(), delete()) v\u00e0 c\u1ea3 c\u00e1c truy v\u1ea5n ph\u1ee9c t\u1ea1p h\u01a1n d\u1ef1a tr\u00ean t\u00ean ph\u01b0\u01a1ng th\u1ee9c (Query Methods).<\/p>\n\n\n\n<p>T\u00f3m l\u1ea1i, <strong>Spring Data JPA<\/strong> \u0111\u01a1n gi\u1ea3n h\u00f3a vi\u1ec7c s\u1eed d\u1ee5ng <strong>t\u1eadp h\u1ee3p c\u00e1c quy t\u1eafc JPA (<\/strong><a href=\"https:\/\/www.oracle.com\/java\/technologies\/persistence-jsp.html\" target=\"_blank\" rel=\"noreferrer noopener\"><strong>Java Persistence API<\/strong><\/a><strong>) <\/strong>b\u1eb1ng c\u00e1ch cung c\u1ea5p m\u1ed9t l\u1edbp tr\u1eebu t\u01b0\u1ee3ng c\u1ea5p cao h\u01a1n, trong khi <strong>Hibernate<\/strong> l\u00e0 m\u1ed9t trong nh\u1eefng c\u00f4ng c\u1ee5 hi\u1ec7n th\u1ef1c h\u00f3a c\u00e1c quy t\u1eafc c\u1ee7a JPA \u0111\u00f3.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-cach-thi\u1ebft-l\u1eadp-va-cai-d\u1eb7t-spring-data-jpa\"><span class=\"ez-toc-section\" id=\"Cach_thiet_lap_va_cai_dat_Spring_Data_JPA\"><\/span><strong>C\u00e1ch thi\u1ebft l\u1eadp v\u00e0 c\u00e0i \u0111\u1eb7t Spring Data JPA<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>\u0110\u1ec3 b\u1eaft \u0111\u1ea7u v\u1edbi Spring Data JPA, b\u1ea1n c\u1ea7n th\u00eam c\u00e1c dependency c\u1ea7n thi\u1ebft v\u00e0o project v\u00e0 c\u1ea5u h\u00ecnh th\u00f4ng tin k\u1ebft n\u1ed1i \u0111\u1ebfn c\u01a1 s\u1edf d\u1eef li\u1ec7u.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-cai-d\u1eb7t-dependencies\"><strong>C\u00e0i \u0111\u1eb7t Dependencies<\/strong><\/h3>\n\n\n\n<p>Ph\u1ea7n n\u00e0y h\u01b0\u1edbng d\u1eabn c\u00e1ch th\u00eam c\u00e1c th\u01b0 vi\u1ec7n c\u1ea7n thi\u1ebft v\u00e0o d\u1ef1 \u00e1n c\u1ee7a b\u1ea1n b\u1eb1ng Maven ho\u1eb7c Gradle.<\/p>\n\n\n\n<p>Tr\u01b0\u1edbc khi b\u1eaft \u0111\u1ea7u, h\u00e3y \u0111\u1ea3m b\u1ea3o b\u1ea1n \u0111\u00e3 c\u00f3:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>JDK<\/strong>: Java Development Kit, phi\u00ean b\u1ea3n 8 tr\u1edf l\u00ean (khuy\u1ebfn ngh\u1ecb 11 ho\u1eb7c 17).<\/li>\n\n\n\n<li><strong>Maven\/Gradle<\/strong>: C\u00f4ng c\u1ee5 qu\u1ea3n l\u00fd dependency v\u00e0 build d\u1ef1 \u00e1n.<\/li>\n\n\n\n<li><strong>IDE<\/strong>: M\u00f4i tr\u01b0\u1eddng ph\u00e1t tri\u1ec3n t\u00edch h\u1ee3p nh\u01b0 IntelliJ IDEA, Eclipse, ho\u1eb7c Visual Studio Code.<\/li>\n<\/ul>\n\n\n\n<p>B\u1ea1n c\u1ea7n th\u00eam hai lo\u1ea1i dependency ch\u00ednh: starter c\u1ee7a Spring Data JPA v\u00e0 driver c\u1ee7a c\u01a1 s\u1edf d\u1eef li\u1ec7u b\u1ea1n mu\u1ed1n s\u1eed d\u1ee5ng.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Spring Boot Starter Data JPA:<\/strong> \u0110\u00e2y l\u00e0 dependency &#8220;t\u1ea5t c\u1ea3 trong m\u1ed9t&#8221;, n\u00f3 \u0111\u00e3 bao g\u1ed3m:\n<ul class=\"wp-block-list\">\n<li><strong>Spring Data JPA<\/strong>: L\u00f5i c\u1ee7a th\u01b0 vi\u1ec7n.<\/li>\n\n\n\n<li><strong>Spring ORM<\/strong>: H\u1ed7 tr\u1ee3 t\u00edch h\u1ee3p ORM.<\/li>\n\n\n\n<li><strong>Hibernate<\/strong>: JPA Provider m\u1eb7c \u0111\u1ecbnh.<\/li>\n\n\n\n<li><strong>JDBC<\/strong>: API k\u1ebft n\u1ed1i CSDL t\u1ea7ng th\u1ea5p.<\/li>\n\n\n\n<li><strong>Database Driver:<\/strong> Th\u01b0 vi\u1ec7n n\u00e0y gi\u00fap \u1ee9ng d\u1ee5ng Java c\u00f3 th\u1ec3 &#8220;n\u00f3i chuy\u1ec7n&#8221; \u0111\u01b0\u1ee3c v\u1edbi m\u1ed9t lo\u1ea1i c\u01a1 s\u1edf d\u1eef li\u1ec7u c\u1ee5 th\u1ec3 (v\u00ed d\u1ee5: PostgreSQL, MySQL).<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Spring Data JPA<\/strong>: L\u00f5i c\u1ee7a th\u01b0 vi\u1ec7n.<\/li>\n\n\n\n<li><strong>Spring ORM<\/strong>: H\u1ed7 tr\u1ee3 t\u00edch h\u1ee3p ORM.<\/li>\n\n\n\n<li><strong>JDBC<\/strong>: API k\u1ebft n\u1ed1i CSDL t\u1ea7ng th\u1ea5p.<\/li>\n\n\n\n<li><strong>Database Driver:<\/strong> Th\u01b0 vi\u1ec7n n\u00e0y gi\u00fap \u1ee9ng d\u1ee5ng Java c\u00f3 th\u1ec3 &#8220;n\u00f3i chuy\u1ec7n&#8221; \u0111\u01b0\u1ee3c v\u1edbi m\u1ed9t lo\u1ea1i c\u01a1 s\u1edf d\u1eef li\u1ec7u c\u1ee5 th\u1ec3 (v\u00ed d\u1ee5: PostgreSQL, MySQL).<\/li>\n<\/ul>\n\n\n\n<p>D\u01b0\u1edbi \u0111\u00e2y l\u00e0 c\u00e1ch khai b\u00e1o trong Maven (<code>pom.xml<\/code>) v\u00e0 Gradle (<code>build.gradle<\/code>).<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"h-d\u1ed1i-v\u1edbi-maven-pom-xml\"><strong>\u0110\u1ed1i v\u1edbi Maven (<code>pom.xml<\/code>)<\/strong><\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;dependencies&gt;\n    &lt;dependency&gt;\n        &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;\n        &lt;artifactId&gt;spring-boot-starter-data-jpa&lt;\/artifactId&gt;\n    &lt;\/dependency&gt;\n\n    &lt;dependency&gt;\n        &lt;groupId&gt;com.h2database&lt;\/groupId&gt;\n        &lt;artifactId&gt;h2&lt;\/artifactId&gt;\n        &lt;scope&gt;runtime&lt;\/scope&gt;\n    &lt;\/dependency&gt;\n\n    &lt;dependency&gt;\n        &lt;groupId&gt;org.postgresql&lt;\/groupId&gt;\n        &lt;artifactId&gt;postgresql&lt;\/artifactId&gt;\n        &lt;scope&gt;runtime&lt;\/scope&gt;\n    &lt;\/dependency&gt;\n\n    &lt;dependency&gt;\n        &lt;groupId&gt;com.mysql&lt;\/groupId&gt;\n        &lt;artifactId&gt;mysql-connector-j&lt;\/artifactId&gt;\n        &lt;scope&gt;runtime&lt;\/scope&gt;\n    &lt;\/dependency&gt;\n&lt;\/dependencies&gt;<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"h-d\u1ed1i-v\u1edbi-gradle-build-gradle\"><strong>\u0110\u1ed1i v\u1edbi Gradle (<code>build.gradle<\/code>)<\/strong><\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code>dependencies {\n    \/\/ 1. Spring Data JPA Starter\n    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'\n\n    \/\/ 2. Ch\u1ecdn M\u1ed8T trong c\u00e1c Database Driver sau\n\n    \/\/ H2 Database (In-memory, t\u1ed1t cho testing)\n    runtimeOnly 'com.h2database:h2'\n\n    \/\/ PostgreSQL Driver\n    runtimeOnly 'org.postgresql:postgresql'\n\n    \/\/ MySQL Driver\n    runtimeOnly 'com.mysql:mysql-connector-j'\n}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-c\u1ea5u-hinh-datasource\"><strong>C\u1ea5u h\u00ecnh datasource<\/strong><\/h3>\n\n\n\n<p>Sau khi \u0111\u00e3 c\u00f3 dependencies, b\u1ea1n c\u1ea7n khai b\u00e1o th\u00f4ng tin \u0111\u1ec3 Spring Boot c\u00f3 th\u1ec3 k\u1ebft n\u1ed1i \u0111\u1ebfn c\u01a1 s\u1edf d\u1eef li\u1ec7u. C\u1ea5u h\u00ecnh n\u00e0y th\u01b0\u1eddng \u0111\u01b0\u1ee3c \u0111\u1eb7t trong file src\/main\/resources\/application.properties ho\u1eb7c application.yml.<\/p>\n\n\n\n<p>D\u01b0\u1edbi \u0111\u00e2y l\u00e0 c\u00e1c v\u00ed d\u1ee5 c\u1ea5u h\u00ecnh cho t\u1eebng lo\u1ea1i CSDL.<\/p>\n\n\n\n<p><strong>S\u1eed d\u1ee5ng <code>application.properties<\/code> (c\u00fa ph\u00e1p key=value)<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># C\u1ea5u h\u00ecnh cho PostgreSQL\nspring.datasource.url=jdbc:postgresql:\/\/localhost:5432\/ten_database\nspring.datasource.username=your_username\nspring.datasource.password=your_password\n\n# C\u1ea5u h\u00ecnh cho MySQL\n# spring.datasource.url=jdbc:mysql:\/\/localhost:3306\/ten_database\n# spring.datasource.username=your_username\n# spring.datasource.password=your_password\n\n# C\u1ea5u h\u00ecnh cho H2 In-Memory Database (kh\u00f4ng c\u1ea7n username\/password n\u1ebfu d\u00f9ng m\u1eb7c \u0111\u1ecbnh)\n# spring.datasource.url=jdbc:h2:mem:testdb\n# spring.datasource.driverClassName=org.h2.Driver\n# spring.jpa.database-platform=org.hibernate.dialect.H2Dialect\n\n# C\u1ea5u h\u00ecnh quan tr\u1ecdng c\u1ee7a JPA Hibernate\nspring.jpa.hibernate.ddl-auto=update\nspring.jpa.show-sql=true\nspring.jpa.properties.hibernate.format_sql=true<\/code><\/pre>\n\n\n\n<p><strong>S\u1eed d\u1ee5ng <code>application.yml<\/code> (c\u00fa ph\u00e1p YAML)<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>spring:\n  datasource:\n    # C\u1ea5u h\u00ecnh cho PostgreSQL\n    url: jdbc:postgresql:\/\/localhost:5432\/ten_database\n    username: your_username\n    password: your_password\n\n    # C\u1ea5u h\u00ecnh cho MySQL\n    # url: jdbc:mysql:\/\/localhost:3306\/ten_database\n    # username: your_username\n    # password: your_password\n    \n    # C\u1ea5u h\u00ecnh cho H2 In-Memory Database\n    # url: jdbc:h2:mem:testdb\n    # driverClassName: org.h2.Driver\n    \n  jpa:\n    hibernate:\n      ddl-auto: update # C\u1ea5u h\u00ecnh quan tr\u1ecdng c\u1ee7a JPA Hibernate\n    show-sql: true\n    properties:\n      hibernate:\n        format_sql: true\n    # database-platform: org.hibernate.dialect.H2Dialect # Cho H2<\/code><\/pre>\n\n\n\n<p><strong>Gi\u1ea3i th\u00edch c\u00e1c thu\u1ed9c t\u00ednh thi\u1ebft y\u1ebfu:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>spring.datasource.url<\/code>: Chu\u1ed7i k\u1ebft n\u1ed1i JDBC \u0111\u1ebfn c\u01a1 s\u1edf d\u1eef li\u1ec7u. C\u00fa ph\u00e1p s\u1ebd kh\u00e1c nhau t\u00f9y lo\u1ea1i CSDL.<\/li>\n\n\n\n<li><code>spring.datasource.username<\/code>: T\u00ean ng\u01b0\u1eddi d\u00f9ng \u0111\u1ec3 \u0111\u0103ng nh\u1eadp v\u00e0o CSDL.<\/li>\n\n\n\n<li><code>spring.datasource.password<\/code>: M\u1eadt kh\u1ea9u c\u1ee7a ng\u01b0\u1eddi d\u00f9ng.<\/li>\n\n\n\n<li><code>spring.jpa.hibernate.ddl-auto<\/code>: \u0110\u00e2y l\u00e0 m\u1ed9t thu\u1ed9c t\u00ednh c\u1ef1c k\u1ef3 quan tr\u1ecdng, n\u00f3 ra l\u1ec7nh cho Hibernate ph\u1ea3i l\u00e0m g\u00ec v\u1edbi schema (c\u1ea5u tr\u00fac b\u1ea3ng) c\u1ee7a c\u01a1 s\u1edf d\u1eef li\u1ec7u khi \u1ee9ng d\u1ee5ng kh\u1edfi \u0111\u1ed9ng.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-cac-thanh-ph\u1ea7n-chinh-c\u1ee7a-spring-data-jpa\"><span class=\"ez-toc-section\" id=\"Cac_thanh_phan_chinh_cua_Spring_Data_JPA\"><\/span><strong>C\u00e1c th\u00e0nh ph\u1ea7n ch\u00ednh c\u1ee7a Spring Data JPA<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>Sau khi \u0111\u00e3 t\u00ecm hi\u1ec3u s\u01a1 l\u01b0\u1ee3c c\u0169ng nh\u01b0 c\u00e1ch thi\u1ebft l\u1eadp v\u00e0 c\u00e0i \u0111\u1eb7t m\u00f4i tr\u01b0\u1eddng ph\u00e1t tri\u1ec3n, ch\u00fang ta s\u1ebd quay l\u1ea1i t\u00ecm hi\u1ec3u v\u1ec1 c\u00e1c th\u00e0nh ph\u1ea7n ch\u00ednh trong Spring Data JPA:<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-entity-anh-x\u1ea1-object-relational\"><strong>Entity &#8211; \u00c1nh x\u1ea1 Object-Relational<\/strong><\/h3>\n\n\n\n<p>M\u1ed9t <strong>Entity<\/strong> l\u00e0 m\u1ed9t l\u1edbp Java th\u00f4ng th\u01b0\u1eddng (POJO &#8211; Plain Old Java Object) \u0111\u01b0\u1ee3c &#8220;\u0111\u00e1nh d\u1ea5u&#8221; \u0111\u1ec3 \u0111\u1ea1i di\u1ec7n cho m\u1ed9t b\u1ea3ng trong c\u01a1 s\u1edf d\u1eef li\u1ec7u. Qu\u00e1 tr\u00ecnh \u00e1nh x\u1ea1 n\u00e0y (Object-Relational Mapping &#8211; ORM) \u0111\u01b0\u1ee3c th\u1ef1c hi\u1ec7n th\u00f4ng qua c\u00e1c <strong>annotation<\/strong> d\u01b0\u1edbi \u0111\u00e2y:<\/p>\n\n\n\n<p><code>@Entity<\/code>: Annotation quan tr\u1ecdng nh\u1ea5t, b\u00e1o cho JPA bi\u1ebft r\u1eb1ng l\u1edbp n\u00e0y l\u00e0 m\u1ed9t th\u1ef1c th\u1ec3 c\u1ea7n \u0111\u01b0\u1ee3c qu\u1ea3n l\u00fd v\u00e0 \u00e1nh x\u1ea1 xu\u1ed1ng m\u1ed9t b\u1ea3ng CSDL.<\/p>\n\n\n\n<p><code>@Table(name = \"ten_bang\")<\/code>: T\u00f9y ch\u1ecdn, d\u00f9ng \u0111\u1ec3 ch\u1ec9 \u0111\u1ecbnh t\u00ean b\u1ea3ng trong CSDL. N\u1ebfu b\u1ecf qua, JPA s\u1ebd t\u1ef1 l\u1ea5y t\u00ean c\u1ee7a l\u1edbp (th\u01b0\u1eddng l\u00e0 \u1edf d\u1ea1ng snake_case).<\/p>\n\n\n\n<p><code>@Id<\/code>: \u0110\u00e1nh d\u1ea5u m\u1ed9t tr\u01b0\u1eddng l\u00e0 <strong>kh\u00f3a ch\u00ednh<\/strong> (primary key) c\u1ee7a b\u1ea3ng. M\u1ed7i Entity b\u1eaft bu\u1ed9c ph\u1ea3i c\u00f3 m\u1ed9t kh\u00f3a ch\u00ednh.<\/p>\n\n\n\n<p><code>@GeneratedValue<\/code>: C\u1ea5u h\u00ecnh c\u00e1ch m\u00e0 kh\u00f3a ch\u00ednh \u0111\u01b0\u1ee3c sinh t\u1ef1 \u0111\u1ed9ng. C\u00f3 nhi\u1ec1u chi\u1ebfn l\u01b0\u1ee3c (strategy) kh\u00e1c nhau:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>GenerationType.IDENTITY<\/code>: Ph\u00f9 h\u1ee3p v\u1edbi c\u00e1c CSDL h\u1ed7 tr\u1ee3 c\u1ed9t t\u1ef1 t\u0103ng (auto-increment) nh\u01b0 MySQL, PostgreSQL.<\/li>\n\n\n\n<li><code>GenerationType.SEQUENCE<\/code>: S\u1eed d\u1ee5ng m\u1ed9t sequence trong CSDL \u0111\u1ec3 sinh kh\u00f3a, ph\u1ed5 bi\u1ebfn v\u1edbi Oracle, PostgreSQL.<\/li>\n\n\n\n<li><code>GenerationType.AUTO<\/code>: M\u1eb7c \u0111\u1ecbnh, JPA Provider (Hibernate) s\u1ebd t\u1ef1 ch\u1ecdn chi\u1ebfn l\u01b0\u1ee3c ph\u00f9 h\u1ee3p nh\u1ea5t.<\/li>\n<\/ul>\n\n\n\n<p><code>@Column(name = \"ten_cot\")<\/code>: T\u00f9y ch\u1ec9nh \u00e1nh x\u1ea1 cho m\u1ed9t tr\u01b0\u1eddng v\u1edbi m\u1ed9t c\u1ed9t. B\u1ea1n c\u00f3 th\u1ec3 \u0111\u1ecbnh ngh\u0129a t\u00ean c\u1ed9t, r\u00e0ng bu\u1ed9c <code>nullable<\/code>, <code>unique<\/code>, <code>length<\/code>, v.v.<\/p>\n\n\n\n<p><strong>V\u00ed d\u1ee5: L\u1edbp <\/strong><strong>User<\/strong><strong> Entity<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import jakarta.persistence.*; \/\/ Ho\u1eb7c javax.persistence.* cho Spring Boot 2.x\nimport java.time.LocalDate;\n\n@Entity\n@Table(name = \"users\") \/\/ \u00c1nh x\u1ea1 t\u1edbi b\u1ea3ng t\u00ean l\u00e0 \"users\"\npublic class User {\n\n    @Id\n    @GeneratedValue(strategy = GenerationType.IDENTITY) \/\/ Kh\u00f3a ch\u00ednh t\u1ef1 t\u0103ng\n    private Long id;\n\n    @Column(name = \"username\", nullable = false, unique = true, length = 50)\n    private String username;\n\n    @Column(name = \"email\", nullable = false, unique = true)\n    private String email;\n\n    @Column(nullable = false) \/\/ T\u00ean c\u1ed9t s\u1ebd t\u1ef1 \u0111\u1ed9ng l\u00e0 \"password\"\n    private String password;\n    \n    @Column(name = \"birth_date\")\n    private LocalDate birthDate;\n\n    \/\/ Constructors, Getters, Setters, toString()...\n    \/\/ (B\u1ecf qua \u0111\u1ec3 cho g\u1ecdn)\n}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-repository\"><strong>Repository<\/strong><\/h3>\n\n\n\n<p><strong>Repository Pattern<\/strong> l\u00e0 m\u1ed9t m\u1eabu thi\u1ebft k\u1ebf nh\u1eb1m t\u1ea1o ra m\u1ed9t l\u1edbp tr\u1eebu t\u01b0\u1ee3ng gi\u1eefa t\u1ea7ng business logic v\u00e0 t\u1ea7ng truy c\u1eadp d\u1eef li\u1ec7u. N\u00f3 \u0111\u00f3ng vai tr\u00f2 nh\u01b0 m\u1ed9t &#8220;kho ch\u1ee9a&#8221; c\u00e1c \u0111\u1ed1i t\u01b0\u1ee3ng, gi\u00fap che gi\u1ea5u \u0111i s\u1ef1 ph\u1ee9c t\u1ea1p c\u1ee7a vi\u1ec7c truy v\u1ea5n CSDL.<\/p>\n\n\n\n<p>Trong Spring Data JPA, b\u1ea1n kh\u00f4ng c\u1ea7n ph\u1ea3i vi\u1ebft l\u1edbp tri\u1ec3n khai cho Repository. Thay v\u00e0o \u0111\u00f3, b\u1ea1n ch\u1ec9 c\u1ea7n \u0111\u1ecbnh ngh\u0129a m\u1ed9t <code>interface <\/code>k\u1ebf th\u1eeba t\u1eeb <code>JpaRepository<\/code>.<\/p>\n\n\n\n<p><strong><code>JpaRepository&lt;T, ID&gt;<\/code><\/strong> \u0110\u00e2y l\u00e0 m\u1ed9t giao di\u1ec7n \u0111\u1eb7c bi\u1ec7t c\u1ee7a Spring Data JPA cung c\u1ea5p s\u1eb5n r\u1ea5t nhi\u1ec1u ph\u01b0\u01a1ng th\u1ee9c h\u1eefu \u00edch:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>C\u00e1c thao t\u00e1c CRUD \u0111\u1ea7y \u0111\u1ee7: <code>save()<\/code>, <code>findById()<\/code>, <code>findAll()<\/code>, <code>deleteById()<\/code>,&#8230;<\/li>\n\n\n\n<li>C\u00e1c thao t\u00e1c ph\u00e2n trang v\u00e0 s\u1eafp x\u1ebfp.<\/li>\n\n\n\n<li>C\u00e1c thao t\u00e1c batch (x\u1eed l\u00fd theo l\u00f4): <code>saveAll()<\/code>, <code>deleteAllInBatch()<\/code>,&#8230;<\/li>\n<\/ul>\n\n\n\n<p>B\u1ea1n ch\u1ec9 c\u1ea7n cung c\u1ea5p 2 tham s\u1ed1:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>T<\/code>: L\u1edbp Entity m\u00e0 repository n\u00e0y s\u1ebd qu\u1ea3n l\u00fd (v\u00ed d\u1ee5: <code>User<\/code>).<\/li>\n\n\n\n<li><code>ID<\/code>: Ki\u1ec3u d\u1eef li\u1ec7u c\u1ee7a kh\u00f3a ch\u00ednh trong Entity \u0111\u00f3 (v\u00ed d\u1ee5: <code>Long<\/code>).<\/li>\n<\/ul>\n\n\n\n<p>V\u00ed d\u1ee5: <code>UserRepository<\/code> Interface<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import org.springframework.data.jpa.repository.JpaRepository;\nimport org.springframework.stereotype.Repository;\n\n@Repository\npublic interface UserRepository extends JpaRepository&lt;User, Long&gt; {\n    \/\/ Spring Data JPA s\u1ebd t\u1ef1 \u0111\u1ed9ng cung c\u1ea5p c\u00e1c ph\u01b0\u01a1ng th\u1ee9c CRUD t\u1ea1i \u0111\u00e2y.\n    \/\/ B\u1ea1n kh\u00f4ng c\u1ea7n vi\u1ebft b\u1ea5t k\u1ef3 d\u00f2ng code tri\u1ec3n khai n\u00e0o!\n    \n    \/\/ Ch\u00fang ta s\u1ebd t\u00ecm hi\u1ec3u c\u00e1ch th\u00eam c\u00e1c ph\u01b0\u01a1ng th\u1ee9c truy v\u1ea5n t\u00f9y ch\u1ec9nh \u1edf ph\u1ea7n sau.\n}<\/code><\/pre>\n\n\n\n<p>Ch\u1ec9 v\u1edbi v\u00e0i d\u00f2ng code ng\u1eafn g\u1ecdn nh\u01b0 tr\u00ean, b\u1ea1n \u0111\u00e3 c\u00f3 m\u1ed9t t\u1ea7ng DAO (Data Access Object) ho\u00e0n ch\u1ec9nh cho <code>User<\/code> entity.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-cac-thao-tac-crud-c\u01a1-b\u1ea3n\"><strong>C\u00e1c thao t\u00e1c CRUD c\u01a1 b\u1ea3n<\/strong><\/h3>\n\n\n\n<p>B\u00e2y gi\u1edd, h\u00e3y xem c\u00e1ch s\u1eed d\u1ee5ng <code>UserRepository<\/code> trong m\u1ed9t l\u1edbp Service \u0111\u1ec3 th\u1ef1c hi\u1ec7n c\u00e1c thao t\u00e1c c\u01a1 b\u1ea3n.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\nimport java.util.List;\nimport java.util.Optional;\n\n@Service\npublic class UserService {\n\n    @Autowired\n    private UserRepository userRepository;\n\n    \/**\n     * CREATE \/ UPDATE: T\u1ea1o m\u1edbi ho\u1eb7c c\u1eadp nh\u1eadt ng\u01b0\u1eddi d\u00f9ng.\n     * Ph\u01b0\u01a1ng th\u1ee9c save() \u0111\u1ee7 th\u00f4ng minh \u0111\u1ec3 bi\u1ebft khi n\u00e0o n\u00ean INSERT, khi n\u00e0o n\u00ean UPDATE.\n     * - N\u1ebfu \u0111\u1ed1i t\u01b0\u1ee3ng User c\u00f3 id = null -&gt; INSERT.\n     * - N\u1ebfu \u0111\u1ed1i t\u01b0\u1ee3ng User c\u00f3 id \u0111\u00e3 t\u1ed3n t\u1ea1i trong DB -&gt; UPDATE.\n     *\/\n    public User saveUser(User user) {\n        return userRepository.save(user);\n    }\n\n    \/**\n     * READ: T\u00ecm m\u1ed9t ng\u01b0\u1eddi d\u00f9ng theo ID.\n     * Tr\u1ea3 v\u1ec1 m\u1ed9t Optional&lt;User&gt; \u0111\u1ec3 x\u1eed l\u00fd tr\u01b0\u1eddng h\u1ee3p kh\u00f4ng t\u00ecm th\u1ea5y user,\n     * tr\u00e1nh l\u1ed7i NullPointerException.\n     *\/\n    public Optional&lt;User&gt; findUserById(Long id) {\n        return userRepository.findById(id);\n    }\n\n    \/**\n     * READ: L\u1ea5y t\u1ea5t c\u1ea3 ng\u01b0\u1eddi d\u00f9ng.\n     *\/\n    public List&lt;User&gt; findAllUsers() {\n        return userRepository.findAll();\n    }\n\n    \/**\n     * DELETE: X\u00f3a ng\u01b0\u1eddi d\u00f9ng theo ID.\n     *\/\n    public void deleteUserById(Long id) {\n        \/\/ N\u00ean ki\u1ec3m tra s\u1ef1 t\u1ed3n t\u1ea1i tr\u01b0\u1edbc khi x\u00f3a \u0111\u1ec3 x\u1eed l\u00fd l\u1ed7i t\u1ed1t h\u01a1n\n        if (userRepository.existsById(id)) {\n            userRepository.deleteById(id);\n        } else {\n            \/\/ N\u00e9m ra m\u1ed9t exception ho\u1eb7c x\u1eed l\u00fd theo logic nghi\u1ec7p v\u1ee5\n            throw new RuntimeException(\"User not found with id: \" + id);\n        }\n    }\n    \n    \/**\n     * DELETE: X\u00f3a ng\u01b0\u1eddi d\u00f9ng b\u1eb1ng c\u00e1ch truy\u1ec1n v\u00e0o \u0111\u1ed1i t\u01b0\u1ee3ng entity.\n     *\/\n    public void deleteUser(User user) {\n        userRepository.delete(user);\n    }\n}<\/code><\/pre>\n\n\n\n<p>Sau \u0111\u00f3 ch\u00fang ta c\u00f3 th\u1ec3 s\u1eed d\u1ee5ng <strong>UserService<\/strong> nh\u01b0 sau:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ Gi\u1ea3 s\u1eed trong m\u1ed9t l\u1edbp Controller ho\u1eb7c m\u1ed9t l\u1edbp kh\u00e1c...\n\/\/ @Autowired private UserService userService;\n\n\/\/ 1. T\u1ea1o ng\u01b0\u1eddi d\u00f9ng m\u1edbi\nUser newUser = new User();\nnewUser.setUsername(\"tien_tran\");\nnewUser.setEmail(\"tien_tran@google.com\");\nnewUser.setPassword(\"password123\");\nUser savedUser = userService.saveUser(newUser);\nSystem.out.println(\"User \u0111\u00e3 \u0111\u01b0\u1ee3c l\u01b0u v\u1edbi ID: \" + savedUser.getId());\n\n\/\/ 2. T\u00ecm ng\u01b0\u1eddi d\u00f9ng theo ID\nOptional&lt;User&gt; foundUser = userService.findUserById(1L);\nfoundUser.ifPresent(user -&gt; System.out.println(\"T\u00ecm th\u1ea5y user: \" + user.getUsername()));\n\n\/\/ 3. C\u1eadp nh\u1eadt ng\u01b0\u1eddi d\u00f9ng\nfoundUser.ifPresent(user -&gt; {\n    user.setEmail(\"gemini.updated@google.com\");\n    userService.saveUser(user); \/\/ D\u00f9ng l\u1ea1i ph\u01b0\u01a1ng th\u1ee9c save()\n    System.out.println(\"\u0110\u00e3 c\u1eadp nh\u1eadt email cho user: \" + user.getUsername());\n});\n\n\/\/ 4. L\u1ea5y t\u1ea5t c\u1ea3 user\nList&lt;User&gt; allUsers = userService.findAllUsers();\nSystem.out.println(\"Danh s\u00e1ch t\u1ea5t c\u1ea3 user: \" + allUsers);\n\n\/\/ 5. X\u00f3a user\nuserService.deleteUserById(1L);\nSystem.out.println(\"\u0110\u00e3 x\u00f3a user v\u1edbi ID 1.\");<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-h\u01b0\u1edbng-d\u1eabn-khai-thac-cac-ph\u01b0\u01a1ng-th\u1ee9c-truy-v\u1ea5n-trong-spring-data-jpa\"><span class=\"ez-toc-section\" id=\"Huong_dan_khai_thac_cac_phuong_thuc_truy_van_trong_Spring_Data_JPA\"><\/span><strong>H\u01b0\u1edbng d\u1eabn khai th\u00e1c c\u00e1c ph\u01b0\u01a1ng th\u1ee9c truy v\u1ea5n trong Spring Data JPA<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-query-derivation-t\u1ea1o-truy-v\u1ea5n-t\u1eeb-ten-ph\u01b0\u01a1ng-th\u1ee9c\"><strong>Query Derivation &#8211; T\u1ea1o truy v\u1ea5n t\u1eeb t\u00ean ph\u01b0\u01a1ng th\u1ee9c<\/strong><\/h3>\n\n\n\n<p>\u0110\u00e2y l\u00e0 t\u00ednh n\u0103ng n\u1ed5i tr\u1ed9i nh\u1ea5t c\u1ee7a Spring Data JPA. Thay v\u00ec ph\u1ea3i t\u1ef1 tay vi\u1ebft nh\u1eefng c\u00e2u l\u1ec7nh truy v\u1ea5n ph\u1ee9c t\u1ea1p, b\u1ea1n ch\u1ec9 c\u1ea7n \u0111\u1eb7t t\u00ean cho ph\u01b0\u01a1ng th\u1ee9c c\u1ee7a m\u00ecnh theo m\u1ed9t quy \u01b0\u1edbc nh\u1ea5t \u0111\u1ecbnh. Spring Data JPA s\u1ebd t\u1ef1 \u0111\u1ed9ng ph\u00e2n t\u00edch t\u00ean ph\u01b0\u01a1ng th\u1ee9c \u0111\u00f3 v\u00e0 d\u1ecbch n\u00f3 th\u00e0nh m\u1ed9t c\u00e2u l\u1ec7nh truy v\u1ea5n t\u01b0\u01a1ng \u1ee9ng \u0111\u1ec3 th\u1ef1c thi d\u01b0\u1edbi c\u01a1 s\u1edf d\u1eef li\u1ec7u.<\/p>\n\n\n\n<p>C\u01a1 ch\u1ebf n\u00e0y ho\u1ea1t \u0111\u1ed9ng b\u1eb1ng c\u00e1ch nh\u1eadn di\u1ec7n c\u00e1c thu\u1ed9c t\u00ednh trong \u0111\u1ed1i t\u01b0\u1ee3ng c\u1ee7a b\u1ea1n (v\u00ed d\u1ee5: <code>email<\/code>, <code>name<\/code>, <code>age<\/code>) v\u00e0 k\u1ebft h\u1ee3p ch\u00fang v\u1edbi c\u00e1c t\u1eeb kh\u00f3a \u0111\u1eb7c bi\u1ec7t.<\/p>\n\n\n\n<p>H\u00e3y t\u01b0\u1edfng t\u01b0\u1ee3ng b\u1ea1n \u0111ang ra l\u1ec7nh b\u1eb1ng ng\u00f4n ng\u1eef t\u1ef1 nhi\u00ean:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u0110\u1ec3 t\u00ecm ng\u01b0\u1eddi d\u00f9ng b\u1eb1ng email, b\u1ea1n ch\u1ec9 c\u1ea7n m\u1ed9t ph\u01b0\u01a1ng th\u1ee9c t\u00ean l\u00e0 <code>findByEmail<\/code>.<\/li>\n\n\n\n<li>Mu\u1ed1n t\u00ecm ng\u01b0\u1eddi d\u00f9ng \u0111\u1ea7u ti\u00ean c\u00f3 t\u00ean cho tr\u01b0\u1edbc v\u00e0 s\u1eafp x\u1ebfp theo ng\u00e0y c\u1eadp nh\u1eadt m\u1edbi nh\u1ea5t? H\u00e3y \u0111\u1eb7t t\u00ean ph\u01b0\u01a1ng th\u1ee9c l\u00e0 <code>findFirstByNameOrderByLastModifiedDateDesc<\/code>.<\/li>\n<\/ul>\n\n\n\n<p>M\u1ed9t s\u1ed1 t\u1eeb kh\u00f3a ph\u1ed5 bi\u1ebfn b\u1ea1n c\u00f3 th\u1ec3 d\u00f9ng \u0111\u1ec3 gh\u00e9p n\u1ed1i v\u00e0 x\u00e2y d\u1ef1ng c\u00e1c &#8220;c\u00e2u l\u1ec7nh&#8221; ngay tr\u00ean t\u00ean ph\u01b0\u01a1ng th\u1ee9c bao g\u1ed3m:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>And, Or<\/strong>: \u0110\u1ec3 k\u1ebft h\u1ee3p nhi\u1ec1u \u0111i\u1ec1u ki\u1ec7n, v\u00ed d\u1ee5 nh\u01b0 t\u00ecm theo <code>t\u00ean V\u00c0 h\u1ecd<\/code>.<\/li>\n\n\n\n<li><strong>Between, LessThan, GreaterThan<\/strong>: \u0110\u1ec3 th\u1ef1c hi\u1ec7n c\u00e1c ph\u00e9p so s\u00e1nh v\u1edbi s\u1ed1 ho\u1eb7c ng\u00e0y th\u00e1ng, v\u00ed d\u1ee5 nh\u01b0 t\u00ecm s\u1ea3n ph\u1ea9m c\u00f3 gi\u00e1 <code>N\u1eb0M GI\u1eeeA<\/code> 100 v\u00e0 200.<\/li>\n\n\n\n<li><strong>Like, Containing<\/strong>: \u0110\u1ec3 t\u00ecm ki\u1ebfm m\u1ed9t ph\u1ea7n c\u1ee7a chu\u1ed7i v\u0103n b\u1ea3n, v\u00ed d\u1ee5 nh\u01b0 t\u00ecm b\u00e0i vi\u1ebft c\u00f3 ti\u00eau \u0111\u1ec1 <code>CH\u1ee8A<\/code> t\u1eeb &#8220;Spring&#8221;.<\/li>\n\n\n\n<li><strong>In<\/strong>: \u0110\u1ec3 t\u00ecm nh\u1eefng \u0111\u1ed1i t\u01b0\u1ee3ng c\u00f3 thu\u1ed9c t\u00ednh n\u1eb1m trong m\u1ed9t danh s\u00e1ch cho tr\u01b0\u1edbc.<\/li>\n\n\n\n<li><strong>OrderBy<\/strong>: \u0110\u1ec3 s\u1eafp x\u1ebfp k\u1ebft qu\u1ea3 tr\u1ea3 v\u1ec1 theo m\u1ed9t thu\u1ed9c t\u00ednh n\u00e0o \u0111\u00f3, v\u00ed d\u1ee5 <code>S\u1eaeP X\u1ebeP THEO<\/code> t\u00ean theo th\u1ee9 t\u1ef1 t\u0103ng d\u1ea7n.<\/li>\n<\/ul>\n\n\n\n<p>B\u1eb1ng c\u00e1ch k\u1ebft h\u1ee3p c\u00e1c t\u1eeb kh\u00f3a n\u00e0y, b\u1ea1n c\u00f3 th\u1ec3 t\u1ea1o ra v\u00f4 s\u1ed1 c\u00e1c truy v\u1ea5n kh\u00e1c nhau m\u00e0 kh\u00f4ng c\u1ea7n vi\u1ebft m\u1ed9t d\u00f2ng l\u1ec7nh SQL n\u00e0o.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-truy-v\u1ea5n-t\u01b0\u1eddng-minh-v\u1edbi-query\"><strong>Truy v\u1ea5n t\u01b0\u1eddng minh v\u1edbi <code>@Query<\/code><\/strong><\/h3>\n\n\n\n<p>T\u1ea5t nhi\u00ean, kh\u00f4ng ph\u1ea3i l\u00fac n\u00e0o vi\u1ec7c \u0111\u1eb7t m\u1ed9t c\u00e1i t\u00ean d\u00e0i ngo\u1eb1ng cho ph\u01b0\u01a1ng th\u1ee9c c\u0169ng l\u00e0 gi\u1ea3i ph\u00e1p hay, \u0111\u1eb7c bi\u1ec7t l\u00e0 v\u1edbi c\u00e1c logic ph\u1ee9c t\u1ea1p. \u0110\u00e2y l\u00e0 l\u00fac ch\u00fa th\u00edch <code>@Query <\/code>ph\u00e1t huy t\u00e1c d\u1ee5ng. N\u00f3 cho ph\u00e9p b\u1ea1n t\u1ef1 \u0111\u1ecbnh ngh\u0129a c\u00e2u l\u1ec7nh truy v\u1ea5n c\u1ee7a ri\u00eang m\u00ecnh.<\/p>\n\n\n\n<p>C\u00f3 hai c\u00e1ch ch\u00ednh \u0111\u1ec3 vi\u1ebft truy v\u1ea5n v\u1edbi <code>@Query<\/code>:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>D\u00f9ng JPQL (Java Persistence Query Language)<\/strong>: \u0110\u00e2y l\u00e0 c\u00e1ch \u0111\u01b0\u1ee3c khuy\u1ebfn kh\u00edch. Thay v\u00ec vi\u1ebft l\u1ec7nh tr\u00ean c\u00e1c b\u1ea3ng v\u00e0 c\u1ed9t c\u1ee7a c\u01a1 s\u1edf d\u1eef li\u1ec7u, b\u1ea1n s\u1ebd vi\u1ebft l\u1ec7nh truy v\u1ea5n tr\u00ean c\u00e1c \u0111\u1ed1i t\u01b0\u1ee3ng (Entity) v\u00e0 thu\u1ed9c t\u00ednh c\u1ee7a ch\u00fang. \u0110i\u1ec1u n\u00e0y gi\u00fap \u1ee9ng d\u1ee5ng c\u1ee7a b\u1ea1n kh\u00f4ng b\u1ecb ph\u1ee5 thu\u1ed9c v\u00e0o m\u1ed9t lo\u1ea1i c\u01a1 s\u1edf d\u1eef li\u1ec7u c\u1ee5 th\u1ec3 n\u00e0o. B\u1ea1n c\u00f3 th\u1ec3 d\u1ec5 d\u00e0ng truy\u1ec1n tham s\u1ed1 v\u00e0o c\u00e2u l\u1ec7nh m\u1ed9t c\u00e1ch an to\u00e0n th\u00f4ng qua c\u00e1c <em>tham s\u1ed1 \u0111\u01b0\u1ee3c \u0111\u1eb7t t\u00ean<\/em> (named parameters).<\/li>\n\n\n\n<li><strong>D\u00f9ng Native SQL<\/strong>: \u0110\u00f4i khi, b\u1ea1n c\u1ea7n s\u1eed d\u1ee5ng m\u1ed9t t\u00ednh n\u0103ng r\u1ea5t ri\u00eang bi\u1ec7t ch\u1ec9 c\u00f3 \u1edf m\u1ed9t h\u1ec7 qu\u1ea3n tr\u1ecb c\u01a1 s\u1edf d\u1eef li\u1ec7u nh\u1ea5t \u0111\u1ecbnh (v\u00ed d\u1ee5: PostgreSQL, Oracle). Native SQL cho ph\u00e9p b\u1ea1n vi\u1ebft m\u1ed9t c\u00e2u l\u1ec7nh SQL thu\u1ea7n v\u00e0 Spring Data JPA s\u1ebd th\u1ef1c thi n\u00f3 tr\u1ef1c ti\u1ebfp. Tuy nhi\u00ean, c\u1ea7n l\u01b0u \u00fd r\u1eb1ng c\u00e1ch l\u00e0m n\u00e0y s\u1ebd l\u00e0m m\u1ea5t \u0111i t\u00ednh linh ho\u1ea1t c\u1ee7a \u1ee9ng d\u1ee5ng. N\u1ebfu sau n\u00e0y b\u1ea1n mu\u1ed1n \u0111\u1ed5i sang m\u1ed9t lo\u1ea1i c\u01a1 s\u1edf d\u1eef li\u1ec7u kh\u00e1c, nh\u1eefng c\u00e2u l\u1ec7nh Native SQL n\u00e0y c\u00f3 th\u1ec3 s\u1ebd b\u1ecb l\u1ed7i v\u00e0 b\u1ea1n ph\u1ea3i vi\u1ebft l\u1ea1i ch\u00fang.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-phan-trang-va-s\u1eafp-x\u1ebfp-paging-amp-sorting\"><strong>Ph\u00e2n trang v\u00e0 s\u1eafp x\u1ebfp (Paging &amp; Sorting)<\/strong><\/h3>\n\n\n\n<p>Khi \u1ee9ng d\u1ee5ng c\u1ee7a b\u1ea1n c\u00f3 h\u00e0ng ng\u00e0n, h\u00e0ng tri\u1ec7u b\u1ea3n ghi, vi\u1ec7c t\u1ea3i t\u1ea5t c\u1ea3 ch\u00fang l\u00ean trong m\u1ed9t l\u1ea7n l\u00e0 \u0111i\u1ec1u kh\u00f4ng th\u1ec3. Spring Data JPA cung c\u1ea5p m\u1ed9t gi\u1ea3i ph\u00e1p c\u1ef1c k\u1ef3 thanh l\u1ecbch cho b\u00e0i to\u00e1n n\u00e0y th\u00f4ng qua hai kh\u00e1i ni\u1ec7m: <strong>Ph\u00e2n trang (Paging)<\/strong> v\u00e0 <strong>S\u1eafp x\u1ebfp (Sorting)<\/strong>.<\/p>\n\n\n\n<p>B\u1ea1n c\u00f3 th\u1ec3 th\u00eam c\u00e1c tham s\u1ed1 \u0111\u1eb7c bi\u1ec7t v\u00e0o ph\u01b0\u01a1ng th\u1ee9c truy v\u1ea5n c\u1ee7a m\u00ecnh \u0111\u1ec3 y\u00eau c\u1ea7u Spring Data JPA t\u1ef1 \u0111\u1ed9ng x\u1eed l\u00fd vi\u1ec7c n\u00e0y.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Tham s\u1ed1 Sort cho ph\u00e9p b\u1ea1n ch\u1ec9 \u0111\u1ecbnh c\u00e1ch s\u1eafp x\u1ebfp k\u1ebft qu\u1ea3 (v\u00ed d\u1ee5: s\u1eafp x\u1ebfp theo gi\u00e1 t\u1eeb cao \u0111\u1ebfn th\u1ea5p).<\/li>\n\n\n\n<li>Tham s\u1ed1 Pageable m\u1ea1nh m\u1ebd h\u01a1n, n\u00f3 bao g\u1ed3m c\u1ea3 th\u00f4ng tin s\u1eafp x\u1ebfp v\u00e0 th\u00f4ng tin ph\u00e2n trang (b\u1ea1n mu\u1ed1n l\u1ea5y trang th\u1ee9 m\u1ea5y? v\u00e0 m\u1ed7i trang c\u00f3 bao nhi\u00eau m\u1ee5c?).<\/li>\n<\/ul>\n\n\n\n<p>Khi b\u1ea1n s\u1eed d\u1ee5ng <code>Pageable<\/code>, k\u1ebft qu\u1ea3 tr\u1ea3 v\u1ec1 kh\u00f4ng ph\u1ea3i l\u00e0 m\u1ed9t danh s\u00e1ch \u0111\u01a1n thu\u1ea7n. Thay v\u00e0o \u0111\u00f3, b\u1ea1n s\u1ebd nh\u1eadn \u0111\u01b0\u1ee3c m\u1ed9t \u0111\u1ed1i t\u01b0\u1ee3ng <code>Page<\/code> \u0111\u1eb7c bi\u1ec7t. \u0110\u1ed1i t\u01b0\u1ee3ng n\u00e0y r\u1ea5t h\u1eefu \u00edch v\u00ec n\u00f3 ch\u1ee9a:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>N\u1ed9i dung c\u1ee7a trang hi\u1ec7n t\u1ea1i: Danh s\u00e1ch c\u00e1c m\u1ee5c thu\u1ed9c v\u1ec1 trang b\u1ea1n y\u00eau c\u1ea7u.<\/li>\n\n\n\n<li>Th\u00f4ng tin ph\u00e2n trang: T\u1ed5ng s\u1ed1 b\u1ea3n ghi, t\u1ed5ng s\u1ed1 trang, trang hi\u1ec7n t\u1ea1i l\u00e0 trang th\u1ee9 m\u1ea5y, c\u00f3 ph\u1ea3i trang \u0111\u1ea7u ti\u00ean hay trang cu\u1ed1i c\u00f9ng kh\u00f4ng.<\/li>\n<\/ul>\n\n\n\n<p>V\u1edbi nh\u1eefng th\u00f4ng tin n\u00e0y, vi\u1ec7c x\u00e2y d\u1ef1ng c\u00e1c ch\u1ee9c n\u0103ng nh\u01b0 thanh \u0111i\u1ec1u h\u01b0\u1edbng &#8220;Next&#8221;, &#8220;Previous&#8221;, &#8220;Go to page&#8230;&#8221; tr\u00ean giao di\u1ec7n ng\u01b0\u1eddi d\u00f9ng tr\u1edf n\u00ean v\u00f4 c\u00f9ng \u0111\u01a1n gi\u1ea3n.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-cac-k\u1ef9-thu\u1eadt-nang-cao-v\u1edbi-spring-data-jpa\"><span class=\"ez-toc-section\" id=\"Cac_ky_thuat_nang_cao_voi_Spring_Data_JPA\"><\/span><strong>C\u00e1c k\u1ef9 thu\u1eadt n\u00e2ng cao v\u1edbi Spring Data JPA<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>Khi \u0111\u00e3 n\u1eafm v\u1eefng nh\u1eefng ki\u1ebfn th\u1ee9c c\u01a1 b\u1ea3n, b\u1ea1n c\u00f3 th\u1ec3 n\u00e2ng t\u1ea7m \u1ee9ng d\u1ee5ng c\u1ee7a m\u00ecnh b\u1eb1ng c\u00e1c k\u1ef9 thu\u1eadt m\u1ea1nh m\u1ebd h\u01a1n. Nh\u1eefng c\u00f4ng c\u1ee5 n\u00e0y gi\u00fap b\u1ea1n gi\u1ea3i quy\u1ebft c\u00e1c b\u00e0i to\u00e1n ph\u1ee9c t\u1ea1p v\u1ec1 hi\u1ec7u n\u0103ng, qu\u1ea3n l\u00fd d\u1eef li\u1ec7u v\u00e0 x\u00e2y d\u1ef1ng truy v\u1ea5n \u0111\u1ed9ng.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-qu\u1ea3n-ly-quan-h\u1ec7-gi\u1eefa-cac-entity\"><strong>Qu\u1ea3n l\u00fd quan h\u1ec7 gi\u1eefa c\u00e1c Entity<\/strong><\/h3>\n\n\n\n<p>Trong th\u1ef1c t\u1ebf, c\u00e1c \u0111\u1ed1i t\u01b0\u1ee3ng d\u1eef li\u1ec7u lu\u00f4n c\u00f3 m\u1ed1i li\u00ean k\u1ebft v\u1edbi nhau. Spring Data JPA cung c\u1ea5p c\u00e1c c\u00f4ng c\u1ee5 \u0111\u1ec3 \u0111\u1ecbnh ngh\u0129a v\u00e0 qu\u1ea3n l\u00fd nh\u1eefng m\u1ed1i quan h\u1ec7 n\u00e0y m\u1ed9t c\u00e1ch hi\u1ec7u qu\u1ea3.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>\u00c1nh x\u1ea1 c\u00e1c m\u1ed1i quan h\u1ec7<\/strong>: B\u1ea1n d\u00f9ng c\u00e1c annotation nh\u01b0 <strong>@OneToOne<\/strong>, <strong>@OneToMany<\/strong>, <strong>@ManyToOne<\/strong>, v\u00e0 <strong>@ManyToMany<\/strong> \u0111\u1ec3 m\u00f4 t\u1ea3 c\u00e1ch c\u00e1c entity li\u00ean k\u1ebft v\u1edbi nhau.<\/li>\n\n\n\n<li><strong>Thu\u1ed9c t\u00ednh <code>cascade<\/code> v\u00e0 <code>fetch type<\/code><\/strong>:\n<ul class=\"wp-block-list\">\n<li><strong>Cascade<\/strong>: Quy\u1ebft \u0111\u1ecbnh xem c\u00e1c h\u00e0nh \u0111\u1ed9ng (l\u01b0u, x\u00f3a, c\u1eadp nh\u1eadt) c\u00f3 n\u00ean \u0111\u01b0\u1ee3c &#8220;lan truy\u1ec1n&#8221; sang c\u00e1c entity li\u00ean quan hay kh\u00f4ng.<\/li>\n\n\n\n<li><strong>Fetch Type<\/strong>: Quy\u1ebft \u0111\u1ecbnh khi n\u00e0o d\u1eef li\u1ec7u li\u00ean quan s\u1ebd \u0111\u01b0\u1ee3c t\u1ea3i. LAZY (ch\u1ec9 t\u1ea3i khi c\u1ea7n) l\u00e0 l\u1ef1a ch\u1ecdn t\u1ed1t cho hi\u1ec7u n\u0103ng, trong khi EAGER (t\u1ea3i ngay l\u1eadp t\u1ee9c) c\u00f3 th\u1ec3 g\u00e2y ra v\u1ea5n \u0111\u1ec1 N+1 Query.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-gi\u1ea3i-quy\u1ebft-v\u1ea5n-d\u1ec1-n-1-query\"><strong>Gi\u1ea3i quy\u1ebft v\u1ea5n \u0111\u1ec1 N+1 Query<\/strong><\/h3>\n\n\n\n<p>\u0110\u00e2y l\u00e0 m\u1ed9t &#8220;c\u1ea1m b\u1eaby&#8221; hi\u1ec7u n\u0103ng kinh \u0111i\u1ec3n. N\u00f3 x\u1ea3y ra khi b\u1ea1n t\u1ea3i N entity, r\u1ed3i l\u1ea1i ph\u1ea3i th\u1ef1c hi\u1ec7n th\u00eam N truy v\u1ea5n n\u1eefa \u0111\u1ec3 l\u1ea5y d\u1eef li\u1ec7u li\u00ean quan.<\/p>\n\n\n\n<p><strong>C\u00e1ch gi\u1ea3i quy\u1ebft<\/strong>: S\u1eed d\u1ee5ng <strong>@EntityGraph<\/strong> \u0111\u1ec3 ch\u1ec9 th\u1ecb cho JPA bi\u1ebft c\u1ea7n t\u1ea3i \u0111\u1ed3ng th\u1eddi c\u00e1c d\u1eef li\u1ec7u li\u00ean quan trong m\u1ed9t c\u00e2u truy v\u1ea5n duy nh\u1ea5t.<\/p>\n\n\n\n<p><strong>V\u00ed d\u1ee5:<\/strong> Gi\u1ea3i quy\u1ebft N+1 query khi l\u1ea5y danh s\u00e1ch t\u00e1c gi\u1ea3 (<code>Author<\/code>) v\u00e0 c\u00e1c b\u00e0i vi\u1ebft (<code>Post<\/code>) c\u1ee7a h\u1ecd.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ Trong entity Author\n@Entity\npublic class Author {\n    @Id\n    private Long id;\n    private String name;\n\n    \/\/ M\u1eb7c \u0111\u1ecbnh l\u00e0 LAZY fetching, c\u00f3 th\u1ec3 g\u00e2y ra N+1 query\n    @OneToMany(mappedBy = \"author\")\n    private List&lt;Post&gt; posts;\n    \n    \/\/ Getters and setters\n}<\/code><\/pre>\n\n\n\n<p>\u0110\u1ec3 kh\u1eafc ph\u1ee5c, ta d\u00f9ng <code>@EntityGraph<\/code> trong repository \u0111\u1ec3 b\u00e1o JPA t\u1ea3i lu\u00f4n danh s\u00e1ch posts.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ Trong AuthorRepository\npublic interface AuthorRepository extends JpaRepository&lt;Author, Long&gt; {\n    \n    \/\/ B\u00e1o cho JPA r\u1eb1ng khi t\u00ecm ki\u1ebfm Author, h\u00e3y t\u1ea3i \u0111\u1ed3ng th\u1eddi thu\u1ed9c t\u00ednh \"posts\".\n    @EntityGraph(attributePaths = { \"posts\" })\n    List&lt;Author&gt; findAll(); \n}<\/code><\/pre>\n\n\n\n<p>Thao t\u00e1c n\u00e0y s\u1ebd g\u1ed9p N+1 c\u00e2u truy v\u1ea5n th\u00e0nh m\u1ed9t c\u00e2u truy v\u1ea5n duy nh\u1ea5t d\u00f9ng JOIN, gi\u00fap c\u1ea3i thi\u1ec7n \u0111\u00e1ng k\u1ec3 hi\u1ec7u n\u0103ng.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-qu\u1ea3n-ly-transactions-giao-d\u1ecbch\"><strong>Qu\u1ea3n l\u00fd transactions (giao d\u1ecbch)<\/strong><\/h3>\n\n\n\n<p>Giao d\u1ecbch \u0111\u1ea3m b\u1ea3o r\u1eb1ng m\u1ed9t chu\u1ed7i c\u00e1c thao t\u00e1c v\u1edbi c\u01a1 s\u1edf d\u1eef li\u1ec7u di\u1ec5n ra nh\u01b0 m\u1ed9t kh\u1ed1i c\u00f4ng vi\u1ec7c duy nh\u1ea5t: ho\u1eb7c t\u1ea5t c\u1ea3 c\u00f9ng th\u00e0nh c\u00f4ng, ho\u1eb7c t\u1ea5t c\u1ea3 c\u00f9ng th\u1ea5t b\u1ea1i.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Vai tr\u00f2 c\u1ee7a <code>@Transactional<\/code><\/strong>: Annotation n\u00e0y khai b\u00e1o m\u1ed9t ph\u01b0\u01a1ng th\u1ee9c s\u1ebd \u0111\u01b0\u1ee3c th\u1ef1c thi b\u00ean trong m\u1ed9t giao d\u1ecbch. N\u1ebfu c\u00f3 l\u1ed7i, to\u00e0n b\u1ed9 c\u00e1c thay \u0111\u1ed5i s\u1ebd \u0111\u01b0\u1ee3c rollback (kh\u00f4i ph\u1ee5c l\u1ea1i tr\u1ea1ng th\u00e1i ban \u0111\u1ea7u).<\/li>\n\n\n\n<li><strong>\u0110\u1eb7t <code>@Transactional<\/code> \u1edf \u0111\u00e2u<\/strong>: Quy t\u1eafc ph\u1ed5 bi\u1ebfn nh\u1ea5t l\u00e0 \u0111\u1eb7t t\u1ea1i t\u1ea7ng Service (Service Layer), v\u00ec m\u1ed9t nghi\u1ec7p v\u1ee5 \u1edf t\u1ea7ng n\u00e0y th\u01b0\u1eddng bao g\u1ed3m nhi\u1ec1u thao t\u00e1c v\u1edbi c\u01a1 s\u1edf d\u1eef li\u1ec7u.<\/li>\n<\/ul>\n\n\n\n<p><strong>V\u00ed d\u1ee5:<\/strong> M\u1ed9t service \u0111\u0103ng k\u00fd ng\u01b0\u1eddi d\u00f9ng, bao g\u1ed3m vi\u1ec7c l\u01b0u ng\u01b0\u1eddi d\u00f9ng v\u00e0 ghi log h\u00e0nh \u0111\u1ed9ng.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>@Service\npublic class UserService {\n\n    @Autowired\n    private UserRepository userRepository;\n    \n    @Autowired\n    private LogRepository logRepository;\n\n    \/\/ To\u00e0n b\u1ed9 ph\u01b0\u01a1ng th\u1ee9c n\u00e0y \u0111\u01b0\u1ee3c bao b\u1ecdc trong m\u1ed9t giao d\u1ecbch.\n    \/\/ N\u1ebfu saveLog th\u1ea5t b\u1ea1i, vi\u1ec7c t\u1ea1o user c\u0169ng s\u1ebd \u0111\u01b0\u1ee3c h\u1ee7y b\u1ecf.\n    @Transactional\n    public void registerUser(User user, String action) {\n        userRepository.save(user); \/\/ Thao t\u00e1c 1\n        \n        \/\/ Gi\u1ea3 s\u1eed c\u00f3 l\u1ed7i x\u1ea3y ra \u1edf \u0111\u00e2y\n        if (action.equals(\"INVALID_ACTION\")) {\n            throw new RuntimeException(\"H\u00e0nh \u0111\u1ed9ng kh\u00f4ng h\u1ee3p l\u1ec7!\");\n        }\n\n        logRepository.save(new Log(action)); \/\/ Thao t\u00e1c 2\n    }\n}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-projections-l\u1ea5y-d\u1eef-li\u1ec7u-t\u1ed1i-gi\u1ea3n\"><strong>Projections: L\u1ea5y d\u1eef li\u1ec7u t\u1ed1i gi\u1ea3n<\/strong><\/h3>\n\n\n\n<p>Projections l\u00e0 k\u1ef9 thu\u1eadt cho ph\u00e9p b\u1ea1n ch\u1ec9 truy v\u1ea5n v\u00e0 l\u1ea5y v\u1ec1 nh\u1eefng c\u1ed9t d\u1eef li\u1ec7u c\u1ea7n thi\u1ebft thay v\u00ec to\u00e0n b\u1ed9 entity, gi\u00fap t\u1ed1i \u01b0u hi\u1ec7u n\u0103ng.<\/p>\n\n\n\n<p><strong>C\u00e1ch th\u1ef1c hi\u1ec7n ph\u1ed5 bi\u1ebfn nh\u1ea5t<\/strong>: D\u00f9ng <strong>Interface-based Projections<\/strong>. B\u1ea1n t\u1ea1o m\u1ed9t interface ch\u1ec9 ch\u1ee9a c\u00e1c ph\u01b0\u01a1ng th\u1ee9c getter cho nh\u1eefng thu\u1ed9c t\u00ednh b\u1ea1n mu\u1ed1n l\u1ea5y.<\/p>\n\n\n\n<p><strong>V\u00ed d\u1ee5:<\/strong> L\u1ea5y th\u00f4ng tin t\u00f3m t\u1eaft c\u1ee7a s\u1ea3n ph\u1ea9m (<code>Product<\/code>) thay v\u00ec t\u1ea5t c\u1ea3 c\u00e1c tr\u01b0\u1eddng.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ Entity Product c\u00f3 nhi\u1ec1u tr\u01b0\u1eddng\n@Entity\npublic class Product {\n    @Id\n    private Long id;\n    private String name;\n    private double price;\n    private String description;\n    private LocalDateTime createdAt;\n    \/\/ ...\n}\n\n\/\/ Projection interface ch\u1ec9 \u0111\u1ecbnh c\u00e1c tr\u01b0\u1eddng c\u1ea7n l\u1ea5y\npublic interface ProductSummary {\n    String getName();\n    double getPrice();\n}<\/code><\/pre>\n\n\n\n<p>Sau \u0111\u00f3, trong repository, b\u1ea1n khai b\u00e1o ph\u01b0\u01a1ng th\u1ee9c tr\u1ea3 v\u1ec1 ki\u1ec3u Product Summary.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ Trong ProductRepository\npublic interface ProductRepository extends JpaRepository&lt;Product, Long&gt; {\n    \n    \/\/ Spring Data JPA s\u1ebd t\u1ef1 \u0111\u1ed9ng t\u1ea1o query ch\u1ec9 SELECT 2 c\u1ed9t name v\u00e0 price\n    List&lt;ProductSummary&gt; findByCategory(String category);\n}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-xay-d\u1ef1ng-truy-v\u1ea5n-d\u1ed9ng-dynamic-queries\"><strong>X\u00e2y d\u1ef1ng truy v\u1ea5n \u0111\u1ed9ng (Dynamic Queries)<\/strong><\/h3>\n\n\n\n<p>\u0110\u00e2y l\u00e0 b\u00e0i to\u00e1n th\u01b0\u1eddng g\u1eb7p khi x\u00e2y d\u1ef1ng c\u00e1c ch\u1ee9c n\u0103ng t\u00ecm ki\u1ebfm ph\u1ee9c t\u1ea1p v\u1edbi nhi\u1ec1u b\u1ed9 l\u1ecdc t\u00f9y ch\u1ecdn.<\/p>\n\n\n\n<p>Spring Data JPA cung c\u1ea5p <strong>Specifications<\/strong> cho ph\u00e9p b\u1ea1n \u0111\u1ecbnh ngh\u0129a c\u00e1c \u0111i\u1ec1u ki\u1ec7n truy v\u1ea5n th\u00e0nh nh\u1eefng kh\u1ed1i logic nh\u1ecf, \u0111\u1ed9c l\u1eadp v\u00e0 c\u00f3 th\u1ec3 t\u00e1i s\u1eed d\u1ee5ng.<\/p>\n\n\n\n<p><strong>V\u00ed d\u1ee5:<\/strong> X\u00e2y d\u1ef1ng truy v\u1ea5n \u0111\u1ed9ng \u0111\u1ec3 t\u00ecm s\u1ea3n ph\u1ea9m theo t\u00ean v\u00e0 gi\u00e1.<\/p>\n\n\n\n<p>\u0110\u1ea7u ti\u00ean, t\u1ea1o m\u1ed9t l\u1edbp ch\u1ee9a c\u00e1c &#8220;m\u1ea3nh&#8221; truy v\u1ea5n c\u00f3 th\u1ec3 t\u00e1i s\u1eed d\u1ee5ng.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>public class ProductSpecifications {\n    \/\/ Tr\u1ea3 v\u1ec1 m\u1ed9t \u0111i\u1ec1u ki\u1ec7n \"name LIKE %keyword%\"\n    public static Specification&lt;Product&gt; nameContains(String keyword) {\n        return (root, query, criteriaBuilder) -&gt; \n            criteriaBuilder.like(root.get(\"name\"), \"%\" + keyword + \"%\");\n    }\n    \/\/ Tr\u1ea3 v\u1ec1 m\u1ed9t \u0111i\u1ec1u ki\u1ec7n \"price &gt; minPrice\"\n    public static Specification&lt;Product&gt; priceGreaterThan(double minPrice) {\n        return (root, query, criteriaBuilder) -&gt; \n            criteriaBuilder.greaterThan(root.get(\"price\"), minPrice);\n    }\n}<\/code><\/pre>\n\n\n\n<p>Sau \u0111\u00f3, trong repository, h\u00e3y k\u1ebf th\u1eeba <code>JpaSpecificationExecutor<\/code> v\u00e0 k\u1ebft h\u1ee3p c\u00e1c <code>Specification<\/code> l\u1ea1i.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ ProductRepository c\u1ea7n k\u1ebf th\u1eeba JpaSpecificationExecutor\npublic interface ProductRepository extends JpaRepository&lt;Product, Long&gt;, JpaSpecificationExecutor&lt;Product&gt; {\n}\n\n\/\/ Trong t\u1ea7ng Service, b\u1ea1n c\u00f3 th\u1ec3 k\u1ebft h\u1ee3p c\u00e1c \u0111i\u1ec1u ki\u1ec7n\n@Service\npublic class ProductService {\n    @Autowired\n    private ProductRepository productRepository;\n\n    public List&lt;Product&gt; searchProducts(String nameKeyword, double minPrice) {\n        \/\/ B\u1eaft \u0111\u1ea7u v\u1edbi m\u1ed9t Specification r\u1ed7ng\n        Specification&lt;Product&gt; spec = Specification.where(null);\n\n        if (nameKeyword != null) {\n            \/\/ N\u1ed1i th\u00eam \u0111i\u1ec1u ki\u1ec7n t\u00ean\n            spec = spec.and(ProductSpecifications.nameContains(nameKeyword));\n        }\n\n        if (minPrice &gt; 0) {\n            \/\/ N\u1ed1i th\u00eam \u0111i\u1ec1u ki\u1ec7n gi\u00e1\n            spec = spec.and(ProductSpecifications.priceGreaterThan(minPrice));\n        }\n        \n        return productRepository.findAll(spec);\n    }\n}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-cac-cach-t\u1ed1i-\u01b0u-hi\u1ec7u-nang-khi-lam-vi\u1ec7c-v\u1edbi-spring-data-jpa\"><span class=\"ez-toc-section\" id=\"Cac_cach_toi_uu_hieu_nang_khi_lam_viec_voi_Spring_Data_JPA\"><\/span><strong>C\u00e1c c\u00e1ch t\u1ed1i \u01b0u hi\u1ec7u n\u0103ng khi l\u00e0m vi\u1ec7c v\u1edbi Spring Data JPA<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>Vi\u1ebft code ch\u1ea1y \u0111\u00fang l\u00e0 m\u1ed9t chuy\u1ec7n, nh\u01b0ng vi\u1ebft code ch\u1ea1y nhanh v\u00e0 hi\u1ec7u qu\u1ea3 l\u1ea1i l\u00e0 m\u1ed9t th\u1eed th\u00e1ch kh\u00e1c.<\/p>\n\n\n\n<p>T\u1ed1i \u01b0u h\u00f3a trong JPA ch\u1ee7 y\u1ebfu xoay quanh vi\u1ec7c <strong>gi\u1ea3m s\u1ed1 l\u1ea7n t\u01b0\u01a1ng t\u00e1c v\u1edbi c\u01a1 s\u1edf d\u1eef li\u1ec7u<\/strong> v\u00e0 <strong>gi\u1ea3m l\u01b0\u1ee3ng d\u1eef li\u1ec7u truy\u1ec1n t\u1ea3i<\/strong> trong m\u1ed7i l\u1ea7n t\u01b0\u01a1ng t\u00e1c. V\u00ec c\u00e1c thao t\u00e1c v\u1edbi database th\u01b0\u1eddng l\u00e0 kh\u00e2u ch\u1eadm nh\u1ea5t trong \u1ee9ng d\u1ee5ng, t\u1ed1i \u01b0u ch\u00fang s\u1ebd mang l\u1ea1i hi\u1ec7u qu\u1ea3 r\u00f5 r\u1ec7t.<\/p>\n\n\n\n<p>&nbsp;D\u01b0\u1edbi \u0111\u00e2y l\u00e0 c\u00e1c ph\u01b0\u01a1ng ph\u00e1p v\u00e0 kinh nghi\u1ec7m th\u1ef1c t\u1ebf \u0111\u1ec3 t\u1ed1i \u01b0u h\u00f3a hi\u1ec7u n\u0103ng khi l\u00e0m vi\u1ec7c v\u1edbi Spring Data JPA:<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-s\u1eed-d\u1ee5ng-caching-strategies\"><strong>S\u1eed d\u1ee5ng Caching Strategies<\/strong><\/h3>\n\n\n\n<p>Caching l\u01b0u tr\u1eef d\u1eef li\u1ec7u th\u01b0\u1eddng xuy\u00ean truy c\u1eadp v\u00e0o b\u1ed9 nh\u1edb \u0111\u1ec3 kh\u00f4ng ph\u1ea3i truy v\u1ea5n l\u1ea1i t\u1eeb database.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>First-Level Cache (L1 Cache)<\/strong>: \u0110\u00e2y l\u00e0 b\u1ed9 \u0111\u1ec7m <strong>m<\/strong>\u1eb7c \u0111\u1ecbnh v\u00e0 t\u1ef1 \u0111\u1ed9ng c\u1ee7a Hibernate, g\u1eafn li\u1ec1n v\u1edbi m\u1ed9t phi\u00ean l\u00e0m vi\u1ec7c (Session) hay m\u1ed9t giao d\u1ecbch (<code>@Transactional<\/code>). N\u1ebfu b\u1ea1n truy v\u1ea5n c\u00f9ng m\u1ed9t \u0111\u1ed1i t\u01b0\u1ee3ng hai l\u1ea7n <em>b\u00ean trong c\u00f9ng m\u1ed9t ph\u01b0\u01a1ng th\u1ee9c service<\/em>, Hibernate s\u1ebd ch\u1ec9 \u0111\u00e1nh v\u00e0o database \u1edf l\u1ea7n \u0111\u1ea7u ti\u00ean, c\u00f2n l\u1ea7n th\u1ee9 hai n\u00f3 s\u1ebd l\u1ea5y ngay t\u1eeb b\u1ed9 nh\u1edb. B\u1ea1n kh\u00f4ng c\u1ea7n c\u1ea5u h\u00ecnh g\u00ec c\u1ea3, nh\u01b0ng c\u1ea7n bi\u1ebft n\u00f3 t\u1ed3n t\u1ea1i.<\/li>\n\n\n\n<li><strong>Second-Level Cache (L2 Cache)<\/strong>: \u0110\u00e2y l\u00e0 b\u1ed9 \u0111\u1ec7m \u0111\u01b0\u1ee3c chia s\u1ebb gi\u1eefa nhi\u1ec1u giao d\u1ecbch v\u00e0 ng\u01b0\u1eddi d\u00f9ng kh\u00e1c nhau.<\/li>\n<\/ul>\n\n\n\n<p>L2 Cache d\u00f9ng cho c\u00e1c d\u1eef li\u1ec7u \u00edt thay \u0111\u1ed5i nh\u01b0ng \u0111\u01b0\u1ee3c \u0111\u1ecdc r\u1ea5t th\u01b0\u1eddng xuy\u00ean (v\u00ed d\u1ee5: danh m\u1ee5c s\u1ea3n ph\u1ea9m, danh s\u00e1ch qu\u1ed1c gia, c\u1ea5u h\u00ecnh h\u1ec7 th\u1ed1ng). Vi\u1ec7c cache ch\u00fang s\u1ebd gi\u1ea3m t\u1ea3i \u0111\u00e1ng k\u1ec3 cho database.<\/p>\n\n\n\n<p>L2 Cache gi\u00fap t\u1ed1i \u01b0u c\u00e1c truy v\u1ea5n \u0111\u1ecdc (<code>SELECT<\/code>) l\u1eb7p \u0111i l\u1eb7p l\u1ea1i tr\u00ean c\u00e1c b\u1ea3ng d\u1eef li\u1ec7u t\u0129nh.<\/p>\n\n\n\n<p><strong>C\u00e1ch l\u00e0m<\/strong>: L2 Cache kh\u00f4ng \u0111\u01b0\u1ee3c b\u1eadt m\u1eb7c \u0111\u1ecbnh. B\u1ea1n c\u1ea7n th\u00eam m\u1ed9t th\u01b0 vi\u1ec7n cache (nh\u01b0 EhCache, Hazelcast) v\u00e0 k\u00edch ho\u1ea1t n\u00f3.<\/p>\n\n\n\n<p>V\u00ed d\u1ee5 c\u1ea5u h\u00ecnh L2 Cache v\u1edbi EhCache:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Properties\n# application.properties\n\n# K\u00edch ho\u1ea1t L2 Cache\nspring.jpa.properties.hibernate.cache.use_second_level_cache=true\n\n# Ch\u1ec9 \u0111\u1ecbnh nh\u00e0 cung c\u1ea5p cache\nspring.jpa.properties.hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.EhCacheRegionFactory<\/code><\/pre>\n\n\n\n<p>Sau \u0111\u00f3, b\u1ea1n ch\u1ec9 c\u1ea7n \u0111\u00e1nh d\u1ea5u c\u00e1c Entity b\u1ea1n mu\u1ed1n cache b\u1eb1ng annotation @Cacheable.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-x\u1eed-ly-hang-lo\u1ea1t-batch-processing\"><strong>X\u1eed l\u00fd h\u00e0ng lo\u1ea1t (Batch Processing)<\/strong><\/h3>\n\n\n\n<p>Khi b\u1ea1n c\u1ea7n <code>INSERT<\/code> ho\u1eb7c <code>UPDATE<\/code> h\u00e0ng ng\u00e0n b\u1ea3n ghi, vi\u1ec7c g\u1eedi t\u1eebng c\u00e2u l\u1ec7nh SQL m\u1ed9t s\u1ebd t\u1ea1o ra h\u00e0ng ng\u00e0n l\u01b0\u1ee3t \u0111i-v\u1ec1 (round-trip) gi\u1eefa \u1ee9ng d\u1ee5ng v\u00e0 database, c\u1ef1c k\u1ef3 l\u00e3ng ph\u00ed th\u1eddi gian.<\/p>\n\n\n\n<p>Batch Processing gi\u00fap t\u1ed1i \u01b0u hi\u1ec7u n\u0103ng cho c\u00e1c thao t\u00e1c <strong>ghi<\/strong> d\u1eef li\u1ec7u s\u1ed1 l\u01b0\u1ee3ng l\u1edbn (INSERT, UPDATE, DELETE) b\u1eb1ng c\u00e1ch nh\u00f3m ch\u00fang l\u1ea1i v\u00e0 g\u1eedi \u0111i trong m\u1ed9t l\u1ea7n.<\/p>\n\n\n\n<p><strong>C\u00e1ch l\u00e0m<\/strong>: B\u1ea1n c\u00f3 th\u1ec3 b\u1eadt t\u00ednh n\u0103ng JDBC batching c\u1ee7a Hibernate trong file c\u1ea5u h\u00ecnh.<br>V\u00ed d\u1ee5 c\u1ea5u h\u00ecnh JDBC Batching:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Properties\n# application.properties\n\n# B\u1eadt t\u00ednh n\u0103ng batch update\nspring.jpa.properties.hibernate.jdbc.batch_size=50\n\n# S\u1eafp x\u1ebfp c\u00e1c c\u00e2u l\u1ec7nh SQL \u0111\u1ec3 t\u1ed1i \u01b0u batch\nspring.jpa.properties.hibernate.order_inserts=true\nspring.jpa.properties.hibernate.order_updates=true<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-cac-best-practices-khac\"><strong>C\u00e1c best practices kh\u00e1c<\/strong><\/h3>\n\n\n\n<p>\u0110\u00e2y l\u00e0 nh\u1eefng kinh nghi\u1ec7m \u0111\u01b0\u1ee3c \u0111\u00fac k\u1ebft \u0111\u1ec3 gi\u00fap code c\u1ee7a b\u1ea1n s\u1ea1ch s\u1ebd, d\u1ec5 b\u1ea3o tr\u00ec v\u00e0 hi\u1ec7u qu\u1ea3 h\u01a1n.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Lu\u00f4n \u01b0u ti\u00ean FetchType.LAZY<\/strong>: \u0110\u1ed1i v\u1edbi c\u00e1c m\u1ed1i quan h\u1ec7 t\u1eadp h\u1ee3p (<code>@OneToMany<\/code>, <code>@ManyToMany<\/code>), h\u00e3y lu\u00f4n d\u00f9ng <code>LAZY<\/code>. Vi\u1ec7c n\u00e0y gi\u00fap b\u1ea1n tr\u00e1nh t\u1ea3i m\u1ed9t l\u01b0\u1ee3ng l\u1edbn d\u1eef li\u1ec7u kh\u00f4ng c\u1ea7n thi\u1ebft. Khi n\u00e0o th\u1ef1c s\u1ef1 c\u1ea7n, h\u00e3y ch\u1ee7 \u0111\u1ed9ng l\u1ea5y ch\u00fang b\u1eb1ng <code>@EntityGraph<\/code> ho\u1eb7c <code>JOIN FETCH<\/code>.<\/li>\n\n\n\n<li><strong>D\u00f9ng Projections (DTO) cho c\u00e1c m\u00e0n h\u00ecnh danh s\u00e1ch<\/strong>: \u0110\u1eebng bao gi\u1edd <code>SELECT *<\/code> khi b\u1ea1n ch\u1ec9 c\u1ea7n hi\u1ec3n th\u1ecb 2-3 c\u1ed9t. Projections gi\u00fap b\u1ea1n t\u1ea1o ra nh\u1eefng c\u00e2u l\u1ec7nh <code>SELECT<\/code> g\u1ecdn nh\u1eb9, ch\u1ec9 l\u1ea5y \u0111\u00fang nh\u1eefng g\u00ec c\u1ea7n thi\u1ebft.<\/li>\n\n\n\n<li><strong>Gi\u1eef Repository \u0111\u01a1n gi\u1ea3n<\/strong>: Repository ch\u1ec9 n\u00ean ch\u1ee9a c\u00e1c ph\u01b0\u01a1ng th\u1ee9c truy v\u1ea5n d\u1eef li\u1ec7u. To\u00e0n b\u1ed9 logic nghi\u1ec7p v\u1ee5, t\u00ednh to\u00e1n, hay k\u1ebft h\u1ee3p nhi\u1ec1u l\u1eddi g\u1ecdi repository n\u00ean \u0111\u01b0\u1ee3c \u0111\u1eb7t \u1edf t\u1ea7ng Service.<\/li>\n\n\n\n<li><strong>Hi\u1ec3u c\u00e2u l\u1ec7nh SQL \u0111\u01b0\u1ee3c sinh ra<\/strong>: B\u1ea1n kh\u00f4ng th\u1ec3 t\u1ed1i \u01b0u th\u1ee9 m\u00e0 b\u1ea1n kh\u00f4ng th\u1ea5y. M\u1ed9t th\u1ef1c h\u00e0nh c\u1ef1c k\u1ef3 quan tr\u1ecdng l\u00e0 lu\u00f4n theo d\u00f5i c\u00e1c c\u00e2u l\u1ec7nh SQL m\u00e0 JPA\/Hibernate t\u1ea1o ra trong qu\u00e1 tr\u00ecnh ph\u00e1t tri\u1ec3n.<br><strong>C\u00e1ch l\u00e0m<\/strong>: B\u1eadt t\u00ednh n\u0103ng ghi log SQL trong file <code>application.properties<\/code>.<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code>Properties\n# Hi\u1ec3n th\u1ecb c\u00e2u l\u1ec7nh SQL ra console\nspring.jpa.show-sql=true\n\n# \u0110\u1ecbnh d\u1ea1ng l\u1ea1i c\u00e2u l\u1ec7nh SQL cho d\u1ec5 \u0111\u1ecdc\nspring.jpa.properties.hibernate.format_sql=true<\/code><\/pre>\n\n\n\n<p>Vi\u1ec7c n\u00e0y gi\u00fap b\u1ea1n ngay l\u1eadp t\u1ee9c ph\u00e1t hi\u1ec7n c\u00e1c v\u1ea5n \u0111\u1ec1 nh\u01b0 N+1 query hay c\u00e1c c\u00e2u <code>JOIN <\/code>kh\u00f4ng hi\u1ec7u qu\u1ea3.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-cac-l\u1ed7i-th\u01b0\u1eddng-g\u1eb7p-v\u1edbi-spring-data-jpa-va-cach-kh\u1eafc-ph\u1ee5c\"><span class=\"ez-toc-section\" id=\"Cac_loi_thuong_gap_voi_Spring_Data_JPA_va_cach_khac_phuc\"><\/span><strong>C\u00e1c l\u1ed7i th\u01b0\u1eddng g\u1eb7p v\u1edbi Spring Data JPA v\u00e0 c\u00e1ch kh\u1eafc ph\u1ee5c<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-s\u1eed-d\u1ee5ng-fetchtype-eager-khong-c\u1ea7n-thi\u1ebft\"><strong>S\u1eed d\u1ee5ng <code>FetchType.EAGER<\/code> kh\u00f4ng c\u1ea7n thi\u1ebft<\/strong><\/h3>\n\n\n\n<p><strong>V\u1ea5n \u0111\u1ec1<\/strong>: G\u00e2y ra t\u00ecnh tr\u1ea1ng &#8220;over-fetching&#8221; (t\u1ea3i th\u1eeba d\u1eef li\u1ec7u), l\u00e0m ch\u1eadm c\u00e1c truy v\u1ea5n v\u00e0 c\u00f3 th\u1ec3 \u1ea9n gi\u1ea5u v\u1ea5n \u0111\u1ec1 N+1.<\/p>\n\n\n\n<p><strong>Kh\u1eafc ph\u1ee5c<\/strong>: Quy t\u1eafc v\u00e0ng l\u00e0: <strong>&#8220;M\u1eb7c \u0111\u1ecbnh d\u00f9ng <code>LAZY<\/code>, khi n\u00e0o c\u1ea7n th\u00ec ch\u1ee7 \u0111\u1ed9ng l\u1ea5y&#8221;<\/strong>. Chuy\u1ec3n t\u1ea5t c\u1ea3 c\u00e1c <code>FetchType.EAGER<\/code> sang <code>LAZY<\/code> v\u00e0 s\u1eed d\u1ee5ng <code>@EntityGraph<\/code> \u1edf repository \u0111\u1ec3 \u0111\u1ecbnh ngh\u0129a c\u00e1c tr\u01b0\u1eddng c\u1ea7n l\u1ea5y m\u1ed9t c\u00e1ch t\u01b0\u1eddng minh.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-v\u1ea5n-d\u1ec1-n-1-query\"><strong>V\u1ea5n \u0111\u1ec1 N+1 Query<\/strong><\/h3>\n\n\n\n<p><strong>V\u1ea5n \u0111\u1ec1<\/strong>: Hi\u1ec7u n\u0103ng \u1ee9ng d\u1ee5ng s\u1ee5t gi\u1ea3m nghi\u00eam tr\u1ecdng khi l\u00e0m vi\u1ec7c v\u1edbi danh s\u00e1ch. M\u1ed9t truy v\u1ea5n l\u1ea5y danh s\u00e1ch k\u00e9o theo N truy v\u1ea5n con.<\/p>\n\n\n\n<p><strong>Kh\u1eafc ph\u1ee5c<\/strong>: D\u00f9ng log SQL \u0111\u1ec3 ph\u00e1t hi\u1ec7n. S\u1eed d\u1ee5ng <code>JOIN FETCH<\/code> trong c\u00e1c c\u00e2u l\u1ec7nh <code>@Query<\/code> ho\u1eb7c d\u00f9ng <code>@EntityGraph<\/code> tr\u00ean ph\u01b0\u01a1ng th\u1ee9c repository \u0111\u1ec3 gi\u1ea3i quy\u1ebft.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-thao-tac-tren-d\u1eef-li\u1ec7u-ngoai-ph\u01b0\u01a1ng-th\u1ee9c-transactional\"><strong>Thao t\u00e1c tr\u00ean d\u1eef li\u1ec7u ngo\u00e0i ph\u01b0\u01a1ng th\u1ee9c <code>@Transactional<\/code><\/strong><\/h3>\n\n\n\n<p><strong>V\u1ea5n \u0111\u1ec1<\/strong>: Khi b\u1ea1n l\u1ea5y m\u1ed9t entity t\u1eeb database, sau \u0111\u00f3 k\u1ebft th\u00fac ph\u01b0\u01a1ng th\u1ee9c <code>@Transactional<\/code> (t\u1ee9c l\u00e0 session \u0111\u00e3 \u0111\u00f3ng), b\u1ea1n s\u1ebd kh\u00f4ng th\u1ec3 truy c\u1eadp v\u00e0o c\u00e1c thu\u1ed9c t\u00ednh <code>LAZY<\/code> c\u1ee7a entity \u0111\u00f3 n\u1eefa. N\u1ebfu c\u1ed1 l\u00e0m v\u1eady, b\u1ea1n s\u1ebd g\u1eb7p l\u1ed7i <code>LazyInitializationException<\/code>.<\/p>\n\n\n\n<p><strong>Kh\u1eafc ph\u1ee5c<\/strong>: \u0110\u1ea3m b\u1ea3o to\u00e0n b\u1ed9 chu tr\u00ecnh x\u1eed l\u00fd m\u1ed9t nghi\u1ec7p v\u1ee5 \u2014 t\u1eeb l\u00fac \u0111\u1ecdc d\u1eef li\u1ec7u, s\u1eeda \u0111\u1ed5i, cho \u0111\u1ebfn l\u00fac truy c\u1eadp c\u00e1c thu\u1ed9c t\u00ednh li\u00ean quan \u2014 \u0111\u1ec1u n\u1eb1m g\u1ecdn b\u00ean trong m\u1ed9t ph\u01b0\u01a1ng th\u1ee9c \u0111\u01b0\u1ee3c \u0111\u00e1nh d\u1ea5u <code>@Transactional<\/code> \u1edf t\u1ea7ng Service.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-cac-cau-h\u1ecfi-th\u01b0\u1eddng-g\u1eb7p-v\u1ec1-spring-data-jpa\"><span class=\"ez-toc-section\" id=\"Cac_cau_hoi_thuong_gap_ve_Spring_Data_JPA\"><\/span><strong>C\u00e1c c\u00e2u h\u1ecfi th\u01b0\u1eddng g\u1eb7p v\u1ec1 Spring Data JPA<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-nguyen-nhan-va-cach-kh\u1eafc-ph\u1ee5c-l\u1ed7i-lazyinitializationexception\"><strong>Nguy\u00ean nh\u00e2n v\u00e0 c\u00e1ch kh\u1eafc ph\u1ee5c l\u1ed7i LazyInitializationException?<\/strong><\/h3>\n\n\n\n<p>L\u1ed7i n\u00e0y x\u1ea3y ra khi b\u1ea1n c\u1ed1 g\u1eafng truy c\u1eadp v\u00e0o m\u1ed9t thu\u1ed9c t\u00ednh ho\u1eb7c m\u1ed9t danh s\u00e1ch li\u00ean quan \u0111\u01b0\u1ee3c t\u1ea3i theo ki\u1ec3u <strong>LAZY<\/strong> (t\u1ea3i l\u01b0\u1eddi) <em>sau khi<\/em> phi\u00ean l\u00e0m vi\u1ec7c (database session) \u0111\u00e3 b\u1ecb \u0111\u00f3ng.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Nguy\u00ean nh\u00e2n:<\/strong> Ph\u1ed5 bi\u1ebfn nh\u1ea5t l\u00e0 khi b\u1ea1n l\u1ea5y m\u1ed9t entity trong m\u1ed9t ph\u01b0\u01a1ng th\u1ee9c service, tr\u1ea3 n\u00f3 v\u1ec1 cho t\u1ea7ng controller, r\u1ed3i \u1edf controller b\u1ea1n m\u1edbi c\u1ed1 g\u1eafng l\u1ea5y danh s\u00e1ch c\u00e1c entity con c\u1ee7a n\u00f3. L\u00fac n\u00e0y, transaction \u0111\u00e3 k\u1ebft th\u00fac, session \u0111\u00e3 \u0111\u00f3ng, v\u00e0 JPA kh\u00f4ng th\u1ec3 quay l\u1ea1i database \u0111\u1ec3 t\u1ea3i d\u1eef li\u1ec7u \u0111\u01b0\u1ee3c n\u1eefa.<\/li>\n\n\n\n<li><strong>C\u00e1ch kh\u1eafc ph\u1ee5c d\u1ee9t \u0111i\u1ec3m:<\/strong> \u0110\u1ea3m b\u1ea3o to\u00e0n b\u1ed9 logic nghi\u1ec7p v\u1ee5, bao g\u1ed3m c\u1ea3 vi\u1ec7c truy c\u1eadp v\u00e0o c\u00e1c d\u1eef li\u1ec7u <code>LAZY<\/code>, \u0111\u1ec1u \u0111\u01b0\u1ee3c th\u1ef1c hi\u1ec7n b\u00ean trong m\u1ed9t ph\u01b0\u01a1ng th\u1ee9c \u0111\u01b0\u1ee3c \u0111\u00e1nh d\u1ea5u <strong><code>@Transactional<\/code><\/strong> \u1edf t\u1ea7ng Service. \u0110i\u1ec1u n\u00e0y gi\u1eef cho session lu\u00f4n m\u1edf trong su\u1ed1t qu\u00e1 tr\u00ecnh x\u1eed l\u00fd, cho ph\u00e9p JPA t\u1ea3i d\u1eef li\u1ec7u khi c\u1ea7n.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-spring-data-jpa-co-nhi\u1ec1u-cach-t\u1ea1o-truy-v\u1ea5n-ten-ph\u01b0\u01a1ng-th\u1ee9c-query-specifications-khi-nao-nen-dung-cach-nao\"><strong>Spring Data JPA c\u00f3 nhi\u1ec1u c\u00e1ch t\u1ea1o truy v\u1ea5n (t\u00ean ph\u01b0\u01a1ng th\u1ee9c, <code>@Query<\/code>, Specifications). Khi n\u00e0o n\u00ean d\u00f9ng c\u00e1ch n\u00e0o?<\/strong><\/h3>\n\n\n\n<p>L\u1ef1a ch\u1ecdn \u0111\u00fang c\u00f4ng c\u1ee5 s\u1ebd gi\u00fap code c\u1ee7a b\u1ea1n d\u1ec5 \u0111\u1ecdc v\u00e0 b\u1ea3o tr\u00ec h\u01a1n. D\u01b0\u1edbi \u0111\u00e2y l\u00e0 m\u1ed9t s\u1ed1 quy t\u1eafc \u0111\u01a1n gi\u1ea3n:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>D\u00f9ng Query Derivation (t\u1ea1o truy v\u1ea5n t\u1eeb t\u00ean ph\u01b0\u01a1ng th\u1ee9c)<\/strong>: Khi b\u1ea1n c\u1ea7n nh\u1eefng truy v\u1ea5n <strong>\u0111\u01a1n gi\u1ea3n, t\u0129nh<\/strong>, kh\u00f4ng c\u00f3 logic ph\u1ee9c t\u1ea1p. V\u00ed d\u1ee5: <code>findByEmail(String email)<\/code> hay <code>findFirstByOrderByIdDesc()<\/code>.<\/li>\n\n\n\n<li><strong>D\u00f9ng <code>@Query<\/code> v\u1edbi JPQL<\/strong>: Khi truy v\u1ea5n c\u1ee7a b\u1ea1n <strong>ph\u1ee9c t\u1ea1p h\u01a1n<\/strong>, c\u1ea7n <code>JOIN<\/code> nhi\u1ec1u b\u1ea3ng, c\u00f3 c\u00e1c h\u00e0m t\u00ednh to\u00e1n, ho\u1eb7c khi t\u00ean ph\u01b0\u01a1ng th\u1ee9c theo quy \u01b0\u1edbc tr\u1edf n\u00ean qu\u00e1 d\u00e0i v\u00e0 kh\u00f3 \u0111\u1ecdc.<\/li>\n\n\n\n<li><strong>D\u00f9ng Specifications (ho\u1eb7c Querydsl)<\/strong>: Khi b\u1ea1n c\u1ea7n x\u00e2y d\u1ef1ng c\u00e1c truy v\u1ea5n <strong>\u0111\u1ed9ng<\/strong>, t\u1ee9c l\u00e0 c\u00e1c \u0111i\u1ec1u ki\u1ec7n <code>WHERE<\/code> \u0111\u01b0\u1ee3c th\u00eam v\u00e0o d\u1ef1a tr\u00ean \u0111\u1ea7u v\u00e0o c\u1ee7a ng\u01b0\u1eddi d\u00f9ng (v\u00ed d\u1ee5: m\u1ed9t form t\u00ecm ki\u1ebfm c\u00f3 nhi\u1ec1u b\u1ed9 l\u1ecdc t\u00f9y ch\u1ecdn).<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-nen-dung-fetchtype-eager-hay-fetchtype-lazy-cho-cac-m\u1ed1i-quan-h\u1ec7\"><strong>N\u00ean d\u00f9ng <\/strong><strong>FetchType.EAGER<\/strong><strong> hay <\/strong><strong>FetchType.LAZY<\/strong><strong> cho c\u00e1c m\u1ed1i quan h\u1ec7?<\/strong><\/h3>\n\n\n\n<p>Quy t\u1eafc v\u00e0ng l\u00e0: <strong>Lu\u00f4n \u01b0u ti\u00ean d\u00f9ng <code>FetchType.LAZY<\/code><\/strong>, \u0111\u1eb7c bi\u1ec7t l\u00e0 cho c\u00e1c m\u1ed1i quan h\u1ec7 t\u1eadp h\u1ee3p nh\u01b0 <code>@OneToMany<\/code> v\u00e0 <code>@ManyToMany<\/code>.<\/p>\n\n\n\n<p>EAGER c\u00f3 v\u1ebb ti\u1ec7n l\u1ee3i v\u00ec n\u00f3 t\u1ea3i m\u1ecdi th\u1ee9 ngay l\u1eadp t\u1ee9c, nh\u01b0ng n\u00f3 ch\u00ednh l\u00e0 nguy\u00ean nh\u00e2n h\u00e0ng \u0111\u1ea7u g\u00e2y ra c\u00e1c v\u1ea5n \u0111\u1ec1 v\u1ec1 hi\u1ec7u n\u0103ng, \u0111\u1eb7c bi\u1ec7t l\u00e0 <strong>N+1 query<\/strong>. N\u00f3 bu\u1ed9c \u1ee9ng d\u1ee5ng ph\u1ea3i t\u1ea3i m\u1ed9t l\u01b0\u1ee3ng l\u1edbn d\u1eef li\u1ec7u m\u00e0 c\u00f3 th\u1ec3 b\u1ea1n kh\u00f4ng bao gi\u1edd d\u00f9ng \u0111\u1ebfn.<\/p>\n\n\n\n<p>C\u00e1ch ti\u1ebfp c\u1eadn t\u1ed1t nh\u1ea5t l\u00e0 h\u00e3y \u0111\u1ec3 m\u1ecdi th\u1ee9 l\u00e0 <code>LAZY<\/code>. Khi n\u00e0o b\u1ea1n th\u1ef1c s\u1ef1 c\u1ea7n d\u1eef li\u1ec7u li\u00ean quan cho m\u1ed9t tr\u01b0\u1eddng h\u1ee3p s\u1eed d\u1ee5ng c\u1ee5 th\u1ec3, h\u00e3y ch\u1ee7 \u0111\u1ed9ng y\u00eau c\u1ea7u JPA t\u1ea3i ch\u00fang b\u1eb1ng c\u00e1ch s\u1eed d\u1ee5ng <strong><code>@EntityGraph<\/code><\/strong> ho\u1eb7c <strong><code>JOIN FETCH<\/code><\/strong>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-projection-la-gi-va-t\u1ea1i-sao-toi-ph\u1ea3i-quan-tam-d\u1ebfn-no\"><strong>&#8220;Projection&#8221; l\u00e0 g\u00ec v\u00e0 t\u1ea1i sao t\u00f4i ph\u1ea3i quan t\u00e2m \u0111\u1ebfn n\u00f3?<\/strong><\/h3>\n\n\n\n<p><code>Projection<\/code> l\u00e0 m\u1ed9t k\u1ef9 thu\u1eadt cho ph\u00e9p b\u1ea1n ch\u1ec9 truy v\u1ea5n v\u00e0 l\u1ea5y v\u1ec1 <strong>m\u1ed9t t\u1eadp h\u1ee3p con c\u00e1c c\u1ed9t d\u1eef li\u1ec7u<\/strong> t\u1eeb database, thay v\u00ec l\u1ea5y to\u00e0n b\u1ed9 t\u1ea5t c\u1ea3 c\u00e1c c\u1ed9t c\u1ee7a m\u1ed9t entity.<\/p>\n\n\n\n<p>B\u1ea1n n\u00ean quan t\u00e2m \u0111\u1ebfn n\u00f3 v\u00ec m\u1ed9t l\u00fd do duy nh\u1ea5t: <strong>Hi\u1ec7u n\u0103ng<\/strong>.<\/p>\n\n\n\n<p>H\u00e3y t\u01b0\u1edfng t\u01b0\u1ee3ng entity <code>User<\/code> c\u1ee7a b\u1ea1n c\u00f3 30 c\u1ed9t, nh\u01b0ng tr\u00ean m\u00e0n h\u00ecnh danh s\u00e1ch, b\u1ea1n ch\u1ec9 c\u1ea7n hi\u1ec3n th\u1ecb <code>username<\/code> v\u00e0 <code>email<\/code>. Vi\u1ec7c s\u1eed d\u1ee5ng Projection s\u1ebd t\u1ea1o ra c\u00e2u l\u1ec7nh <code>SELECT username<\/code>, <code>email FROM users<\/code>&#8230; thay v\u00ec <code>SELECT * FROM users<\/code>&#8230;. \u0110i\u1ec1u n\u00e0y gi\u00fap gi\u1ea3m \u0111\u00e1ng k\u1ec3 l\u01b0\u1ee3ng d\u1eef li\u1ec7u truy\u1ec1n t\u1ea3i gi\u1eefa \u1ee9ng d\u1ee5ng v\u00e0 database, l\u00e0m cho \u1ee9ng d\u1ee5ng c\u1ee7a b\u1ea1n nhanh h\u01a1n v\u00e0 t\u1ed1n \u00edt b\u1ed9 nh\u1edb h\u01a1n.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-v\u1ea5n-d\u1ec1-n-1-query-la-gi-no-co-th\u1ef1c-s\u1ef1-nghiem-tr\u1ecdng-khong\"><strong>V\u1ea5n \u0111\u1ec1 &#8220;N+1 query&#8221; l\u00e0 g\u00ec? N\u00f3 c\u00f3 th\u1ef1c s\u1ef1 nghi\u00eam tr\u1ecdng kh\u00f4ng?<\/strong><\/h3>\n\n\n\n<p>\u0110\u00e2y l\u00e0 m\u1ed9t trong nh\u1eefng &#8220;c\u1ea1m b\u1eaby&#8221; hi\u1ec7u n\u0103ng nguy hi\u1ec3m nh\u1ea5t khi l\u00e0m vi\u1ec7c v\u1edbi ORM. N\u00f3 x\u1ea3y ra khi b\u1ea1n th\u1ef1c hi\u1ec7n <strong>1<\/strong> c\u00e2u truy v\u1ea5n \u0111\u1ec3 l\u1ea5y danh s\u00e1ch c\u00e1c \u0111\u1ed1i t\u01b0\u1ee3ng cha, sau \u0111\u00f3 l\u1ea1i th\u1ef1c hi\u1ec7n th\u00eam <strong>N<\/strong> c\u00e2u truy v\u1ea5n n\u1eefa \u0111\u1ec3 l\u1ea5y d\u1eef li\u1ec7u li\u00ean quan cho t\u1eebng \u0111\u1ed1i t\u01b0\u1ee3ng cha \u0111\u00f3.<\/p>\n\n\n\n<p><strong>N\u00f3 c\u1ef1c k\u1ef3 nghi\u00eam tr\u1ecdng.<\/strong> M\u1ed9t ch\u1ee9c n\u0103ng tr\u00f4ng c\u00f3 v\u1ebb \u0111\u01a1n gi\u1ea3n c\u00f3 th\u1ec3 \u00e2m th\u1ea7m t\u1ea1o ra h\u00e0ng tr\u0103m, th\u1eadm ch\u00ed h\u00e0ng ng\u00e0n l\u1eddi g\u1ecdi \u0111\u1ebfn database, l\u00e0m \u1ee9ng d\u1ee5ng c\u1ee7a b\u1ea1n ch\u1eadm \u0111i tr\u00f4ng th\u1ea5y.<\/p>\n\n\n\n<p>C\u00e1ch d\u1ec5 nh\u1ea5t \u0111\u1ec3 ph\u00e1t hi\u1ec7n ra n\u00f3 l\u00e0 b\u1eadt t\u00ednh n\u0103ng ghi log SQL (<code>spring.jpa.show-sql=true<\/code>). N\u1ebfu b\u1ea1n th\u1ea5y trong console log xu\u1ea5t hi\u1ec7n m\u1ed9t c\u00e2u <code>SELECT<\/code> \u0111\u1ea7u ti\u00ean, theo sau l\u00e0 h\u00e0ng lo\u1ea1t c\u00e1c c\u00e2u <code>SELECT<\/code> gi\u1ed1ng h\u1ec7t nhau \u0111\u01b0\u1ee3c th\u1ef1c thi l\u1eb7p \u0111i l\u1eb7p l\u1ea1i, th\u00ec \u0111\u00f3 ch\u00ednh l\u00e0 d\u1ea5u hi\u1ec7u c\u1ee7a N+1 query.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-t\u1ed5ng-k\u1ebft\"><span class=\"ez-toc-section\" id=\"Tong_ket\"><\/span><strong>T\u1ed5ng k\u1ebft<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>Spring Data JPA kh\u00f4ng ch\u1ec9 l\u00e0 m\u1ed9t c\u00f4ng c\u1ee5 gi\u00fap lo\u1ea1i b\u1ecf c\u00e1c \u0111o\u1ea1n code boilerplate nh\u00e0m ch\u00e1n. Qua nh\u1eefng g\u00ec ch\u00fang ta \u0111\u00e3 t\u00ecm hi\u1ec3u, t\u1eeb s\u1ef1 k\u1ef3 di\u1ec7u c\u1ee7a vi\u1ec7c t\u1ef1 sinh truy v\u1ea5n t\u1eeb t\u00ean ph\u01b0\u01a1ng th\u1ee9c, s\u1ee9c m\u1ea1nh ki\u1ec3m so\u00e1t c\u1ee7a <code>@Query<\/code>, cho \u0111\u1ebfn c\u00e1c k\u1ef9 thu\u1eadt t\u1ed1i \u01b0u hi\u1ec7u n\u0103ng v\u1edbi Projections v\u00e0 Caching, c\u00f3 th\u1ec3 th\u1ea5y \u0111\u00e2y l\u00e0 m\u1ed9t framework c\u1ef1c k\u1ef3 to\u00e0n di\u1ec7n.<\/p>\n\n\n\n<p>Hi v\u1ecdng r\u1eb1ng b\u00e0i vi\u1ebft n\u00e0y \u0111\u00e3 cung c\u1ea5p cho b\u1ea1n m\u1ed9t l\u1ed9 tr\u00ecnh r\u00f5 r\u00e0ng \u0111\u1ec3 khai th\u00e1c s\u00e2u h\u01a1n s\u1ee9c m\u1ea1nh c\u1ee7a Spring Data JPA, gi\u00fap b\u1ea1n x\u00e2y d\u1ef1ng nh\u1eefng \u1ee9ng d\u1ee5ng kh\u00f4ng ch\u1ec9 ch\u1ea1y \u0111\u00fang, m\u00e0 c\u00f2n ch\u1ea1y nhanh v\u00e0 hi\u1ec7u qu\u1ea3.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>S\u1ef1 ra \u0111\u1eddi c\u1ee7a Spring Data JPA \u0111\u00e3 th\u1ef1c s\u1ef1 thay \u0111\u1ed5i c\u00e1ch l\u1eadp tr\u00ecnh vi\u00ean ti\u1ebfp c\u1eadn t\u1ea7ng d\u1eef li\u1ec7u. Spring Data JPA l\u00e0 m\u1ed9t module c\u1ee7a Spring Data framework, \u0111\u01b0\u1ee3c x\u00e2y d\u1ef1ng \u0111\u1ec3 \u0111\u01a1n gi\u1ea3n h\u00f3a t\u1ea7ng truy c\u1eadp d\u1eef li\u1ec7u v\u00e0 gi\u1ea3m thi\u1ec3u m\u00e3 boilerplate, gi\u00fap t\u0103ng n\u0103ng su\u1ea5t v\u00e0 gi\u1ea3m thi\u1ec3u [&hellip;]<\/p>\n","protected":false},"author":203,"featured_media":93111,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_gspb_post_css":"","footnotes":""},"categories":[109,10350],"tags":[],"class_list":["post-91205","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-chuyen-mon-it","category-java"],"blocksy_meta":[],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v26.8 (Yoast SEO v27.7) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Spring Data JPA: H\u01b0\u1edbng d\u1eabn to\u00e0n t\u1eadp t\u1eeb c\u01a1 b\u1ea3n \u0111\u1ebfn n\u00e2ng cao - ITviec Blog<\/title>\n<meta name=\"description\" content=\"H\u01b0\u1edbng d\u1eabn to\u00e0n t\u1eadp v\u1ec1 Spring Data JPA t\u1eeb c\u00e0i \u0111\u1eb7t, th\u00e0nh ph\u1ea7n, truy v\u1ea5n, t\u1ed1i \u01b0u v\u00e0 x\u1eed l\u00fd l\u1ed7i, gi\u00fap b\u1ea1n \u00e1p d\u1ee5ng hi\u1ec7u qu\u1ea3 v\u00e0o d\u1ef1 \u00e1n.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/itviec.com\/blog\/spring-data-jpa-la-gi\/\" \/>\n<meta property=\"og:locale\" content=\"vi_VN\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Spring Data JPA: H\u01b0\u1edbng d\u1eabn to\u00e0n t\u1eadp t\u1eeb c\u01a1 b\u1ea3n \u0111\u1ebfn n\u00e2ng cao\" \/>\n<meta property=\"og:description\" content=\"S\u1ef1 ra \u0111\u1eddi c\u1ee7a Spring Data JPA \u0111\u00e3 th\u1ef1c s\u1ef1 thay \u0111\u1ed5i c\u00e1ch l\u1eadp tr\u00ecnh vi\u00ean ti\u1ebfp c\u1eadn t\u1ea7ng d\u1eef li\u1ec7u. Spring Data JPA l\u00e0 m\u1ed9t module c\u1ee7a Spring Data framework, \u0111\u01b0\u1ee3c\" \/>\n<meta property=\"og:url\" content=\"https:\/\/itviec.com\/blog\/spring-data-jpa-la-gi\/\" \/>\n<meta property=\"og:site_name\" content=\"ITviec Blog\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/ITviec\" \/>\n<meta property=\"article:published_time\" content=\"2025-11-24T07:43:02+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-11-24T07:43:05+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/itviec.com\/blog\/wp-content\/uploads\/2025\/11\/spring-data-jpa-scaled.png\" \/>\n\t<meta property=\"og:image:width\" content=\"800\" \/>\n\t<meta property=\"og:image:height\" content=\"421\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Tien Tran\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@ITviec\" \/>\n<meta name=\"twitter:site\" content=\"@ITviec\" \/>\n<meta name=\"twitter:label1\" content=\"\u0110\u01b0\u1ee3c vi\u1ebft b\u1edfi\" \/>\n\t<meta name=\"twitter:data1\" content=\"Tien Tran\" \/>\n\t<meta name=\"twitter:label2\" content=\"\u01af\u1edbc t\u00ednh th\u1eddi gian \u0111\u1ecdc\" \/>\n\t<meta name=\"twitter:data2\" content=\"26 ph\u00fat\" \/>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Spring Data JPA: H\u01b0\u1edbng d\u1eabn to\u00e0n t\u1eadp t\u1eeb c\u01a1 b\u1ea3n \u0111\u1ebfn n\u00e2ng cao - ITviec Blog","description":"H\u01b0\u1edbng d\u1eabn to\u00e0n t\u1eadp v\u1ec1 Spring Data JPA t\u1eeb c\u00e0i \u0111\u1eb7t, th\u00e0nh ph\u1ea7n, truy v\u1ea5n, t\u1ed1i \u01b0u v\u00e0 x\u1eed l\u00fd l\u1ed7i, gi\u00fap b\u1ea1n \u00e1p d\u1ee5ng hi\u1ec7u qu\u1ea3 v\u00e0o d\u1ef1 \u00e1n.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/itviec.com\/blog\/spring-data-jpa-la-gi\/","og_locale":"vi_VN","og_type":"article","og_title":"Spring Data JPA: H\u01b0\u1edbng d\u1eabn to\u00e0n t\u1eadp t\u1eeb c\u01a1 b\u1ea3n \u0111\u1ebfn n\u00e2ng cao","og_description":"S\u1ef1 ra \u0111\u1eddi c\u1ee7a Spring Data JPA \u0111\u00e3 th\u1ef1c s\u1ef1 thay \u0111\u1ed5i c\u00e1ch l\u1eadp tr\u00ecnh vi\u00ean ti\u1ebfp c\u1eadn t\u1ea7ng d\u1eef li\u1ec7u. Spring Data JPA l\u00e0 m\u1ed9t module c\u1ee7a Spring Data framework, \u0111\u01b0\u1ee3c","og_url":"https:\/\/itviec.com\/blog\/spring-data-jpa-la-gi\/","og_site_name":"ITviec Blog","article_publisher":"https:\/\/www.facebook.com\/ITviec","article_published_time":"2025-11-24T07:43:02+00:00","article_modified_time":"2025-11-24T07:43:05+00:00","og_image":[{"width":800,"height":421,"url":"https:\/\/itviec.com\/blog\/wp-content\/uploads\/2025\/11\/spring-data-jpa-scaled.png","type":"image\/png"}],"author":"Tien Tran","twitter_card":"summary_large_image","twitter_creator":"@ITviec","twitter_site":"@ITviec","twitter_misc":{"\u0110\u01b0\u1ee3c vi\u1ebft b\u1edfi":"Tien Tran","\u01af\u1edbc t\u00ednh th\u1eddi gian \u0111\u1ecdc":"26 ph\u00fat"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/itviec.com\/blog\/spring-data-jpa-la-gi\/#article","isPartOf":{"@id":"https:\/\/itviec.com\/blog\/spring-data-jpa-la-gi\/"},"author":{"name":"Tien Tran","@id":"https:\/\/itviec.com\/blog\/#\/schema\/person\/1595d671c49cfa2a48cd3c0a047a1298"},"headline":"Spring Data JPA: H\u01b0\u1edbng d\u1eabn to\u00e0n t\u1eadp t\u1eeb c\u01a1 b\u1ea3n \u0111\u1ebfn n\u00e2ng cao","datePublished":"2025-11-24T07:43:02+00:00","dateModified":"2025-11-24T07:43:05+00:00","mainEntityOfPage":{"@id":"https:\/\/itviec.com\/blog\/spring-data-jpa-la-gi\/"},"wordCount":7053,"publisher":{"@id":"https:\/\/itviec.com\/blog\/#organization"},"image":{"@id":"https:\/\/itviec.com\/blog\/spring-data-jpa-la-gi\/#primaryimage"},"thumbnailUrl":"https:\/\/itviec.com\/blog\/wp-content\/uploads\/2025\/11\/spring-data-jpa-scaled.png","articleSection":["Chuy\u00ean m\u00f4n IT","Java"],"inLanguage":"vi"},{"@type":"WebPage","@id":"https:\/\/itviec.com\/blog\/spring-data-jpa-la-gi\/","url":"https:\/\/itviec.com\/blog\/spring-data-jpa-la-gi\/","name":"Spring Data JPA: H\u01b0\u1edbng d\u1eabn to\u00e0n t\u1eadp t\u1eeb c\u01a1 b\u1ea3n \u0111\u1ebfn n\u00e2ng cao - ITviec Blog","isPartOf":{"@id":"https:\/\/itviec.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/itviec.com\/blog\/spring-data-jpa-la-gi\/#primaryimage"},"image":{"@id":"https:\/\/itviec.com\/blog\/spring-data-jpa-la-gi\/#primaryimage"},"thumbnailUrl":"https:\/\/itviec.com\/blog\/wp-content\/uploads\/2025\/11\/spring-data-jpa-scaled.png","datePublished":"2025-11-24T07:43:02+00:00","dateModified":"2025-11-24T07:43:05+00:00","description":"H\u01b0\u1edbng d\u1eabn to\u00e0n t\u1eadp v\u1ec1 Spring Data JPA t\u1eeb c\u00e0i \u0111\u1eb7t, th\u00e0nh ph\u1ea7n, truy v\u1ea5n, t\u1ed1i \u01b0u v\u00e0 x\u1eed l\u00fd l\u1ed7i, gi\u00fap b\u1ea1n \u00e1p d\u1ee5ng hi\u1ec7u qu\u1ea3 v\u00e0o d\u1ef1 \u00e1n.","breadcrumb":{"@id":"https:\/\/itviec.com\/blog\/spring-data-jpa-la-gi\/#breadcrumb"},"inLanguage":"vi","potentialAction":[{"@type":"ReadAction","target":["https:\/\/itviec.com\/blog\/spring-data-jpa-la-gi\/"]}]},{"@type":"ImageObject","inLanguage":"vi","@id":"https:\/\/itviec.com\/blog\/spring-data-jpa-la-gi\/#primaryimage","url":"https:\/\/itviec.com\/blog\/wp-content\/uploads\/2025\/11\/spring-data-jpa-scaled.png","contentUrl":"https:\/\/itviec.com\/blog\/wp-content\/uploads\/2025\/11\/spring-data-jpa-scaled.png","width":800,"height":421,"caption":"spring data jpa - itviec blog"},{"@type":"BreadcrumbList","@id":"https:\/\/itviec.com\/blog\/spring-data-jpa-la-gi\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Chuy\u00ean m\u00f4n IT","item":"https:\/\/itviec.com\/blog\/chuyen-mon-it\/"},{"@type":"ListItem","position":2,"name":"Spring Data JPA: H\u01b0\u1edbng d\u1eabn to\u00e0n t\u1eadp t\u1eeb c\u01a1 b\u1ea3n \u0111\u1ebfn n\u00e2ng cao"}]},{"@type":"WebSite","@id":"https:\/\/itviec.com\/blog\/#website","url":"https:\/\/itviec.com\/blog\/","name":"ITviec Blog","description":"IT Jobs &amp; People in Vietnam","publisher":{"@id":"https:\/\/itviec.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/itviec.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"vi"},{"@type":"Organization","@id":"https:\/\/itviec.com\/blog\/#organization","name":"ITviec","url":"https:\/\/itviec.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"vi","@id":"https:\/\/itviec.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/itviec.com\/blog\/wp-content\/uploads\/2018\/12\/itviec-black-square-facebook.png","contentUrl":"https:\/\/itviec.com\/blog\/wp-content\/uploads\/2018\/12\/itviec-black-square-facebook.png","width":1800,"height":1800,"caption":"ITviec"},"image":{"@id":"https:\/\/itviec.com\/blog\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/ITviec","https:\/\/x.com\/ITviec","https:\/\/www.linkedin.com\/company\/itviec","https:\/\/www.youtube.com\/channel\/UCYthAQ3bcGr57M_ag5gHDvQ"]},{"@type":"Person","@id":"https:\/\/itviec.com\/blog\/#\/schema\/person\/1595d671c49cfa2a48cd3c0a047a1298","name":"Tien Tran","image":{"@type":"ImageObject","inLanguage":"vi","@id":"https:\/\/itviec.com\/blog\/wp-content\/uploads\/2024\/05\/tien-tran-author-e1715658627643-100x100.jpg","url":"https:\/\/itviec.com\/blog\/wp-content\/uploads\/2024\/05\/tien-tran-author-e1715658627643-100x100.jpg","contentUrl":"https:\/\/itviec.com\/blog\/wp-content\/uploads\/2024\/05\/tien-tran-author-e1715658627643-100x100.jpg","caption":"Tien Tran"},"url":"https:\/\/itviec.com\/blog\/author\/tien-tran\/"}]}},"_links":{"self":[{"href":"https:\/\/itviec.com\/blog\/wp-json\/wp\/v2\/posts\/91205","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/itviec.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/itviec.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/itviec.com\/blog\/wp-json\/wp\/v2\/users\/203"}],"replies":[{"embeddable":true,"href":"https:\/\/itviec.com\/blog\/wp-json\/wp\/v2\/comments?post=91205"}],"version-history":[{"count":4,"href":"https:\/\/itviec.com\/blog\/wp-json\/wp\/v2\/posts\/91205\/revisions"}],"predecessor-version":[{"id":93109,"href":"https:\/\/itviec.com\/blog\/wp-json\/wp\/v2\/posts\/91205\/revisions\/93109"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/itviec.com\/blog\/wp-json\/wp\/v2\/media\/93111"}],"wp:attachment":[{"href":"https:\/\/itviec.com\/blog\/wp-json\/wp\/v2\/media?parent=91205"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/itviec.com\/blog\/wp-json\/wp\/v2\/categories?post=91205"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/itviec.com\/blog\/wp-json\/wp\/v2\/tags?post=91205"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}