SpringBoot JPA + H2增刪改查示例
下面的例子是基於SpringBoot JPA以及H2資料庫來實現的,下面就開始搭建專案吧。
首先看下專案的整體結構:
具體操作步驟:
開啟IDEA,建立一個新的Spring Initializr專案,填寫好groupID等資訊,依賴勾選web和H2,一路next:
pom.xml關鍵依賴:
<dependencies> <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>com.h2database</groupId> <artifactId>h2</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
新建controller、domain、service包,建立JPA實體類User:
package com.example.demo.domain; import org.springframework.format.annotation.DateTimeFormat; import java.io.Serializable; import java.time.LocalDate; import javax.persistence.*; /** * @Description: SpringBoot自動配置會探測到我們使用了H2資料庫,它會根據實體類自動建立資料表 * @author: Alan * @Date: 2018/11/30 22:33 */ @Entity @Table(name = "user") public class User implements Serializable{ private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id;//主鍵 @Column(nullable = false) private String firstName;//名 @Column(nullable = false) private String lastName;//姓 @Column(nullable = false) private String idCard;//身份證 @Column(nullable = false) @DateTimeFormat(pattern = "yyyy-MM-dd") private LocalDate dateOfBirth;//出生日期 public User() { } public User(Long id, String firstName, String lastName, String idCard, LocalDate dateOfBirth) { this.id = id; this.firstName = firstName; this.lastName = lastName; this.idCard = idCard; this.dateOfBirth = dateOfBirth; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public String getIdCard() { return idCard; } public void setIdCard(String idCard) { this.idCard = idCard; } public LocalDate getDateOfBirth() { return dateOfBirth; } public void setDateOfBirth(LocalDate dateOfBirth) { this.dateOfBirth = dateOfBirth; } @Override public String toString() { return "User{" + "id=" + id + ", firstName='" + firstName + '\'' + ", lastName='" + lastName + '\'' + ", idCard='" + idCard + '\'' + ", dateOfBirth=" + dateOfBirth + '}'; } }
說明:
@Entity: 指明瞭這是一個entity
@Table:指定生成的表名
@Id: 標記該entity的主鍵
@GeneratedValue: 提供主鍵的生成策略
編寫配置檔案和資料生成語句:
application.properties:
#啟用開發環境的的配置檔案
spring.profiles.active=dev
application-dev.properties:
#埠設定
server.port=8080
#開啟日誌記錄(日誌檔案會在10Mb大小的時候被截斷,產生新的日誌檔案)
logging.file=logs/my.log
spring.h2.console.enabled=true
spring.jpa.open-in-view=true
spring.data.jpa.repositories.bootstrap-mode=default
logging.level.org.hibernate.SQL=debug
import.sql:
INSERT INTO USER (FIRST_NAME, LAST_NAME, ID_CARD, DATE_OF_BIRTH) values ('Steven1', 'Jobs1','630121199206081105', '1998-07-13');
INSERT INTO USER (FIRST_NAME, LAST_NAME, ID_CARD, DATE_OF_BIRTH) values ('Steven2', 'Jobs2','510181199412105672', '1992-07-13');
INSERT INTO USER (FIRST_NAME, LAST_NAME, ID_CARD, DATE_OF_BIRTH) values ('Steven3', 'Jobs','610702199009261457', '1991-07-13');
INSERT INTO USER (FIRST_NAME, LAST_NAME, ID_CARD, DATE_OF_BIRTH) values ('Steven4', 'Jobs','430426198801075355', '1994-07-13');
INSERT INTO USER (FIRST_NAME, LAST_NAME, ID_CARD, DATE_OF_BIRTH) values ('Steven5', 'Michael','420117199502232760', '1998-07-13');
INSERT INTO USER (FIRST_NAME, LAST_NAME, ID_CARD, DATE_OF_BIRTH) values ('Steven6', 'Michael','130203199404122670', '1998-07-13');
INSERT INTO USER (FIRST_NAME, LAST_NAME, ID_CARD, DATE_OF_BIRTH) values ('Steven7', 'Michael','430703197612014630', '1998-07-13');
INSERT INTO USER (FIRST_NAME, LAST_NAME, ID_CARD, DATE_OF_BIRTH) values ('Steven8', 'Michael','350124197805280264', '1998-07-13');
INSERT INTO USER (FIRST_NAME, LAST_NAME, ID_CARD, DATE_OF_BIRTH) values ('Steven9', 'Michael','500230197205314628', '1998-08-19');
JpaRepository
該介面繼承了PagingAndSortingRepository和QueryByExampleExecutor介面,相比CrudRepository介面多了分頁和排序功能,因此JpaRepository功能更加全面,如果你不需要分頁和排序功能,使用CrudRepository即可。這裡我們使用JpaRepository,其定義如下:
@NoRepositoryBean public interface JpaRepository<T, ID> extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> {
UserRepository(相當於DAO層,定義了增刪改查的方法):
package com.example.demo.service; import com.example.demo.domain.User; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; import java.time.LocalDate; import java.util.List; /** * @Description: * @author: Alan * @Date: 2018/11/30 22:54 */ public interface UserRepository extends JpaRepository<User, Long>{ /******************************create***************************************/ @Override User save(User user); /******************************read***************************************/ /** * Using sort * @param lastName * @param sort * @return */ @Query("select u from User u where u.lastName like ?1%") List<User> findByAndSort(String lastName, Sort sort); /** * Query creation * this translates into the following query: * select u from User u where u.idCard = ?1 */ User findByIdCard(String idCard); /** * Native Queries * The @Query annotation allows for running native queries by setting the nativeQuery flag to true * @param idCard * @return */ @Query(value = "select * from user where ID_CARD = ?1", nativeQuery = true) User findByIdCard2(String idCard); /** * Using @Query * @param idCard * @return */ @Query("select u from User u where u.idCard = ?1") User findByIdCard3(String idCard); /** * Declare native count queries for pagination at the query method by using @Query * @param lastName * @param pageable * @return */ @Query(value = "SELECT * FROM User WHERE LAST_NAME = ?1", countQuery = "SELECT count(*) FROM User WHERE LAST_NAME = ?1", nativeQuery = true) Page<User> findByLastNameWithPageable(String lastName, Pageable pageable); /** * Using Named Parameters * @param firstName * @param lastName * @return */ @Query("select u from User u where u.firstName = :firstName or u.lastName = :lastName") List<User> findByFirstNameOrLastName(@Param("firstName") String firstName, @Param("lastName") String lastName); /** * findByDateOfBirth * @param date * @return */ List<User> findByDateOfBirth(@Param("date") LocalDate date); /** * find all users * @param sort * @return */ @Override List<User> findAll(Sort sort); /****************************update*****************************************/ /** * update a usr by Modifying Queries * @param firstName * @param idCard * @return */ @Modifying @Query("update User u set u.firstName = ?1 where u.idCard = ?2") int updateUser(String firstName, String idCard); /****************************delete*****************************************/ /** * delete a user by idCard * @param idCard */ void deleteByIdCard(String idCard); /** * Using a derived delete query * @param idCard */ @Modifying @Query("delete from User u where u.idCard = ?1") void deleteByIdCard2(String idCard); /** * delete a user by id * @param id */ @Override @Modifying @Query(value = "delete from user where id = ?1", nativeQuery = true) void deleteById(Long id); }
UserService:
package com.example.demo.service; import com.example.demo.domain.User; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.data.repository.query.Param; import java.time.LocalDate; import java.util.List; /** * @Description: * @author: Alan * @Date: 2018/12/1 11:44 */ public interface UserService { /****************************create*****************************************/ User save(User user); /****************************read*****************************************/ List<User> findByAndSort(String lastName, Sort sort); User findByIdCard(String idCard); User findByIdCard2(String idCard); User findByIdCard3(String idCard); Page<User> findByLastNameWithPageable(String lastName, Pageable pageable); List<User> findByFirstNameOrLastName(String firstName, String lastName); List<User> findByDateOfBirth(@Param("date") LocalDate date); List<User> findAll(Sort sort); /*****************************update****************************************/ int updateUser(String firstName, String idCard); /*****************************delete****************************************/ void deleteByIdCard(String idCard); void deleteByIdCard2(String idCard); void deleteById(Long id); }
UserServiceImpl:(UserService的實現類)
package com.example.demo.service; import com.example.demo.domain.User; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; import java.time.LocalDate; import java.util.List; /** * @Description: * @author: Alan * @Date: 2018/12/1 11:44 */ @Component("userService") @Transactional public class UserServiceImpl implements UserService { private UserRepository userRepository; UserServiceImpl(UserRepository userRepository) { this.userRepository = userRepository; } /**************************create********************************/ @Override public User save(User user) { return userRepository.save(user); } /**************************read********************************/ @Override public List<User> findByAndSort(String lastName, Sort sort) { return userRepository.findByAndSort(lastName, sort); } @Override public User findByIdCard(String idCard) { return userRepository.findByIdCard(idCard); } @Override public User findByIdCard2(String idCard) { return userRepository.findByIdCard2(idCard); } @Override public User findByIdCard3(String idCard) { return userRepository.findByIdCard3(idCard); } @Override public Page<User> findByLastNameWithPageable(String lastName, Pageable pageable) { return userRepository.findByLastNameWithPageable(lastName, pageable); } @Override public List<User> findByFirstNameOrLastName(String firstName, String lastName) { return userRepository.findByFirstNameOrLastName(firstName, lastName); } @Override public List<User> findByDateOfBirth(@Param("date") LocalDate date) { return userRepository.findByDateOfBirth(date); } @Override public List<User> findAll(Sort sort) { return userRepository.findAll(sort); } /**************************update********************************/ @Override public int updateUser(String firstName, String idCard) { return userRepository.updateUser(firstName, idCard); } /**************************delete********************************/ @Override public void deleteByIdCard(String idCard) { userRepository.deleteByIdCard(idCard); } @Override public void deleteByIdCard2(String idCard) { userRepository.deleteByIdCard2(idCard); } @Override public void deleteById(Long id) { userRepository.deleteById(id); } }
UserController:
package com.example.demo.controller; import com.example.demo.domain.User; import com.example.demo.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.format.annotation.DateTimeFormat; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import java.time.LocalDate; import java.util.List; /** * @Description: * POST - Create a new resource * GET - Read a resource * PUT - Update an existing resource * DELETE - Delete a resource * Tomcat by default is not enabled for HTTP PUT command. * 只要讓位址列的引數可以傳入函式裡面,就能執行修改、新增、刪除操作,method用RequestMethod.GET即可 * 用PUT、POST、DELETE會報405錯誤,因為輸入到位址列預設使用GET方法 * 註解@DateTimeFormat(iso = DateTimeFormat.ISO.DATE)主要是解決請求日期無法轉成LocalDate的問題 * @author: Alan * @Date: 2018/12/1 10:38 */ @RestController public class UserController { @Autowired private UserService userService; /*****************************create*************************************/ @RequestMapping(value = "/saveUser/{firstName}/{lastName}/{idCard}/{date}",method = RequestMethod.GET) @Transactional public User saveUser(@PathVariable String firstName, @PathVariable String lastName, @PathVariable String idCard, @PathVariable @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate date) { User user = new User();//Id是自增長的,不需要傳 user.setFirstName(firstName); user.setLastName(lastName); user.setIdCard(idCard); user.setDateOfBirth(date); return userService.save(user); } /*****************************Read***** ********************************/ @RequestMapping(value = "/findByAndSort/{lastName}", method = RequestMethod.GET) public List<User> findByAndSort(@PathVariable String lastName) { Sort sort = new Sort(Sort.Direction.DESC, "firstName"); return userService.findByAndSort(lastName, sort); } @RequestMapping(value = "/findByIdCard/{idCard}", method = RequestMethod.GET) @Transactional(readOnly = true) public User findByIdCard(@PathVariable(name = "idCard") String idCard) { return userService.findByIdCard(idCard); } @RequestMapping(value = "/findByIdCard2/{idCard}", method = RequestMethod.GET) @Transactional(readOnly = true) public User findByIdCard2(@PathVariable(name = "idCard") String idCard) { return userService.findByIdCard2(idCard); } @RequestMapping(value = "/findByIdCard3/{idCard}", method = RequestMethod.GET) @Transactional(readOnly = true) public User findByIdCard3(@PathVariable(name = "idCard") String idCard) { return userService.findByIdCard3(idCard); } @RequestMapping(value = "/findByLastNameWithPageable/{lastName}", method = RequestMethod.GET) @Transactional(readOnly = true) public Page<User> findByLastNameWithPageable(@PathVariable String lastName) { Sort sort = new Sort(Sort.Direction.DESC, "id"); Pageable pageable = new PageRequest(5,2,sort); return userService.findByLastNameWithPageable(lastName, pageable); } @RequestMapping(value = "/findByFirstNameOrLastName/{firstName}/{lastName}", method = RequestMethod.GET) public List<User> findByFirstNameOrLastName(@PathVariable String firstName, @PathVariable String lastName) { return userService.findByFirstNameOrLastName(firstName, lastName); } @RequestMapping(value = "/findByDateOfBirth/{date}", method = RequestMethod.GET) public List<User> findByDateOfBirth(@PathVariable(name = "date") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate date) { return userService.findByDateOfBirth(date); } @RequestMapping(value = "/findAll", method = RequestMethod.GET) public List<User> findAll() { Sort sort = new Sort(Sort.Direction.ASC, "id"); return userService.findAll(sort); } /*****************************update*************************************/ @RequestMapping(value = "/updateUser/{firstName}/{idCard}", method = RequestMethod.GET) public int updateUser(@PathVariable String firstName, @PathVariable String idCard) { return userService.updateUser(firstName, idCard); } /*****************************delete*************************************/ @RequestMapping(value = "/deleteByIdCard/{idCard}", method = RequestMethod.GET) @Transactional public String deleteByIdCard(@PathVariable String idCard) { userService.deleteByIdCard(idCard); return "SUCCESS"; } @RequestMapping(value = "/deleteByIdCard2/{idCard}", method = RequestMethod.GET) @Transactional public String deleteByIdCard2(@PathVariable String idCard) { userService.deleteByIdCard2(idCard); return "SUCCESS"; } @RequestMapping(value = "/deleteById/{id}", method = RequestMethod.GET) @Transactional public String deleteById(@PathVariable Long id) { userService.deleteById(id); return "SUCCESS"; } }
SpringBoot主類移植com包下,這樣其他類才能被掃描到:
啟動SpringBoot專案:點選選單欄的執行按鈕或者執行main方法
此時控制檯可以看到建立表和插入sql語句的日誌:
查詢所有使用者:
瀏覽器位址列輸入:http://localhost:8080/findAll
可以看到所有的記錄:
[ { "id": 1, "firstName": "Steven1", "lastName": "Jobs1", "idCard": "630121199206081105", "dateOfBirth": "1998-07-13" }, { "id": 2, "firstName": "Steven2", "lastName": "Jobs2", "idCard": "510181199412105672", "dateOfBirth": "1992-07-13" }, { "id": 3, "firstName": "Steven3", "lastName": "Jobs", "idCard": "610702199009261457", "dateOfBirth": "1991-07-13" }, { "id": 4, "firstName": "Steven4", "lastName": "Jobs", "idCard": "430426198801075355", "dateOfBirth": "1994-07-13" }, { "id": 5, "firstName": "Steven5", "lastName": "Michael", "idCard": "420117199502232760", "dateOfBirth": "1998-07-13" }, { "id": 6, "firstName": "Steven6", "lastName": "Michael", "idCard": "130203199404122670", "dateOfBirth": "1998-07-13" }, { "id": 7, "firstName": "Steven7", "lastName": "Michael", "idCard": "430703197612014630", "dateOfBirth": "1998-07-13" }, { "id": 8, "firstName": "Steven8", "lastName": "Michael", "idCard": "350124197805280264", "dateOfBirth": "1998-07-13" }, { "id": 9, "firstName": "Steven9", "lastName": "Michael", "idCard": "500230197205314628", "dateOfBirth": "1998-08-19" } ]View Code
新增一個user:
http://localhost:8080/saveUser/java/springboot/330987193709193205/1937-09-19
頁面會輸出新插入的user:
此時再findAll,會發現多了新插入的id為10的記錄:
[ { "id": 1, "firstName": "Steven1", "lastName": "Jobs1", "idCard": "630121199206081105", "dateOfBirth": "1998-07-13" }, { "id": 2, "firstName": "Steven2", "lastName": "Jobs2", "idCard": "510181199412105672", "dateOfBirth": "1992-07-13" }, { "id": 3, "firstName": "Steven3", "lastName": "Jobs", "idCard": "610702199009261457", "dateOfBirth": "1991-07-13" }, { "id": 4, "firstName": "Steven4", "lastName": "Jobs", "idCard": "430426198801075355", "dateOfBirth": "1994-07-13" }, { "id": 5, "firstName": "Steven5", "lastName": "Michael", "idCard": "420117199502232760", "dateOfBirth": "1998-07-13" }, { "id": 6, "firstName": "Steven6", "lastName": "Michael", "idCard": "130203199404122670", "dateOfBirth": "1998-07-13" }, { "id": 7, "firstName": "Steven7", "lastName": "Michael", "idCard": "430703197612014630", "dateOfBirth": "1998-07-13" }, { "id": 8, "firstName": "Steven8", "lastName": "Michael", "idCard": "350124197805280264", "dateOfBirth": "1998-07-13" }, { "id": 9, "firstName": "Steven9", "lastName": "Michael", "idCard": "500230197205314628", "dateOfBirth": "1998-08-19" }, { "id": 10, "firstName": "java", "lastName": "springboot", "idCard": "330987193709193205", "dateOfBirth": "1937-09-19" } ]View Code
更新一個user:
將剛插入的id為10的使用者的firstName修改成java666:
http://localhost:8080/updateUser/java666/330987193709193205
頁面返回1,表示修改成功。
輸入:http://localhost:8080/findByIdCard/330987193709193205
可以看到身份證為330987193709193205的firstName確實被修改了:
刪除一個user:
輸入:http://localhost:8080/deleteById/1
頁面顯示:
這樣id為1的user就被刪除了,再輸入http://localhost:8080/findAll,id為1的user已不存在:
[ { "id": 2, "firstName": "Steven2", "lastName": "Jobs2", "idCard": "510181199412105672", "dateOfBirth": "1992-07-13" }, { "id": 3, "firstName": "Steven3", "lastName": "Jobs", "idCard": "610702199009261457", "dateOfBirth": "1991-07-13" }, { "id": 4, "firstName": "Steven4", "lastName": "Jobs", "idCard": "430426198801075355", "dateOfBirth": "1994-07-13" }, { "id": 5, "firstName": "Steven5", "lastName": "Michael", "idCard": "420117199502232760", "dateOfBirth": "1998-07-13" }, { "id": 6, "firstName": "Steven6", "lastName": "Michael", "idCard": "130203199404122670", "dateOfBirth": "1998-07-13" }, { "id": 7, "firstName": "Steven7", "lastName": "Michael", "idCard": "430703197612014630", "dateOfBirth": "1998-07-13" }, { "id": 8, "firstName": "Steven8", "lastName": "Michael", "idCard": "350124197805280264", "dateOfBirth": "1998-07-13" }, { "id": 9, "firstName": "Steven9", "lastName": "Michael", "idCard": "500230197205314628", "dateOfBirth": "1998-08-19" }, { "id": 10, "firstName": "java666", "lastName": "springboot", "idCard": "330987193709193205", "dateOfBirth": "1937-09-19" } ]View Code
分頁查詢:
輸入:http://localhost:8080/findByLastNameWithPageable/Michale
頁面顯示:lastName為Michale的共有5條記錄,page設定:每頁2個,共5頁
輸出結果與程式一致:
附錄:
註解說明:
@Entity: 指明瞭這是一個entity
@Table:指定生成的表名
@Id: 標記該entity的主鍵
@GeneratedValue: 提供主鍵的生成策略
@Component:宣告為一個元件
@Transactional:宣告為事務
@Autowired:自動注入
@Query:查詢操作
@Modifying:修改操作
@PathVariable:將URL中的請求引數繫結到控制器的入參上
@Override:重寫
@Param:宣告屬性
語句說明:
1、使用SpEL表示式
@Query("select u from User u where u.idCard = ?1")
User findByIdCard3(String idCard);
2、使用原生SQL(需新增nativeQuery=true)
@Query(value = "select * from user where ID_CARD = ?1", nativeQuery = true) User findByIdCard2(String idCard);
3、使用屬性表示式(Property Expressions)
User findByIdCard(String idCard);
(注:上面的方法,JPA會轉換成等價的查詢語句:select * from User u where u.idCard = ?1)
官方文件上的JPA標準API:
Keyword | Sample | JPQL snippet |
---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4、使用命名引數(:引數名[email protected])
@Query("select u from User u where u.firstName = :firstName or u.lastName = :lastName") List<User> findByFirstNameOrLastName(@Param("firstName") String firstName, @Param("lastName") String lastName);
H2資料庫控制檯:
位址列輸入http://localhost:8080/h2-console/進入H2控制檯
程式執行流程圖(呼叫關係):
以上就是SpringBoot JPA增刪改查的簡單應用,當然你也可以將資料庫換成mysql。
官方參考文件:https://docs.spring.io/spring-data/jpa/docs/current/reference/html/