ams
ams

Reputation: 62702

How to validate Spring Data JPA Queries on Startup?

Given a Spring Data JPA Repository like so.

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);
}

How do I get Spring Data JPA to validate each of these queries at startup. For example when I use named queries with hibernate and the query is syntactically incorrect or property name is wrong hibernate complains.

Can spring data be configured to validate queries on start-up?

Upvotes: 2

Views: 4246

Answers (2)

matsev
matsev

Reputation: 33779

Rather than validating this at startup, I suggest that you create a test for this that can be executed by your continues integration server. Since you are already using Spring, it is very simple to create an Embedded Database that you can initialize with known test data.

Create two files schema.sql which is the actual production data schema, and test-data.sql which contains some known test data. Next, create a separate test application context that :

<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>

or Java based configuration:

@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
}

Next, you create a test for your 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
    }
}

The addition of @Transactional to the test class will cause the database to automatically rollback after each test method has completed. Consequently, all test will have the same database state (as specified by the test-data.sql) even if repository write operations are executed within a test.

Upvotes: 3

gerrytan
gerrytan

Reputation: 41143

You can create a method decorated with @PostCreate annotation on your bean and invoke the repository method so any exceptions will happen immediately. It is cumbersome if you have many.

Probably a more appropriate method is to unit tests those repository methods.

Upvotes: 0

Related Questions