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 社区所有即将举行的活动。

查看所有