介绍Spring Data JDBC

在即将发布的代号为Lovelace的 Spring Data版本中,我们将包含一个新模块: Spring Data JDBC


Spring Data JDBC的思想是提供对关系数据库的访问, 而无需使用JPA的所有复杂性


JPA提供了诸如延迟加载缓存更改跟踪 (脏跟踪)之类的功能。 尽管事实上这些功能非常酷,但是如果您确实需要它们,它们当然会使理解数据访问逻辑的过程大大复杂化。


延迟加载机制可以突然执行资源密集型请求,甚至会因异常而失败。 当您决定比较一个实体的两个版本时, 缓存会以您的方式出现,并且与跟踪更改一起使您更难理解在什么时候实际执行所有数据库操作?


Spring Data JDBC专注于更简单的模型 。 不会有缓存,更改跟踪或延迟加载。 而是,仅当您调用存储库方法时,才会执行SQL查询。 该方法执行后,返回的结果将完全加载到内存中。 实体将没有“会话”机制或代理对象。 所有这些都应使Spring Data JDBC成为用于访问数据的更简单,更直观的工具。


当然,这种简化的方法会带来许多限制,我们将在下一篇文章中讨论。 即将发布的版本是该库的第一个版本,我们有许多计划和想法要实现,但是我们必须推迟它们,以便您有机会尽早开始使用Spring Data JDBC。


例子


首先,我们需要定义实体:


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

请注意,我们没有定义getter或setter。 当然,您可以根据需要添加它们。 本质上,对实体的唯一要求是使用Id注释对字段进行注释(但必须是org.springframework.data.annotation.Id ,而不是javax.persistence one )。

接下来,您需要定义存储库。 最简单的方法是扩展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 ,几个bean将自动添加到上下文中。 如果需要更改Spring Data JDBC的行为,也可以重叠它们。 但是在此示例中,我们将保留默认行为。
  3. 一个非常重要的组件是NamedParameterJdbcOperations ,用于执行数据库查询。
  4. 严格来说,不需要交易经理。 但是没有它,就不会有交易支持,很少有人会喜欢它,对吗?
  5. Spring Data JDBC并不直接使用DataSource ,但是TransactionManagerNamedParameterJdbcOperation要求它在上下文中存在,这就是我们确定所需bean的原因。

这就是开始使用Spring Data JDBC所需要的全部。 现在编写一个测试以查看其工作原理:


 @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


只有使用标准的CRUD方法,您才能远离CrudRepository类存储库。 我们有意决定推迟自动查询的生成,这是Spring Data的流行功能,当基于方法名称生成SQL查询时,Spring Data会在以后的版本中使用。 现在,您只需使用熟悉的@Query批注即可确切指定应执行的SQL查询。


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

如果要修改或删除请求中的数据,可以在方法中添加@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可以说的更多,我们一定会在以后的文章中告诉您。


同时,您可以研究示例代码文档以及源代码 。 如果您有任何疑问,请随时在StackOverflow提问 。 并且,如果您发现错误或想要请求新功能-请创建票证

Source: https://habr.com/ru/post/zh-CN423697/


All Articles