Reputation: 62702
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
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
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