【从零入门系列-3】Spring Boot 之 数据库操作
文章系列
前言
前一章简述了如何设计实现数据库实体类,本篇文章在此基础上进行开发,完成对该数据库表的常用操作,主要包括使用Spring Data JPA进行简单的增删改查和复杂查询操作。
Spring Data JPA是Spring提供的一套简化JPA开发的框架,按照约定好的【方法命名规则】写dao层接口,就可以在不写接口实现的情况下,实现对数据库的访问和操作,同时提供了很多除了CRUD之外的功能,如分页、排序、复杂查询等等,Spring Data JPA 可以理解为 JPA 规范的再次封装抽象,底层还是使用了 Hibernate 的 JPA 技术实现。通过引入Spring Data JPA后,我们可以基本不用写代码就能实现对数据库的增删改查操作。
此外,由于Spring Data JPA自带实现了很多内置的后台操作方法,因此在调用方法时必须根据其规范使用,深刻理解规范和约定。
表的基本操作实现(CRUD)
在这里,先介绍一下JpaRepository,这是类型为interface的一组接口规范,是基于JPA的Repository接口,能够极大地减少访问数据库的代码编写,是实现Spring Data JPA技术访问数据库的关键接口。
package com.arbboter.demolibrary.Dao;
import com.arbboter.demolibrary.Domain.Book;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface BookJpaRepository extends JpaRepository<Book, Integer> {
}
@Repository持久层组件,用于标注数据访问组件,即DAO组件,此时配合上上一篇文章中的JPA配置,我们就可以进行增删改查啦,不用添加任何其他代码,因为JpaRepository已经帮我们实现好了。
打开框架自动生成的测试代码文件DemoLibraryApplicationTests.java编写测试用例,测试增删改查效果,测试代码如下:
@RunWith(SpringRunner.class)
@SpringBootTest
public class DemoLibraryApplicationTests {
@Autowired
private BookJpaRepository bookJpaRepository;
@Test
public void contextLoads() {
Book book = new Book();
book.setName("Spring Boot 入门学习实践");
book.setAuthor("arbboter");
book.setImage("https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=2656353677,2997395625&fm=26&gp=0.jpg");
bookJpaRepository.save(book);
System.out.println("保存数据成功:" + book);
book = bookJpaRepository.findById(book.getId()).get();
System.out.println("新增后根据ID查询结果:" + book);
book.setName("Spring Boot 入门学习实践(修改版)");
bookJpaRepository.save(book);
System.out.println("修改后根据ID查询结果:" + book);
bookJpaRepository.deleteById(book.getId());
}
}
注意在测试代码用需要对属性bookJpaRepository使用@Autowired自动注入实现初始化,@Autowired注解,它可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作。
[外链图片转存失败(img-sGwiAwwL-1566186700190)(https://raw.githubusercontent.com/arbboter/resource/master/segmentfault/image/SpringBoot/20190514-%E6%95%B0%E6%8D%AE%E5%BA%93%E6%93%8D%E4%BD%9C/1557817269112.png)]
通过测试结果我们可以看到,程序已经能够对表数据进行增删改查,且我们通过删除SQL可以观察到,获取生成记录ID的SQL语句为:
Hibernate: select next_val as id_val from hibernate_sequence with (updlock, holdlock, rowlock)
Hibernate: update hibernate_sequence set next_val= ? where next_val=?
因此可推断出,JpaRepository对默认的自增ID均使用表hibernate_sequence作为ID生成器,所有默认的ID表公用此ID生成器。
通过上述例子,我们可以发现,虽然我们没有写任何一条SQL语句,但是程序已经可以正常操作数据库了,这对苦逼的C++程序员手写SQL来说真是不要说太幸福哈。不过上述示例也存在一些问题,数据查询均是通过ID操作的,但是实际使用中,数据查询还需要根据其他条件,比如书名或作者,是不是需要手写SQL实现?答案是否定的,JpaRepository支持接口规范方法名查询,意思是如果在接口中定义的查询方法符合它的命名规则,就可以不用写实现,框架自动提供实现的方法,只需要声明无需自己实现即可使用。
JpaRepository的规范方法名查询
在我们实现的接口中,可以只定义查询方法,如果是符合规范的,可以不用写实现,就可以直接使用。
JpaRepository会对方法名进行校验,不符合规范会报错,除非添加@Query注解。
在本示例中,我们希望通过书名和作者的常用场景提供查询方案,可按下述实现:
@Repository
public interface BookJpaRepository extends JpaRepository<Book, Integer> {
List<Book> findByName(String name);
List<Book> findByNameLike(String name);
List<Book> findByNameAndAuthor(String name, String author);
List<Book> findByNameOrAuthor(String name, String author);
List<Book> findByAuthorIn(Collection authors);
}
上述代码通,我们实现了模糊、精准、And和Or以及In的查询定义,都是根据JPA的命名规范定义方法,此时我们不用自己去实现方法,直接可以调用。
测试代码如下: