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的集成,请参考另一篇文章。

广告
将在 10 秒后关闭
bannerAds