Spring Boot训练营:Spring Boot + Spring Data JDBC版
这是Spring Boot营系列的课程,主题是Spring Boot + Spring Data JDBC。
这次的目的
使用Spring Boot应用程序,使用Spring Data JDBC进行数据库访问。
这次要使用的库
-
- spring-boot-starter:2.2.0.M4
-
- spring-boot-starter-data-jdbc:2.2.0.M4
-
- spring-boot-starter-test:2.2.0.M4
-
- h2:1.4.199
- lombok:1.18.8
通过使用Spring Initializr创建项目,可以解决以下步骤中的一些问题。
数据库访问
在进行Spring Data JDBC的实现之前,首先需要进行数据库访问的配置。
数据库访问的定义
在Spring Boot中,它会自动帮我们定义一些访问数据库的Bean,比如DataSource等。默认情况下,它会访问内存中的H2数据库,所以我们需要添加h2的依赖关系。
pom.xml 可以被翻译为 “项目对象模型”,是一个用于管理和构建Java项目的XML文件。
<dependencies>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
注意事项。
如果在Spring Boot的配置文件中更改驱动程序和连接目标,则可以访问另一个数据库。(需要添加相应依赖的驱动程序)src/main/resources/application.yml
spring:
datasource:
driver-class-name: org.postgresql.Driver
url: jdbc:postgresql://localhost:5432/testdb
username: postgres
password: postgres
如果在src/main/resources的直接子目录下创建以下的SQL文件,应用在启动时也可以自动进行数据库的初始化。默认情况下,被认为有效的SQL文件如下。
-
- schema.sql
-
- schema-${platform}.sql
-
- data.sql
- data-${platform}.sql
尽管看起来一样,但是在schema.sql文件中定义DDL,在data.sql文件中定义DML。
注意。
${platform}可以使用spring.datasource.platform属性进行指定。
在单元测试时,可以使用H2,在集成测试时,可以使用Postgresql,这样可以灵活切换。
这次我们将创建schema.sql并创建表格。
主要资源/模式.sql
create table if not exists todo (
todo_id identity,
todo_title varchar(30),
finished boolean,
created_at timestamp
);
SpringBoot引导数据JDBC
这是一个用于使用Spring Boot和Spring Data JDBC的起始器。
详细信息可以参考开发者@kazuki43zoo的文章,更推荐去看一下w。
通过使用Spring Boot的自动配置机制,可以自动为Spring Boot应用程序定义使用Spring Data JDBC的Bean。开发者只需将spring-boot-starter-data-jdbc添加到依赖关系中即可。
Pom.xml文件。
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
</dependencies>
src/main/java/*/Application.java的中文本地化的释义如下:
src/main/java/*/Application.java的主要类文件。
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
主类未做任何更改,仍然保持Spring Boot应用程序的默认设置。
首先,Spring Data JDBC 是什么?
提到Spring的数据库访问,我们通常会想到Spring Data的JdbcTemplate和Spring Data JPA,而Spring Data JDBC则类似于将这两者混合起来的一种方法。
使用类似Spring Data JPA的语法定义Repository后,将利用JdbcTemplate(NamedParameterJdbcTemplate)执行SQL语句。
以下是Spring Data JDBC所支持的主要功能:
-
- CRUDを実現するシンプルなAPIを提供する
@Queryでカスタムクエリを定義できる
SQL実行前後などのイベントをインターセプトする
Spring Data JDBCを経由してMyBatisのSQLを実行できる -> 別エントリで!
これらをAuto-Configする
与Spring Data JPA相比,以下是一些明显的区别:
-
- カスタムクエリはJPQLではなくSQL(NamedParameterJdbcTemplateの文法)で定義する
- Lazy Fetch(遅延読み込み)のような機能がない
领域类
在用于映射数据库数据的领域类上添加@ID以识别主键。为了省略Getter和Setter的实现,以下使用了Lombok的@Data。
src/main/java/*/domain/Todo.java 的中文释义是什么?
@Data
public class Todo {
@Id
private String todoId;
private String todoTitle;
private boolean finished;
private LocalDateTime createdAt;
}
注意:
如果表名和Domain类名不相同,只需要在类上添加@Table(“表名”)即可。
代码库接口
Spring的Repository接口继承了Spring Data的CrudRepository接口。
src/main/java/*/repository/TodoRepository.java:
src/main/java/*/repository/TodoRepository.java的位置
// (1)
public interface TodoRepository extends CrudRepository<Todo, String> {
// (2)
// (3)
@Query("SELECT COUNT(*) FROM todo WHERE finished = :finished")
long countByFinished(@Param("finished") boolean finished);
}
(1) 仓库接口继承了CrudRepository。泛型为<领域类的类型,ID的类型>。
当继承CrudRepository时,将自动获得CRUD支持的默认方法(查询)。通过查看CrudRepository的JavaDoc即可了解提供的方法。
如果要实现自定义查询,可以在方法上添加@Query注解来编写SQL语句。使用@Param注解加在参数上,参数的值将被嵌入到SQL语句中的:参数名位置。这样非常容易理解吧。
注意:
在更新类的自定义查询中,需要使用@Query + @Modifying标注。
多行的SQL.
在上面,尽管SQL在一行中提到,但是由于可读性差,建议将其分成多行进行编写。
可以采用以下方式进行字符串连接。
@Query("SELECT"
+ " COUNT(*)"
+ " FROM todo"
+ " WHERE"
+ " finished = :finished")
long countByFinished(@Param("finished") boolean finished);
不使用CRUD的默认方法时。
如果表结构复杂,无法使用表级别的CRUD操作时,可以通过继承Repository接口来替代CrudRepository。
按照自定义查询的方式实现,我们将开始实现 @Query 方法。
public interface TodoRepository extends Repository<Todo, String> {
@Query("SELECT ...")
long findAll();
}
执行SQL动态化
在Spring Data JDBC中,似乎不支持动态SQL的构建。
虽然Spring Data JPA的CrudRepository接口定义了可以接收Example参数的方法,但在Spring Data的CrudRepository接口中并没有定义,非常简单。
春季引导器测试
这是用于测试Spring Boot的起始器。
通过使用Spring Boot的自动配置机制,可以自动完成用于测试Spring Boot应用的Bean定义。开发者只需添加spring-boot-starter-test依赖并进行少量设置即可。
pom.xml -> 项目对象模型文件
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
JUnit 测试用例
在JUnit测试案例中,只需在类上添加@DataJdbcTest注解并使用@Autowired注入目标测试的仓库即可。
src/test/java/*/repository/TodoRepositoryTest.java的中文释义是什么?
@DataJdbcTest
@Transactional
class TodoRepositoryTest {
@Autowired
TodoRepository todoRepository;
@Test
@Sql(statements = "INSERT INTO todo (todo_title, finished, created_at) VALUES ('sample todo', false, '2019-01-01')")
void testFindAll() {
// execute
Iterable<Todo> todos = todoRepository.findAll();
// assert
assertThat(todos)
.hasSize(1)
.extracting(Todo::getTodoTitle, Todo::isFinished, Todo::getCreatedAt)
.containsExactly(tuple("sample todo", false, LocalDate.of(2019, 1, 1).atStartOfDay()));
}
@DataJdbcTest使用于Spring Data JDBC,它会自动为您进行Bean定义,包括用于访问数据库的DataSource等。
@DataJdbcTest没有自动添加@Transactional,所以为了在测试结束后进行回滚,需要自己添加@Transactional。而@DataJpaTest却可以自动添加,为什么会这样呢…
注意:
从Spring Boot 2.2.2开始,@DataJdbcTest注解中会自动添加@Transactional注解。
总结
通过使用Spring Data JDBC的starter,我们可以省略配置方面的繁琐工作,将重点放在Repository的实现上。
关于Spring Data JDBC和MyBatis的集成,请参考另一篇文章。