Java for Web学习笔记(一一五):Spring Data(3)配置

史钊
2023-12-01

使用XML来配置

之前为了让代码跑起来,我们已经通过Java代码对Spring Data进行了配置。再此,我们将进一步学习,包括XML方式。

XML配置涉及两个namespace:

<?xml version="1.0" encoding="UTF-8"?>
<!-- 引入namespace,另外schemaLocation中请注意project采用的版本 -->
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:data="http://www.springframework.org/schema/data/repository"
       xmlns:data-jpa="http://www.springframework.org/schema/data/jpa"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
                           http://www.springframework.org/schema/data/repository
                           http://www.springframework.org/schema/data/repository/spring-repository-1.6.xsd
                           http://www.springframework.org/schema/data/jpa
                           http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd"> 
<!-- populator: 根据文件(json或者XML)来填充仓库的数据,其作用相当于最后在表格中预设某些条目。这是危险的,不会在生产环境中使用。例子中data:jackson2-populator定义一个bean(bean名字可在可选的id属性中指定),使用Jackson Data Processor 2.x ObjectMapper作为文件解析器,解析器的bean名字在object-mapper-ref中定义。此外还有data:jackson-populator,这是使用Jackson Data Processor 1.x ObjectMapper,还有xml的data:unmarshaller-populator,使用unmarshaller-ref来说明解析器的bean名。这是一个json文件的例子:-->
<!--  [{"_class" : "com.some.Class",  -->
<!--     "id" : "id1",                -->
<!--     "firstname" : "Admin",       -->
<!--     "lastname" : "admin"         -->
<!--   },                             -->
<!--   {"_class" : "com.some.Class",  -->
<!--    "id" : "id2",                 -->
<!--    "firstname" : "user",         -->
<!--    "lastname" : "user"           -->
<!--   }]                             -->
    <data:jackson2-populator locations="classpath:com/sample/config/inserts.json"
                             object-mapper-ref="objectMapper" />
<!--     这是重点,也是之前我们在java代码中配置的@EnableJpaRepositories所对应,属性有: -->
<!--  ➤ base-package 必须:将扫描扩展了org.springframework.data.repository.Repository接口,没有标记@NoRepositoryBean,为它们生成接口的实现。-->
<!--  ➤ named-queries-location 可选:这个不是Spring Data的,而是JPA的,就是我们使用entityManager.createNamedQuery()中的预定义JPQL,相当于相当于Entity代码中的@NamedQueries,我们可以定义.properties文件包含这些预定义。 -->
<!--  ➤ repository-impl-postfix 可选:缺省是Impl,也就是BookRepository的自定义方法实现会自动查找BookRepositoryImpl。 -->
<!--  ➤ query-lookup-strategy 可选:查找的策略,缺省是create-if-not-found,表示使用已定义的查询方法,如果不匹配,则根据规则(例如find...By...)创建该方法的实现。use-declared-query表示只使用已定义的,不根据方法名创建查询的实现;create则表示不使用已定义的,只使用根据方法名创建查询的实现。-->
<!--  ➤ factory-class 可选,定义非缺省的repository factory bean -->
<!--  ➤ transaction-manager-ref 可选,如果不指定,则采用Spring framework缺省的PlatformTransactionManager -->
<!--     Spring data JPA特有的属性: -->
<!--  ➤ entity-manager-factory-ref 可选,缺省为的Bean为entityManagerFactory,如果不是,需要明确指出 -->
    <data-jpa:repositories base-package="com.sample" 
                           transaction-manager-ref="jpaTransactionManager"
                           entity-manager-factory-ref="entityManagerFactoryBean"
                           query-lookup-strategy="create">
<!--     在data-jpa:repositories中的子element有: -->
<!--  ➤ <data:include-filter>接口自动生成代码必须要符合的条件,类似于<context:component-scan>中的<context:include-filter> -->
<!--  ➤ <data:exclude-filter>接口自动生成代码必须不满足的条件,类似于<context:component-scan>中的<context:exclude-filter> -->
<!--     例如我们将JPA DB和MongoDB的repository接口都放在同一个package中(当然分开放也可轻松解决问题),那么扫描到扩展Repository接口的就好自动生成代码,这样会生成两份代码,造成错误。我们通过include-filter做进一步限制,只有扩展JpaRepository的生产Spring data JPA相关的代码,而扩展MongoRepository生成Spring data mongo的代码,例如如下:-->
<!--     <data-jpa:repositories base-package="com.sample">  -->
<!--          <data:include-filter type="assignable" expression="org.springframework.data.jpa.repository.JpaRepository" />  -->
<!--     </data-jpa:repositories>  -->
<!--     <data-mongo:repositories base-package="com.sample">  -->
<!--          <data:include-filter type="assignable" expression="org.springframework.data.mongodb.repository.MongoRepository" />  -->
<!--     </data-mongo:repositories> -->        
        <data:include-filter type="annotation" expression="com.sample.MyRepository" />
    </data-jpa:repositories>
<!--     当允许审计Spring Data在保存entity时,可以设置特定的entity属性,例如谁保存,什么时间保存。其他的spring data项目有也有类似的元素。含有以下属性:-->
<!--  ➤ auditor-aware-ref 是an org.springframework.data.domain.AuditorAware<U>的实现的Bean名字,检查当前的认证用户或principal。如果无此属性,审计将不会记录那个用户进行了修改。 -->
<!--  ➤ set-dates 缺省值为true,表明当创建或者修改时,记录是否要设置日期。 -->
<!--  ➤ date-time-provider-ref org..springframework.data.auditing.DateTimeProvider实现的bean名字,缺省为org.springframework.data.auditing.CurrentDateTimeProvider,基于Calendar。-->
<!--  ➤ modify-on-creation 缺省值为true,表明是否在创建时设置修改日期,如果为false,则修改日期只在update的时候设置,create不设置。-->
    <data-jpa:auditing auditor-aware-ref="auditorAwareImpl" />
</beans>

一般来讲我们只设置data-jpa:repositories。

使用Java代码来配置

通过@EnableJpaRepositories来替代 <data-jpa:repositories>的相关配置,这也是我们之前小例子的做法。

@EnableJpaRepositories标记:

  • basePackages和basePackageClasses对应XMl配置中的base-package
  • namedQueriesLocation <--> named-queries-location
  • repositoryImplementationPostfix <--> repository-impl-postfix
  • queryLookupStrategy <--> query-lookup-strategy,值为QueryLookupStrategy.Key enum。
  • repositoryFactoryBeanClass <--> factory-class
  • transactionManagerRef <--> transaction-manager-ref
  • entityManagerFactoryRef <--> entity-manager-factory-ref

@ComponentScan.Filter标记

  • includeFilters <--> <data:include-filter>
  • excludeFilters <--> <data:exclude-filter>

例子如下:

@Configuration
...
@EnableJpaRepositories( basePackages = "com.wrox.site.repositories",
                        entityManagerFactoryRef = "entityManagerFactoryBean",
                        transactionManagerRef = "jpaTransactionManager"
)
...
public class RootContextConfiguration implements AsyncConfigurer, SchedulingConfigurer{
   ...
}

审计的配置

如果set-dates=true,modify-on-creation=true(缺省值),我们只需定义AuditorAware 的Bean即可。

如果上述两个中有false,我们只能使用XML的,在Java代码中,通过@ImportResource来提供XML的配置。

更常见的情况,审计是基于entity,我们可以在entity的属性上标记,表明这是一个审计的列。注意,属性不能同时具有下面两个或以上的标记。

  • @org.springframework.data.annotation.CreatedBy 记录登录的用户,其Java类型必须同AuditorAware的返回值。
  • @org.springframework.data.annotation.CreatedDate,可以使用long,Long,java.util.Date,org.joda.time.DateTime,Calendar,Instant,LocalDateTime,OffsetDateTime,ZonedDateTime,但不能使用Timestamp。
  • @org.springframework.data.annotation.LastModifiedBy
  • @org.springframework.data.annotation.LastModifiedDate

配置Spring MVC的支持

Spring data可以和Spring MVC的接口参数进行自动转换,例如Pageable和Sort。

@RequestMapping("/person/{id}")
/* Spring data可以自动调用findOne(),根据id来获取具体的Person对象。*/
public String viewPerson(@PathVariable("id") Person person){
    ......
}

在DispatcherServlet的配置

只需在DispatcherServlet的配置类上加上@org.springframework.data.web.config.EnableSpringDataWebSupport即可,可以自动注册下面的bean

  • org.springframework.data.repository.support.DomainClassConverter:将请求参数和路径进行转换,如上面的例子
  • PageableHandlerMethodArgumentResolver,转换请求中的Pageable参数
  • SortHandlerMethodArgumentResolver,转换请求中的Sort参数
@Configuration
@EnableWebMvc
@EnableSpringDataWebSupport
@ComponentScan( basePackages = "com.wrox.site",
                useDefaultFilters = false,
                includeFilters = @ComponentScan.Filter(WebController.class) )
public class WebServletContextConfiguration extends WebMvcConfigurerAdapter
EnableSpringDataWebSupport使用缺省值,包括名字,最大的page数,缺省的Pageable和Sort的值等等。如果你不适用缺省值,需要自己定义,那么删除@EnableSpringDataWebSupport,手动注册这些bean。相关的代码例子在后面学习。


相关链接:我的Professional Java for Web Applications相关文章

 类似资料: