JPA是Spring Data框架的其中一個模塊,全稱為Java Persistence API,是一個持久層規範,Hibernate框架是JPA實現之一。 本文內容: (1)項目構建 (2)數據訪問層與業務層 (3)自定義數據存儲邏輯 (4)方法名查詢 (5)使用@Query註解 ...
Spring Data框架為數據訪問提供了一個通用的模型,無論訪問哪種資料庫,都可以使用同樣的方式,主要有以下幾個功能:
(1)提供數據與對象映射的抽象層,同一個對象,可以被映射為不同資料庫的數據;
(2)根據數據存儲介面的方法名,自動實現數據查詢;
(3)為各個領域模型提供最基本的實現,例如增刪改查功能;
(4)可在原有邏輯的基礎上實現自定義資料庫操作邏輯。
JPA是Spring Data框架的其中一個模塊,全稱為Java Persistence API,是一個持久層規範,Hibernate框架是JPA實現之一。
本文內容:
(1)項目構建
(2)數據訪問層與業務層
(3)自定義數據存儲邏輯
(4)方法名查詢
(5)使用@Query註解
開發環境:IntelliJ IDEA 2019.2.2
Spring Boot版本:2.1.8
一、項目構建
1、新建一個名稱為demo的Spring Boot項目。
2、pom.xml
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> </dependency>
3、application.yml
spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/testdb?useSSL=false&serverTimezone=UTC username: root password:
4、打開Navicat for MySQL,在測試資料庫testdb中創建表user
CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(32) NOT NULL, `age` tinyint(4) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4;
5、實體類 User.java
package com.example.demo.entity; import javax.persistence.*; @Entity @Table(name = "user") public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; private String name; private Integer age; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } }
二、數據訪問層與業務層
數據訪問層繼承JpaRepository後會自動實現很多內置的方法,擁有基本的資料庫CRUD操作。
1、數據訪問層 UserRepository.java
package com.example.demo.repository; import com.example.demo.entity.User; import org.springframework.data.jpa.repository.JpaRepository; public interface UserRepository extends JpaRepository<User,Integer>{ }
2、業務層 UserService.java
package com.example.demo.service; import com.example.demo.entity.User; import com.example.demo.repository.UserRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import java.util.List; import java.util.Optional; @Service public class UserService { @Autowired UserRepository userRepository; public void save(User user) { userRepository.save(user); } public Page<User> getUserPage(Pageable pageable) { return userRepository.findAll(pageable); } public List<User> getUsers(){ List<User> users = userRepository.findAll(); return users; } public Optional<User> findById(Integer id) { return userRepository.findById(id); } public void deleteById(Integer id) { userRepository.deleteById(id); } }
3、控制器 UserController.java
package com.example.demo; import com.example.demo.entity.User; import com.example.demo.service.UserService; 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.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; import java.util.List; import java.util.Optional; @RestController public class UserController { @Resource UserService userService; @RequestMapping("/save") public String save(){ for(int i=1;i<=20;i++){ User user = new User(); user.setName("a" + i); user.setAge(i); userService.save(user); } return "添加成功"; } @RequestMapping("/getUserPage") public Page<User> getUserPage(Integer page, Integer size){ Sort sort = new Sort(Sort.Direction.ASC, "id"); Pageable pageable = PageRequest.of(page,size,sort); Page<User> users = userService.getUserPage(pageable); return users; } @RequestMapping("/getUsers") public List<User> getUsers(){ List<User> users = userService.getUsers(); return users; } @RequestMapping("/findById") public Optional<User> findById(Integer id){ Optional<User> user = userService.findById(id); return user; } @RequestMapping("/deleteById") public String deleteById(Integer id){ userService.deleteById(id); return "刪除成功"; } }
三、自定義數據存儲邏輯
繼承JpaRepository可以完成很多工作,但有時需要實現自定義數據存儲邏輯。
使用例子:
1、新建一個介面 UserRepositoryCustom.java
package com.example.demo.repository; import com.example.demo.entity.User; import java.util.List; public interface UserRepositoryCustom { List<User> myQuery(); }
2、新建介面 UserRepositoryCustom的實現類UserRepositoryCustomImpl.java
package com.example.demo.repository.impl; import com.example.demo.entity.User; import com.example.demo.repository.UserRepositoryCustom; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import javax.persistence.Query; import java.util.List; public class UserRepositoryImpl implements UserRepositoryCustom { @PersistenceContext private EntityManager em; public List<User> myQuery(){ //說明:下麵這個User不是資料庫表名,而是實體類名,並且區分大小寫 Query q = em.createQuery("from User"); return q.getResultList(); } }
3、修改原來的 UserRepository.java,同時繼承JpaRepository和UserRepositoryCustom
package com.example.demo.repository; import com.example.demo.entity.User; import org.springframework.data.jpa.repository.JpaRepository; public interface UserRepository extends JpaRepository<User,Integer>,UserRepositoryCustom { }
4、修改原來的 UserService.java,增加方法
public List<User> myQuery(){ return userRepository.myQuery(); }
5、修改原來的 UserController.java,代碼略。
四、方法名查詢
JpaRepository支持介面規範方法名查詢,即如果在介面中定義的查詢方法符合它的命名規則,就可以不用寫實現邏輯。
例如根據對象User的欄位name進行查詢,實現類似“from User where name=?”查詢,直接在介面中寫“List<User> name(String name);”,方法名也可寫findByName,Spring Data JPA框架在進行方法名解析時,會先把方法名多餘的首碼截取掉,比如find、findBy、read、readBy、get、getBy,然後對剩下部分進行解析。另外還可以根據特定關鍵字實現條件查詢,如下表所示:
關鍵字 | 例子 | 對應的SQL |
IsNotNull | findByAgeNotNull | ... where x.age not null |
Like | findByNameLike | ... where x.name like ?1 |
NotLike | findByNameNotLike | ... where x.name not like ?1 |
StartingWith | findByNameStartingWith | ... where x.name like ?1(parameter bound with appended %) |
EndingWith | findByNameEndingWith | ... where x.name like ?1(parameter bound with prepended %) |
Containing | findByNameContaining | ... where x.name like ?1(parameter bound wrapped in %) |
OrderBy | findByAgeOrderByName | ... where x.age = ?1 order by x.name desc |
Not | findByNameNot | ... where x.name <> ?1 |
In | findByAgeIn | ... where x.age in ?1 |
NotIn | findByAgeNotIn | ... where x.age not in ?1 |
True | findByActiveTrue | ... where x.avtive = true |
Flase | findByActiveFalse | ... where x.active = false |
And | findByNameAndAge | ... where x.name = ?1 and x.age = ?2 |
Or | findByNameOrAge | ... where x.name = ?1 or x.age = ?2 |
Between | findBtAgeBetween | ... where x.age between ?1 and ?2 |
LessThan | findByAgeLessThan | ... where x.age < ?1 |
GreaterThan | findByAgeGreaterThan | ... where x.age > ?1 |
After/Before | ... | ... |
IsNull | findByAgeIsNull | ... where x.age is null |
使用例子:
1、修改原來的 UserRepository.java,增加方法
@RequestMapping("/id") public List<User> id(Integer id){ List<User> users = userService.id(id); return users; } @RequestMapping("/name") public List<User> name(String name){ List<User> users = userService.name(name); return users; } @RequestMapping("/age") public List<User> age(Integer age){ List<User> users = userService.age(age); return users; } @RequestMapping("/findByIdAndName") public List<User> findByIdAndName(Integer id, String name){ List<User> users = userService.findByIdAndName(id, name); return users; } @RequestMapping("/findByAgeBetween") public List<User> findByAgeBetween(Integer startAge, Integer endAge){ List<User> users = userService.findByAgeBetween(startAge, endAge); return users; }
2、修改原來的 UserService.java,增加方法
public List<User> id(Integer id){ return userRepository.id(id); } public List<User> name(String name){ return userRepository.name(name); } public List<User> age(Integer age){ return userRepository.age(age); } public List<User> findByIdAndName(Integer id, String name){ return userRepository.findByIdAndName(id, name); } public List<User> findByAgeBetween(Integer startAge, Integer endAge){ return userRepository.findByAgeBetween(startAge, endAge); }
3、修改原來的 UserController.java,代碼略。
五、使用@Query註解
在方法中使用@Query註解,提供JPQL(Java Presistence Query Language)或SQL語句,同樣可以實現查詢功能。
使用例子:
1、修改原來的 UserRepository.java,增加方法
@Query("select u from User u where u.name = ?1") List<User> findUserName(String name); @Query(value = "select * from user u where u.name = ?1", nativeQuery = true) List<User> findNativeByName(String name);
2、修改原來的 UserService.java,增加方法
public List<User> findUserName(String name){ return userRepository.findUserName(name); } public List<User> findNativeByName(String name){ return userRepository.findNativeByName(name); }
3、修改原來的 UserController.java,代碼略。