Spring Data JDBC 简介

工程 | Jens Schauder | 2018 年 9 月 17 日 | ...

随着即将发布的 Lovelace GA 版本,我们将发布一个新的 Spring Data 模块:Spring Data JDBC

Spring Data JDBC 的理念是提供对关系数据库的访问,而无需受 JPA 复杂性的限制。JPA 提供诸如延迟加载、缓存和脏数据跟踪等功能。虽然这些功能在您需要时非常有用,但它们实际上会使思考 JPA 及其行为变得比必要时更复杂。

延迟加载可能会在您不期望的时候触发代价高昂的语句,或者可能会抛出异常。当您实际上想要比较实体的两个版本时,缓存可能会妨碍您,而脏数据跟踪则使得很难找到所有持久化操作都通过的单一入口点。

Spring Data JDBC 旨在提供一个更简单的模型。它不会有缓存、脏数据跟踪或延迟加载。相反,SQL 语句仅在您调用存储库方法时发出。作为该方法结果返回的对象在方法返回之前已完全加载。没有“会话”并且实体没有代理。所有这些都应该使 Spring Data JDBC 更易于理解。

当然,这种更简单的方法会导致一些约束,这些约束将在以后的文章中介绍。此外,这是第一个版本,因此我们有很多想要实现的功能,并且计划实现,但我们不得不推迟实现,以便尽早将某些东西提供给您。

让我们来看一个简单的例子。

首先,我们需要一个实体

class Customer {
    @Id
    Long id;
    String firstName;
    LocalDate dob;
}

请注意,您不需要 getter 或 setter。如果您更喜欢这样做,使用它们完全没问题。实际上,唯一的要求是实体具有使用 Id 注解的属性(即 @org.springframework.data.annotation.Id,而不是 javax.persistence 中的)。

接下来,我们需要声明一个存储库。最简单的方法是扩展 CrudRepository

interface CustomerRepository extends CrudRepository<Customer, Long> {}

最后,我们需要配置 ApplicationContext 以启用存储库的创建

@Configuration
@EnableJdbcRepositories (1)
public class CustomerConfig extends JdbcConfiguration { (2)

    @Bean
    NamedParameterJdbcOperations operations() { (3)
        return new NamedParameterJdbcTemplate(dataSource());
    }

    @Bean
    PlatformTransactionManager transactionManager() { (4)
        return new DataSourceTransactionManager(dataSource());
	}

    @Bean
    DataSource dataSource(){ (5)
        return new EmbeddedDatabaseBuilder()
                .generateUniqueName(true)
                .setType(EmbeddedDatabaseType.HSQL)
                .addScript("create-customer-schema.sql")
                .build();
    }
}

让我们逐步完成配置步骤。

  1. EnableJdbcRepositories 启用存储库的创建。因为它需要某些 bean 的存在,所以我们需要其余的配置。

  2. 扩展 JdbcConfiguration 会向 ApplicationContext 添加一些默认 bean。您可以覆盖其方法以自定义 Spring Data JDBC 的某些行为。目前,我们使用默认实现。

  3. 真正重要的部分是 NamedParameterJdbcOperations,它在内部用于将 SQL 语句提交到数据库。

  4. 严格来说,事务管理器不是必需的。但是您将无法获得跨多个语句的事务支持,没有人想要那样,对吧?

  5. Spring Data JDBC 不会直接使用 DataSource,但是,由于 TransactionManagerNamedParameterJdbcOperations 需要它,因此将其注册为 bean 是一种确保两者使用同一实例的简单方法。

这就是开始使用它所需的一切。现在让我们在测试中使用它

@RunWith(SpringRunner.class)
@Transactional
@ContextConfiguration(classes = CustomerConfig.class)
public class CustomerRepositoryTest {

    @Autowired CustomerRepository customerRepo;

    @Test
    public void createSimpleCustomer() {

        Customer customer = new Customer();
        customer.dob = LocalDate.of(1904, 5, 14);
        customer.firstName = "Albert";

        Customer saved = customerRepo.save(customer);

        assertThat(saved.id).isNotNull();

        saved.firstName = "Hans Albert";

        customerRepo.save(saved);

        Optional<Customer> reloaded = customerRepo.findById(saved.id);

        assertThat(reloaded).isNotEmpty();

        assertThat(reloaded.get().firstName).isEqualTo("Hans Albert");
    }
}

@Query 注解

您可能仅使用 CrudRepository 中的基本 CRUD 方法无法走得太远。我们决定将查询推导(Spring Data 从方法名称推导出要使用的查询的流行功能)推迟到以后的版本。在它到来之前,您可以使用简单的 @Query 注解在存储库方法上指定查询

@Query("select id, first_name, dob from customer where upper(first_name) like '%' || upper(:name) || '%' ")
List<Customer> findByName(@Param("name") String name);

请注意,如果您使用 -parameters 标志编译,则不需要 @Param 注解。

如果要执行更新或删除语句,可以在方法中添加 @Modifying 注解。

让我们创建另一个测试以尝试新的方法。

@Test
public void findByName() {

    Customer customer = new Customer();
    customer.dob = LocalDate.of(1904, 5, 14);
    customer.firstName = "Albert";

    Customer saved = customerRepo.save(customer);

    assertThat(saved.id).isNotNull();

    customer.id= null; (1)
    customer.firstName = "Bertram";

    customerRepo.save(customer);

    customer.id= null;
    customer.firstName = "Beth";

    customerRepo.save(customer);

    assertThat(customerRepo.findByName("bert")).hasSize(2); (2)
}
  1. 由于 Java 对象与其对应行的关联只是其 Id 加上其类型,因此将 Id 设置为 null 并再次保存它会在数据库中创建另一行。

  2. 我们正在进行不区分大小写的 (like) 搜索,因此,我们找到了“Albert”和“Bertram”,但没有找到“Beth”。

结束语

关于 Spring Data JDBC,还有更多内容需要学习。继续阅读 Spring Data JDBC 引用和聚合

或者您可以 查看示例文档,当然还有 源代码。如果您有任何疑问,请 在 StackOverflow 上提问。如果您发现错误或想要请求功能,请 创建问题

获取 Spring 新闻通讯

与 Spring 新闻通讯保持联系

订阅

领先一步

VMware 提供培训和认证,以加快您的进步。

了解更多

获取支持

Tanzu Spring 在一个简单的订阅中提供 OpenJDK™、Spring 和 Apache Tomcat® 的支持和二进制文件。

了解更多

即将举行的活动

查看 Spring 社区中所有即将举行的活动。

查看全部