Spring Data JDBC参考文档三
原标题:Spring认证|Spring Data JDBC参考文档三 (内容来源:Spring中国教育管理中心)#Spring##java##程序员#
9.6.9. 身份证生成
Spring Data JDBC 使用 ID 来标识实体。实体的 ID 必须使用 Spring Data 的@Id注解进行注解。
当您的数据库具有用于 ID 列的自动增量列时,生成的值在将其插入数据库后在实体中设置。
一个重要的约束是,在保存实体后,该实体不能再是新的。请注意,实体是否是新实体是实体状态的一部分。对于自动增量列,这会自动发生,因为 ID 由 Spring Data 使用 ID 列中的值设置。如果您不使用自增列,您可以使用一个BeforeSave监听器,它设置实体的 ID(在本文档后面介绍)。
9.6.10. 乐观锁定
Spring Data JDBC 通过@Version在聚合根上注释的数字属性来支持乐观锁定 。每当 Spring Data JDBC 使用这样的版本属性保存聚合时,会发生两件事:聚合根的更新语句将包含一个 where 子句,检查存储在数据库中的版本实际上未更改。如果不是这种情况,
OptimisticLockingFailureException将会抛出一个will。此外,实体和数据库中的 version 属性都会增加,因此并发操作将注意到更改并抛出一个(OptimisticLockingFailureException如果适用),如上所述。
这个过程也适用于插入新的聚合,其中 anull或0version 表示一个新实例,然后增加的实例将实例标记为不再是新的,这使得在对象构造期间生成 id 的情况下,例如当 UUID 是用过的。
在删除过程中,版本检查也适用,但不会增加版本。
9.7. 查询方法
本节提供有关 Spring Data JDBC 的实现和使用的一些特定信息。
您通常在存储库上触发的大多数数据访问操作都会导致对数据库运行查询。定义这样的查询就是在存储库接口上声明一个方法,如以下示例所示:
示例 58.带有查询方法的 PersonRepository
interface PersonRepository extends PagingAndSortingRepository {
List findByFirstname(String firstname);
List findByFirstnameOrderByLastname(String firstname, Pageable pageable);
Slice findByLastname(String lastname, Pageable pageable);
Page findByLastname(String lastname, Pageable pageable);
Person findByFirstnameAndLastname(String firstname, String lastname);
Person findFirstByLastname(String lastname);
@Query("SELECT * FROM person WHERE lastname = :lastname")
List findByLastname(String lastname);
}
该方法显示对所有具有给定 的人的查询lastname。该查询是通过解析可以与And和连接的约束的方法名称来派生的Or。因此,方法名称导致查询表达式为SELECT … FROM person WHERE firstname = :firstname。
使用Pageable来抵消和排序参数传递到数据库。
返回一个Slice. 选择LIMIT+1行以确定是否有更多数据要使用。ResultSetExtractor不支持自定义。
运行分页查询,返回Page. 仅选择给定页面边界内的数据,并可能使用计数查询来确定总计数。ResultSetExtractor不支持自定义。
查找给定条件的单个实体。它以
IncorrectResultSizeDataAccessException非唯一结果结束。
与 相比,即使查询产生更多的结果文档,第一个实体也总是被发出。
该findByLastname方法显示了对所有具有给定姓氏的人的查询。
下表显示了查询方法支持的关键字:
查询派生仅限于可以在WHERE不使用连接的情况下在子句中使用的属性。
9.7.1. 查询查找策略
JDBC 模块支持将查询手动定义为@Query注释中的字符串或属性文件中的命名查询。
从方法名称派生查询目前仅限于简单属性,这意味着属性直接存在于聚合根中。此外,此方法仅支持选择查询。
9.7.2. 使用@Query
下面的例子展示了如何使用@Query来声明一个查询方法:
示例 59. 使用 @Query 声明查询方法
public interface UserRepository extends CrudRepository {
@Query("select firstName, lastName from User u where u.emailAddress = :email")
User findByEmailAddress(@Param("email") String email);
}
对于将查询结果转换为实体RowMapper,默认情况下使用与 Spring Data JDBC 生成的查询相同的实体。您提供的查询必须与RowMapper预期的格式相匹配。必须提供实体构造函数中使用的所有属性的列。通过 setter、wither 或 field 访问设置的属性列是可选的。结果中没有匹配列的属性将不会被设置。该查询用于填充聚合根、嵌入实体和一对一关系,包括作为 SQL 数组类型存储和加载的原始类型数组。为实体的映射、列表、集合和数组生成单独的查询。
Spring 完全支持 Java 8 的基于-parameters编译器标志的参数名称发现。通过在构建中使用此标志作为调试信息的替代方法,您可以省略@Param命名参数的注释。
Spring Data JDBC 仅支持命名参数。
9.7.3. 命名查询
如果如上一节所述,注解中没有给出查询,Spring Data JDBC 将尝试定位一个命名查询。有两种方法可以确定查询的名称。默认是采用查询的域类,即存储库的聚合根,采用其简单名称并附加以..分隔的方法名称。或者,@Query注释具有一个name属性,可用于指定要查找的查询的名称。
命名查询应在
META-INF/jdbc-named-queries.properties类路径上的属性文件中提供。
可以通过将值设置为 来更改该文件的位置@
EnableJdbcRepositories.namedQueriesLocation。
风俗 RowMapper
您可以RowMapper通过使用@Query(rowMapperClass = ….)或 通过注册RowMapperMapbean 并注册RowMapper每个方法的返回类型来配置要使用的对象。以下示例显示了如何注册
DefaultQueryMappingConfiguration:
@Bean
QueryMappingConfiguration rowMappers() {
return new DefaultQueryMappingConfiguration()
.register(Person.class, new PersonRowMapper())
.register(Address.class, new AddressRowMapper());
}
在确定将哪个RowMapper用于方法时,根据方法的返回类型遵循以下步骤:
如果类型是简单类型,RowMapper则使用no 。
相反,查询应返回单行单列,并对该值应用到返回类型的转换。
QueryMappingConfiguration迭代中的实体类,直到找到一个是相关返回类型的超类或接口。使用RowMapper为该类注册的。
迭代按照注册的顺序进行,因此请确保在特定类型之后注册更通用的类型。
如果适用,包装器类型(例如集合)或被Optional解包。因此,返回类型 ofOptional使用Person前面过程中的类型。
使用自定义RowMapperthrough QueryMappingConfiguration、@Query(rowMapperClass=…)或自定义ResultSetExtractor会禁用实体回调和生命周期事件,因为结果映射可以根据需要发出自己的事件/回调。
修改查询
您可以使用@Modifyingon query 方法将查询标记为修改查询,如以下示例所示:
@Modifying
@Query("UPDATE DUMMYENTITY SET name = :name WHERE id = :id")
boolean updateName(@Param("id") Long id, @Param("name") String name);
您可以指定以下返回类型:
void
int (更新记录数)
boolean(是否更新了记录)
9.8. MyBatis 集成
CRUD 操作和查询方法可以委托给 MyBatis。本节介绍如何配置 Spring Data JDBC 以与 MyBatis 集成,以及将查询的运行以及到库的映射移交给它的约定。
9.8.1. 配置
将 MyBatis 正确插入 Spring Data JDBC 的最简单方法是导入MyBatisJdbcConfiguration应用程序配置:
@Configuration
@EnableJdbcRepositories
@Import(MyBatisJdbcConfiguration.class)
class Application {
@Bean
SqlSessionFactoryBean sqlSessionFactoryBean() {
// Configure MyBatis here
}
}
如您所见,您只需要声明一个
SqlSessionFactoryBeanasMyBatisJdbcConfiguration依赖于最终SqlSession可用的bean ApplicationContext。
9.8.2. 使用约定
对于 中的每个操作CrudRepository,Spring Data JDBC 运行多个语句。如果SqlSessionFactory应用程序上下文中有 ,Spring Data 会检查每一步是否SessionFactory提供了一条语句。如果找到,则使用该语句(包括其配置到实体的映射)。
声明的名称与串接实体类型的完全限定名称构造Mapper.和String确定的一种说法。例如,如果org.example.User要插入的实例,Spring Data JDBC 会查找名为 的语句
org.example.UserMapper.insert。
当语句运行时, [ MyBatisContext]的实例作为参数传递,这使得语句可以使用各种参数。
下表描述了可用的 MyBatis 语句:
内容提示:本文(Spring Data JDBC参考文档)未完待续......