如何在启动时验证 Spring Data JPA 查询?

Posted

技术标签:

【中文标题】如何在启动时验证 Spring Data JPA 查询?【英文标题】:How to validate Spring Data JPA Queries on Startup? 【发布时间】:2014-01-14 01:21:12 【问题描述】:

给定一个像这样的 Spring Data JPA 存储库。

public interface ProductRepository extends CrudRepository<Product, Long>, QueryDslPredicateExecutor<Product> 


    @Query("select p from Product p where p.attributes[?1] = ?2")
    List<Product> findByAttributeAndValue(String attribute, String value);

如何让 Spring Data JPA 在启动时验证每个查询。例如,当我在 hibernate 中使用命名查询并且查询在语法上不正确或属性名称错误时,hibernate 会抱怨。

是否可以配置 spring 数据以在启动时验证查询?

【问题讨论】:

您不想在没有控制逻辑的情况下运行查询。假设您有一个delete from Product 方法。进行测试。 @MarkusMalkusch 我只想验证查询而不运行它们,如果查询引用不存在的属性或实体,或者有无法解析的语法错误,请在 satrtup 了解. @ams 没有要求在启动时运行查询,而是验证它们。如果查询包含未映射到您的代码的无效 JPQL 或实体/属性名称,那么您希望获得快速失败行为,因此在服务器启动时,异常会告诉您您的查询无效。顺便说一句:hibernate 不会按照您的假设来验证命名查询。见这里:***.com/questions/27565706/… 【参考方案1】:

与其在启动时验证它,我建议您为此创建一个可以由您的持续集成服务器执行的测试。由于您已经在使用 Spring,因此创建一个 Embedded Database 非常简单,您可以使用已知的测试数据对其进行初始化。

创建两个文件schema.sql 是实际的生产数据架构,test-data.sql 包含一些已知的测试数据。接下来,创建一个单独的测试应用程序上下文:

<beans ...>

    <jpa:repositories base-package="com.example.repositories" />

    <jdbc:embedded-database id="dataSource">
        <jdbc:script location="classpath:schema.sql"/>
        <jdbc:script location="classpath:test-data.sql"/>
    </jdbc:embedded-database>

    <tx:annotation-driven/>

    <!-- more beans -->
</beans>

或基于 Java 的配置:

@Configuration
@EnableJpaRepositories("com.example.repositories")
@EnableTransactionManagement
public class TestConfig 

    @Bean(destroyMethod = "shutdown")
    public void EmbeddedDatabase embeddedDatabase() 
        EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
        return builder.setType(H2).addScript("schema.sql").addScript("test-data.sql").build();

    // more beans

接下来,为ProductRepository 创建一个测试:

@ContextConfiguration([reference to your xml or Java application context])
@RunWith(SpringJUnit4ClassRunner.class) 
@Transactional
public class ProductRepositoryTest 

    @Autowired
    ProductRepository repository;

    @Test
    public void findProductByAttributeAndValue() 
        List<Product> actual = repository.findByAttributeAndValue("attr", "val");

        // add assertions that 'actual' contains the expected data from the test-data.sql
    

在测试类中添加@Transactional 将导致数据库在每个测试方法完成后自动回滚。因此,所有测试都将具有相同的数据库状态(由 test-data.sql 指定),即使在测试中执行存储库写入操作也是如此。

【讨论】:

我已经有一个相当不错的测试套件,但它需要一段时间才能运行 :) 更喜欢在启动时只对查询进行语法检查的方法。【参考方案2】:

您可以在 bean 上创建一个带有 @PostCreate 注释的方法并调用存储库方法,这样任何异常都会立即发生。多的话就麻烦了。

可能更合适的方法是对这些存储库方法进行单元测试。

【讨论】:

而且,仅仅调用方法是不够的,因为如果结果为空,可能仍然存在潜在的转换异常。

以上是关于如何在启动时验证 Spring Data JPA 查询?的主要内容,如果未能解决你的问题,请参考以下文章

如何通过 Spring Data JPA 了解底层数据库名称

处理 JPA 规范和 spring-data-jpa 时如何使用声明 Stream 作为返回类型

从控制台应用程序使用带有休眠功能的spring-data-jpa时如何延迟加载收集

JPA,Spring Data进行后端非空验证的步骤

在 Spring Data JPA 中,如何在运行时添加实体?

如何在实现 Spring Data JPA AuditorAware 接口时获取 getUserPrincipal().getUserName()