Spring Data JDBC介绍及实现代码
Spring新增了一个新的数据模块:SpringDataJDBC。SpringDataJDBC背后的想法是提供对关系数据库的访问,而无需处理JPA的复杂性。JPA提供延迟加载,缓存和脏跟踪等功能。果你需要这些功能会很很棒,但会让猜测JPA的行为比非JPA更难。
延迟加载可能会在你不需要时触发昂贵的语句,或者它可能会因异常而失败。当你想要比较一个实体的两个版本是哪个变成脏数据时,缓存可能会妨碍你,让你很难找到所有持久性操作都通过的那个点。
SpringDataJDBC目标是实现更简单的模型,不会有缓存,脏数据跟踪或延迟加载。相反,只有在调用数据库方法时才会发出SQL语句。方法返回的对象会完全加载,不会有延迟。实体没有“会话”和代理。所有这些都应该使SpringDataJDBC更易于推理。
当然,这种更简单的方法会导致约束。
我们来看一个简单的例子。
首先,我们需要一个实体:
classCustomer{ @Id Longid; StringfirstName; LocalDatedob; }
请注意,不需要getter或setter。如果您意,可以增加。实际上,唯一的要求是实体有一个注释的属性Id(即@org.springframework.data.annotation.Id,注意不是javax.persistence,后者是JPA)。
接下来,我们需要声明一个存储库。最简单的方法是扩展CrudRepository:
interfaceCustomerRepositoryextendsCrudRepository{}
最后,我们需要配置ApplicationContext以启用存储库的创建:
@Configuration @EnableJdbcRepositories(1) publicclassCustomerConfigextendsJdbcConfiguration{(2) @Bean NamedParameterJdbcOperationsoperations(){(3) returnnewNamedParameterJdbcTemplate(dataSource()); } @Bean PlatformTransactionManagertransactionManager(){(4) returnnewDataSourceTransactionManager(dataSource()); } @Bean DataSourcedataSource(){(5) returnnewEmbeddedDatabaseBuilder() .generateUniqueName(true) .setType(EmbeddedDatabaseType.HSQL) .addScript("create-customer-schema.sql") .build(); } }
让我们一步一步地解释。
1.EnableJdbcRepositories可以创建存储库。由于它需要存在一些bean,我们需要其余的配置。
2.继承扩展的JdbcConfiguration将一些默认bean添加到ApplicationContext。可以覆盖其方法以自定义SpringDataJDBC的某些行为。现在,我们使用默认实现。
3.真正重要的部分是NamedParameterJdbcOperations,它在内部用于向数据库提交SQL语句。
4.严格来说,事务管理器不是必需的。不支持跨越多个SQL语句的事务。
5.SpringDataJDBC没有直接使用DataSource,但是,由于TransactionManager和NamedParameterJdbcOperations需要,将DataSource注册为bean是一种确保两者使用相同实例的简单方法。
这就是一切。现在让我们测试玩玩:
@RunWith(SpringRunner.class) @Transactional @ContextConfiguration(classes=CustomerConfig.class) publicclassCustomerRepositoryTest{ @AutowiredCustomerRepositorycustomerRepo; @Test publicvoidcreateSimpleCustomer(){ Customercustomer=newCustomer(); customer.dob=LocalDate.of(1904,5,14); customer.firstName="Albert"; Customersaved=customerRepo.save(customer); assertThat(saved.id).isNotNull(); saved.firstName="HansAlbert"; customerRepo.save(saved); Optionalreloaded=customerRepo.findById(saved.id); assertThat(reloaded).isNotEmpty(); assertThat(reloaded.get().firstName).isEqualTo("HansAlbert"); } }
@Query注解
你可能不会只使用基本的CRUD方法CrudRepository。可以使用简单的@Query注释来指定存储库方法的查询:
@Query("selectid,first_name,dobfromcustomerwhereupper(first_name)like'%'||upper(:name)||'%'") ListfindByName(@Param("name")Stringname);
请注意,@Param如果使用-parameters标志进行编译,则不需要注释。
如果要执行更新或删除语句,可以使用@Modifying向方法添加注释。
让我们创建另一个测试以试用新方法。
@Test publicvoidfindByName(){ Customercustomer=newCustomer(); customer.dob=LocalDate.of(1904,5,14); customer.firstName="Albert"; Customersaved=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) }
由于Java对象与其对应行之间的连接是Id类型,因此设置Id为null并再次保存它会在数据库中创建另一行。
我们正在进行不区分大小写(例如)搜索,因此,我们找到“Albert”和“Bertram”,但不是“Beth”。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。