Skip to content

Commit 3b58fec

Browse files
parikshitduttafmbenhassine
authored andcommitted
Add support for Named Query in JpaPagingItemReader
Issue #1667
1 parent d257fce commit 3b58fec

File tree

4 files changed

+215
-1
lines changed

4 files changed

+215
-1
lines changed
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* Copyright 2020 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.batch.item.database.orm;
17+
18+
import javax.persistence.Query;
19+
20+
import org.springframework.util.Assert;
21+
import org.springframework.util.StringUtils;
22+
23+
/**
24+
* <p>
25+
* This query provider creates JPA named {@link Query}s.
26+
* </p>
27+
*
28+
* @author Mahmoud Ben Hassine
29+
* @author Parikshit Dutta
30+
* @since 4.3
31+
*
32+
* @param <E> entity returned by executing the query
33+
*/
34+
public class JpaNamedQueryProvider<E> extends AbstractJpaQueryProvider {
35+
36+
private Class<E> entityClass;
37+
38+
private String namedQuery;
39+
40+
@Override
41+
public Query createQuery() {
42+
return getEntityManager().createNamedQuery(namedQuery, entityClass);
43+
}
44+
45+
/**
46+
* @param namedQuery name of a jpa named query
47+
*/
48+
public void setNamedQuery(String namedQuery) {
49+
this.namedQuery = namedQuery;
50+
}
51+
52+
/**
53+
* @param entityClazz name of a jpa entity class
54+
*/
55+
public void setEntityClass(Class<E> entityClazz) {
56+
this.entityClass = entityClazz;
57+
}
58+
59+
@Override
60+
public void afterPropertiesSet() throws Exception {
61+
Assert.isTrue(StringUtils.hasText(namedQuery), "Named query cannot be empty");
62+
Assert.notNull(entityClass, "Entity class cannot be NULL");
63+
}
64+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* Copyright 2020 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.batch.item.database;
17+
18+
import javax.persistence.EntityManagerFactory;
19+
20+
import org.springframework.batch.item.ItemReader;
21+
import org.springframework.batch.item.database.orm.JpaNamedQueryProvider;
22+
import org.springframework.batch.item.sample.Foo;
23+
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
24+
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
25+
26+
/**
27+
* Integration Test for {@link JpaPagingItemReader} and {@link JpaNamedQueryProvider}.
28+
*
29+
* @author Parikshit Dutta
30+
*/
31+
public class JpaPagingItemReaderNamedQueryIntegrationTests
32+
extends AbstractGenericDataSourceItemReaderIntegrationTests {
33+
34+
@Override
35+
protected ItemReader<Foo> createItemReader() throws Exception {
36+
LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
37+
factoryBean.setDataSource(dataSource);
38+
factoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
39+
factoryBean.setPersistenceUnitName("bar");
40+
factoryBean.afterPropertiesSet();
41+
42+
EntityManagerFactory entityManagerFactory = factoryBean.getObject();
43+
44+
JpaNamedQueryProvider<Foo> jpaNamedQueryProvider = new JpaNamedQueryProvider<>();
45+
jpaNamedQueryProvider.setNamedQuery("allFoos");
46+
jpaNamedQueryProvider.setEntityClass(Foo.class);
47+
jpaNamedQueryProvider.afterPropertiesSet();
48+
49+
JpaPagingItemReader<Foo> inputSource = new JpaPagingItemReader<>();
50+
inputSource.setEntityManagerFactory(entityManagerFactory);
51+
inputSource.setQueryProvider(jpaNamedQueryProvider);
52+
inputSource.afterPropertiesSet();
53+
inputSource.setSaveState(true);
54+
55+
return inputSource;
56+
}
57+
}

spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/builder/JpaPagingItemReaderBuilderTests.java

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2017 the original author or authors.
2+
* Copyright 2017-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -15,7 +15,9 @@
1515
*/
1616
package org.springframework.batch.item.database.builder;
1717

18+
import java.util.ArrayList;
1819
import java.util.HashMap;
20+
import java.util.List;
1921
import java.util.Map;
2022
import javax.persistence.EntityManagerFactory;
2123
import javax.sql.DataSource;
@@ -26,6 +28,7 @@
2628

2729
import org.springframework.batch.item.ExecutionContext;
2830
import org.springframework.batch.item.database.JpaPagingItemReader;
31+
import org.springframework.batch.item.database.orm.JpaNamedQueryProvider;
2932
import org.springframework.batch.item.database.orm.JpaNativeQueryProvider;
3033
import org.springframework.batch.item.sample.Foo;
3134
import org.springframework.context.ConfigurableApplicationContext;
@@ -48,6 +51,7 @@
4851

4952
/**
5053
* @author Michael Minella
54+
* @author Parikshit Dutta
5155
*/
5256
public class JpaPagingItemReaderBuilderTests {
5357

@@ -134,6 +138,40 @@ public void testConfigurationNoSaveState() throws Exception {
134138
assertEquals(0, executionContext.size());
135139
}
136140

141+
@Test
142+
public void testConfigurationNamedQueryProvider() throws Exception {
143+
JpaNamedQueryProvider<Foo> namedQueryProvider = new JpaNamedQueryProvider<>();
144+
namedQueryProvider.setNamedQuery("allFoos");
145+
namedQueryProvider.setEntityClass(Foo.class);
146+
namedQueryProvider.afterPropertiesSet();
147+
148+
JpaPagingItemReader<Foo> reader = new JpaPagingItemReaderBuilder<Foo>()
149+
.name("fooReader")
150+
.entityManagerFactory(this.entityManagerFactory)
151+
.queryProvider(namedQueryProvider)
152+
.build();
153+
154+
reader.afterPropertiesSet();
155+
156+
ExecutionContext executionContext = new ExecutionContext();
157+
reader.open(executionContext);
158+
159+
Foo foo;
160+
List<Foo> foos = new ArrayList<>();
161+
162+
while((foo = reader.read()) != null) {
163+
foos.add(foo);
164+
}
165+
166+
reader.update(executionContext);
167+
reader.close();
168+
169+
int id = 0;
170+
for (Foo testFoo:foos) {
171+
assertEquals(++id, testFoo.getId());
172+
}
173+
}
174+
137175
@Test
138176
public void testConfigurationQueryProvider() throws Exception {
139177

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* Copyright 2020 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.batch.item.database.orm;
17+
18+
import static org.junit.Assert.*;
19+
import org.junit.Test;
20+
21+
import org.springframework.batch.item.sample.Foo;
22+
23+
/**
24+
* Test for {@link JpaNamedQueryProvider}s.
25+
*
26+
* @author Parikshit Dutta
27+
*/
28+
public class JpaNamedQueryProviderTests {
29+
30+
@Test
31+
public void testJpaNamedQueryProviderNamedQueryIsProvided() {
32+
JpaNamedQueryProvider<Foo> jpaNamedQueryProvider = new JpaNamedQueryProvider<>();
33+
jpaNamedQueryProvider.setEntityClass(Foo.class);
34+
35+
try {
36+
jpaNamedQueryProvider.afterPropertiesSet();
37+
}
38+
catch (Exception exception) {
39+
assertEquals("Named query cannot be empty", exception.getMessage());
40+
}
41+
}
42+
43+
@Test
44+
public void testJpaNamedQueryProviderEntityClassIsProvided() {
45+
JpaNamedQueryProvider<Foo> jpaNamedQueryProvider = new JpaNamedQueryProvider<>();
46+
jpaNamedQueryProvider.setNamedQuery("allFoos");
47+
48+
try {
49+
jpaNamedQueryProvider.afterPropertiesSet();
50+
}
51+
catch (Exception exception) {
52+
assertEquals("Entity class cannot be NULL", exception.getMessage());
53+
}
54+
}
55+
}

0 commit comments

Comments
 (0)