在 Spring Boot 中使用 Jdbi3 简介

如果您是 Java 开发人员并且曾经做过任何应用程序开发,那么您很可能会遇到需要为您的应用程序添加持久层的情况。多年来,这意味着包含重型 ORM,例如 Hibernate/JPA 或一些类似的库,以及随之而来的所有怪癖和挑战。一年前,我的一位同事指导我采用Jdbi一种新的(对我而言)处理数据的方法,从那时起我就没有回头。

Jdbi 舒适地位于 ORM 库和低级JDBC驱动程序之间,作为一个直观、简洁和轻量级的库,可以与您的持久层进行交互。Jdbi 不提供任何实体管理、中介服务或魔术来管理您的数据。此外,它不提供自动查询组合(如来自QueryDSLspring-data-jpa)、类似于 Hibernate 的 DDL 生成,甚至不提供 Java 应用程序服务器标志性的容器管理事务。

此时,您可能会问自己,“我为什么要牺牲所有这些花哨而有用的功能”?虽然这个问题有很多答案,但有几件事真正吸引了我对 Jdbi 的兴趣,下面重点介绍:

  • Jdbi 有声明式和流畅的 API。两者都非常易于使用,允许您编写干净简洁的代码,并且对引擎盖下实际发生的事情几乎没有想象空间
  • 关闭!我对使用 Hibernate 的最大抱怨之一是连接边界通常被应用程序服务器隐藏。Jdbi 通过使用闭包显式定义连接生命周期的能力完全解决了这个问题
  • 在方便的地方轻松将行和列自动映射到 Bean,但在需要时可以轻松定义自定义行为
  • 使用本机连接、选择和复杂查询,而不是依赖应用程序逻辑(即 Hibernate 使用子选择进行连接)。由于您的数据模型不表示为代码,因此在返回查询结果时您不会受到它的影响。可以轻松构建新的数据视图并将其映射到自定义 bean 中,几乎不费吹灰之力
  • 最后,由于没有中间层来管理您的数据,因此它比许多 ORM 的性能要高得多!

使用 Jdbi 和 Spring Boot 构建一个简单的应用程序

下面的小教程将概述一些简单的步骤,让您开始在自己的 spring 项目中使用 Jdbi。这两种工具的功能都非常丰富。本教程将概述如何在 Spring Boot 应用程序中使用 Jdbi3 进行设置,但不会深入探讨每个功能更强大的功能。请继续关注未来的帖子以获取更多信息。

将 Jdbi 依赖项添加到您的项目

在开始之前,您需要将几个 Jdbi 依赖项添加到您的pom.xml. 在本教程中,我们将使用我最喜欢的数据库:Postgres。如果您在为此示例创建数据库时需要帮助,可以参考 Postgres 的官方文档

<dependencies>
    <!-- Additional Spring Dependency -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jdbc</artifactId>
    </dependency>
    <!-- Jdbi Dependencies -->
    <dependency>
        <groupId>org.jdbi</groupId>
        <artifactId>jdbi3-core</artifactId>
        <version>3.6.0</version>
    </dependency>
    <dependency>
        <groupId>org.jdbi</groupId>
        <artifactId>jdbi3-sqlobject</artifactId>
        <version>3.6.0</version>
    </dependency>
    <dependency>
        <groupId>org.jdbi</groupId>
        <artifactId>jdbi3-postgres</artifactId>
        <version>3.6.0</version>
    </dependency>
</dependencies>

添加库是一种轻量级的方式,可以在不向项目添加不必要的依赖spring-boot-starter-data-jdbc项的情况下获得所有方便的 spring-boot 自动配置。DataSource由于Jdbi只是一个包装器,JDBC我们不会添加任何不会使用的东西。

设置数据源永久链接

在我们开始使用我们的应用程序之前,我们需要告诉 Spring 数据库的连接信息。实现这一点的最简单方法是在我们的src/main/resources/application.yml. 一般来说,我会硬编码我需要在本地开发的值,application.yml然后提供prod配置文件,或者利用 springs externalized configuration model

spring:
  datasource:
    # I previously created a "Role" for my postgres database for this tutorial 
    username: jdbi-example-spring-boot
    # When developing locally , I tend not to use passwords for ease of use
    password: ""
    url: jdbc:postgresql://localhost/jdbi-example-spring-boot
    driver-class-name: org.postgresql.Driver

配置 Jdbi Bean

我们要让 Jdbi 对应用程序可用,创建一个可以自动装配到任何需要它的服务的 bean。为此,我们可以创建一个新的配置类并注册必要的 bean。

@Configuration
public class JdbiConfiguration {

    @Bean
    public Jdbi jdbi(DataSource datasource){
        return Jdbi.create(dataSource)
            .installPlugin(new PostgresPlugin())
            .installPlugin(new SqlObjectPlugin());
    }
}

由于spring-boot-starter-data-jdbc不需要自己配置DataSource,而是允许springDataSource直接将之前定义的bean注入到 jdbi()Bean定义方法中。最后,我们创建Jdbibean 并确保初始化正确的插件,以便Jdbi了解 Postgresjsonb使用的特定数据类型和操作(即 Postgres 数据)。

创建 POJO固定链接

我们将要创建一个简单的 POJO 来表示我们的数据。需要注意的是,这根本不需要与我们的数据模型对应,但可以包含对我们的需求有用的任何内容,而无需更改数据模型。Jdbi 不会像在 Hibernate 中那样自动生成任何数据模型。请注意,@Data注释来自lombok,这是一个适用于任何 Java 开发人员的方便库!

@Data
public class User {
    private Long id;
    private String firstName;
    private String lastName;
    private String phoneNumber 
}

定义一个声明式DAO

我是 Jdbi 定义持久性交互的声明性方法的忠实粉丝。这种方法使用带有注释组合的接口,然后 Jdbi 可以使用这些接口为您生成 DAO 的实现。通过使用声明性方法,您可以清楚地了解 jdbi 执行代码时究竟发生了什么。

public interface UserDao {

    @Transaction
    @SqlUpdate("CREATE TABLE IF NOT EXISTS users(id BIGINT NOT NULL PRIMARY KEY, first_name VARCHAR(48), last_name VARCHAR(48), phone_number VARCHAR(48))")
    void createUserTable();

    @Transaction
    @SqlUpdate("INSERT INTO users(id,first_name,last_name,phone_number) VALUES(:id,:firstName,:lastName,:phoneNumber)")
    void createUser(@BindBean User user);

    @SqlQuery("SELECT * FROM users")
    @RegisterBeanMapper(User.class)
    List<User> getUsers();

    @SqlQuery("SELECT * FROM users WHERE id = :id")
    @RegisterBeanMapper(User.class)
    User getUser(@Bind("id") Long id);

}

这里发生了很多事情,但是从注释中很容易准确地理解每种方法试图实现的目标。@Transaction注释告诉 Jdbi 将特定的方法调用包装在事务中。您可以将其他参数传递给此注释以修改事务生命周期,但是对于我们的目的,默认值很好。这两个注解在外观@SqlQUery@SqlUpdate非常相似,都将SQL字符串作为参数,但是它们决定了非常不同的行为。@SqlUpdate用于定义以某种方式更改数据的操作。这可以通过SETINSERT,DELETEALTER 操作。这@SqlQuery另一方面,注解不能以任何方式修改数据,而只能用于检索数据。

使用 Jdbi,您可以在执行时提供参数化SQL字符串和绑定方法参数SQL。上面演示了两种方法(但是 Jdbi 提供了更多的绑定方法)@Bind@BindBean. 注释将@Bind方法参数映射到 中的特定参数SQL,而@BindBean注释将使用gettersbean 的 将其所有属性绑定到SQL.

最后,Jdbi 提供了将行(甚至连接行)映射到所需 bean 或原始类型的简单方法。上面的示例使用@RegisterBeanMapper(User.class)注释告诉 Jdbi 使用存在的设置器将返回的行转换为User对象。需要注意的是,这并不User像 Hibernate 那样 Proxy 类,而你返回的对象是一个真正的 POJO。如果您需要更多地控制 bean 的映射方式,Jdbi 提供了许多额外的策略来进行行、列和集合级别的映射。

设置控制器

@RestController
public class UserController {

    private Jdbi jdbi;

    public UserController(Jdbi jdbi){
        this.jdbi = jdbi;
        jdbi.useExtension(UserDao.class,UserDao::createUserTable);
    }

    @PostMapping("/users")
    public User createUser(@RequestBody User user){
        user.setId(System.currentTimeMillis());
        jdbi.useExtension(UserDao.class, dao -> dao.createUser(user));
        return user;
    }

    @GetMapping("/users")
    public List<User> getUsers(){
        return jdbi.withExtension(UserDao.class, UserDao::getUsers);
    }

    @GetMapping("/users/{id}")
    public User getUsers(@PathVariable  Long id){
        return jdbi.withExtension(UserDao.class, dao -> dao.getUser(id));
    }

}

Jdbi在控制器中,我们使用闭包进行交互。在我看来,这是与数据库交互的好方法:它明确定义了连接边界,将持久性逻辑与服务层分开,并保证在闭包之外没有副作用。它清晰、简洁和干净的代码将使您的生活更轻松。

我们在这里使用了两种特定的方法:withExtensionuseExtension. 这些方法将Dao接口用作“扩展”的参数,然后是闭包的 lambda 函数或方法引用。闭包传递了一个参数,即dao从我们的接口创建的实例。withExtension提供了一种返回值的方法,同时useExtension允许我们简单地对数据库运行一些东西。Jdbi当然提供了其他检索和更新数据的方法,完整的分类请参考官方文档。

创建您的 Spring Boot 应用程序

@SpringBootApplication
public class JdbiExampleApplication {
    public static void main(String[] args) {
        SpringApplication.run(JdbiExampleApplication.class, args);
    }
}

测试你的 API

现在您已经设置好了 Spring 应用程序,您可以对其进行测试了!您可以发出一些简单的 curl 请求,以确保您的 REST-API 已准备就绪。

创建一个新用户

curl -XPOST -H 'Content-Type: application/json' 'http://localhost:8080/users' -d '{"firstName":"Joe","lastName":"Shmo","phoneNumber":"714-832-2211"}'
{
    "id":1589208108922,
    "firstName":"Maria",
    "lastName":"Magee",
    "phoneNumber":"676332415"
}

检索所有用户

curl 'http://localhost:8080/users'
[
    {
        "id":1589208108922,
        "firstName":"Maria",
        "lastName":"Magee",
        "phoneNumber":"676332415"
    }
]

检索单个用户永久链接

curl 'http://localhost:8080/users/1589208108922'
{
    "id":1589208108922,
    "firstName":"Maria",
    "lastName":"Magee",
    "phoneNumber":"676332415"
}

关闭永久链接

至此,您应该了解如何设置一个简单的 spring-boot 应用程序并Jdbi为持久层供电!如果您有兴趣了解更多有关Jdbi提供的惊人功能的信息,可以查看官方文档。如果您想继续学习,可以在GitHub上找到本教程的所有源代码。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值