SpringBoot 学习笔记_整合持久层——Spring Boot JPA
声明:
本次学习参考 《SpringBoot + Vue 开发实战》 · 王松(著) 一书。
本文的目的是记录我学习的过程和遇到的一些问题以及解决办法,其内容主要来源于原书。
如有侵权,请联系我删除
SpringBoot 整合持久层开发
整合 Spring Boot JPA
JPA
是一种ORM
规范。Spring Data
是Spring
的一个子项目,致力于简化数据的访问,通过规范的方法名称来分析开发者的意图,进而减少数据库访问层的代码。
-
创建数据库(表会根据实体类自动创建)
-
创建 SpringBoot 项目,添加依赖
<!-- 添加 Spring Boot JPA 依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.9</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency>
-
数据库配置(
application.properties
)### 数据库基本配置 ### spring.datasource.type=com.alibaba.druid.pool.DruidDataSource #spring.datasource.url=jdbc:mysql:///chapter05?serverTimezone=GMT spring.datasource.url=jdbc:mysql://localhost:3306/chapter05?serverTimezone=GMT spring.datasource.username=root spring.datasource.password=root #### 数据库配置 —— JPA 相关 #### # 表示是否在控制台打印 JPA 打印过程生成的 SQL spring.jpa.show-sql=true # 表示 JPA 对应的数据库是 MySQL spring.jpa.database=mysql # 表示在项目启动时根据实体类更新数据库中的表(可选:create、create-drop、validate、no) spring.jpa.hibernate.ddl-auto=update # 表示使用的数据库方言是 MySQL57Dialect spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL57Dialect
-
创建实体类
// @Entity 表示该类是一个实体类。在项目启动时会根据该类自动生成一个数据表,表名称即 @Entity 的 name 值,如果不配置,默认为类名。 @Entity(name = "t_book") public class BookJPA { // @Id 表示该实体类的主键。所有实体类都要有主键 @Id // @GeneratedValue 表示主键自动生成,strategy 表示生成策略 @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; // @Column 表示表中字段名称和实体类中属性名称的映射。如果不配置,默认生成字段名就是属性名。nullable 表示是否可为空 @Column(name = "book_name", nullable = false) private String name; private String author; private Float price; // @Transient 表示生成数据表时,忽略该字段 @Transient private String description; }
-
创建数据库访问层
/** * 整合 JPA 的 BookDao * * 自定义 Dao 继承 JpaRepository。JpaRepository 中提供了一些基本的数据操作方法,有增删改查、分页查询、排序查询等。 */ public interface BookJPADao extends JpaRepository<BookJPA, Integer> { //Spring Data JPA 支持既定规范命名查询(方法名复合既定规范,自动生成对应 SQL) /** * keyWords 示例 对应 SQL * And findByNameAndAge where name=? and age=? * Or findByNameOrAge where name=? or age=? * Is/Equals findByAgeIs/findByAgeEquals where age=? * Between findByAgeBetween where age between ? and ? * LessThan/Before findByAgeLessThan/findByAgeBefore where age < ? * LessThanEquals findByAgeLessThanEquals where age <= ? * GreaterThan/After findByAgeGreaterThan/findByAgeAfter where age > ? * GreaterThanEquals findByAgeGreaterThanEquals where age >= ? * IsNull findByNameIsNull where name is null * IsNotNull/NotNull findByNameNotNull where name is not null * Not findByNameNot where name <> ? * In findByAgeIn where age in(?) * NotIn findByAgeNotIn where age not in(?) * NotLike findByNameNotLike where name not like ? * StartingWith findByNameStartingWith where name like '?%' * EndingWith findByNameEndingWith where name like '%?' * Containing/Contains findByNameContains where name like '%?%' * True findByEnabledTrue where enabled = true * False findByEnabledFalse where enabled = false * IgnoreCase findByNameIgnoreCase where UPPER(name)=UPPER(?) * * OrderBy findByAgeGreaterThanOrderByIdDesc where age > ? order by id desc */ // 查询作者名以某字符开头的所有书 List<BookJPA> getBooksByAuthorStartingWith(String author); // 查询价格大于某值得所有书 List<BookJPA> getBooksByPriceGreaterThan(Float price); // Spring Data JPA 支持原生 SQL。 nativeQuery = true 表示使用原生 SQL 语句 @Query(value = "select * from t_book where id=(select max(id) from t_book)", nativeQuery = true) BookJPA getMaxIdBook(); // Spring Data JPA 支持默认的 JPQL。JPQL 是一种可移植的面向对象表达式语言。 // 通过类名和属性(并非数据库列名)来进行参数绑定。参数需要使用 @Param 绑定。 @Query("select b from t_book b where b.id > :id and b.author=:author") List<BookJPA> getBookByIdAndAuthor(@Param("author") String author, @Param("id") Integer id); // Spring Data JPA 支持默认的 JPQL。 // 通过占位符进行参数传递。参数顺序有严格要求。 @Query("select b from t_book b where b.id < ?2 and b.name like %?1%") List<BookJPA> getBooksByIdAndNameAnd(String name, Integer id); // 如果方法涉及修改操作,需要添加 @Modifying 注解并添加事务 }
-
创建 Service 和 Controller
/** * 整合 Spring Data JPA 的 Service 层 */ @Service public class BookJPAService { @Autowired BookJPADao bookDao; public void addBook(BookJPA book){ bookDao.save(book); } public Page<BookJPA> getBookByPage(Pageable pageable){ return bookDao.findAll(pageable); } public List<BookJPA> getBooksByAuthorStartingWith(String author){ return bookDao.getBooksByAuthorStartingWith(author); } public List<BookJPA> getBooksByPriceGreaterThan(Float price){ return bookDao.getBooksByPriceGreaterThan(price); } public BookJPA getMaxIdBook(){ return bookDao.getMaxIdBook(); } public List<BookJPA> getBookByIdAuthor(String author, Integer id){ return bookDao.getBookByIdAndAuthor(author, id); } public List<BookJPA> getBooksByIdAndName(String name, Integer id){ return bookDao.getBooksByIdAndName(name, id); } }
/** * 整个 Spring Data JPA 的 Controller 层 */ @RestController public class BookJPAController { @Autowired BookJPAService bookService; @GetMapping("/jpa/findAll") public void findAll(){ PageRequest pageable = PageRequest.of(2, 3); Page<BookJPA> page = bookService.getBookByPage(pageable); System.out.println(" 总页数: " + page.getTotalPages()); System.out.println(" 总记录: " + page.getTotalElements()); System.out.println(" 查询结果: " + page.getContent()); System.out.println(" 当前页数: " + page.getNumber() + 1); System.out.println(" 当前页记录数: " + page.getNumberOfElements()); System.out.println(" 每页记录数: " + page.getSize()); } @GetMapping("/jpa/search") public void search(){ List<BookJPA> bs1 = bookService.getBookByIdAndAuthor("吴承恩", 1); List<BookJPA> bs2 = bookService.getBooksByAuthorStartingWith("施"); List<BookJPA> bs3 = bookService.getBooksByPriceGreaterThan(0.1F); BookJPA book = bookService.getMaxIdBook(); System.out.println(bs1); System.out.println(bs2); System.out.println(bs3); System.out.println(book); } @GetMapping("/jpa/save") public void save(){ BookJPA book = new BookJPA(); book.setAuthor("卧龙"); book.setName("卧龙锅巴"); book.setPrice(3.5F); bookService.addBook(book); } }