#330 - Added projection sample for how to avoid dedicated SQL result set mappings.
Upgraded to Ingalls snapshots as the sampler needs some tweaks that have not made it into a released version yet.
This commit is contained in:
@@ -11,6 +11,10 @@
|
||||
<artifactId>spring-data-jpa-jpa21</artifactId>
|
||||
<name>Spring Data JPA - JPA 2.1 specific features</name>
|
||||
|
||||
<properties>
|
||||
<spring-data-releasetrain.version>Ingalls-BUILD-SNAPSHOT</spring-data-releasetrain.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
|
||||
@@ -21,5 +21,4 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
* @author Thomas Darimont
|
||||
*/
|
||||
@SpringBootApplication
|
||||
class CustomResultSetMappingsConfiguration {
|
||||
}
|
||||
class CustomResultSetMappingsConfiguration {}
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package example.springdata.jpa.resultsetmappings;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@@ -23,39 +25,40 @@ import javax.persistence.ConstructorResult;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.NamedNativeQueries;
|
||||
import javax.persistence.NamedNativeQuery;
|
||||
import javax.persistence.SqlResultSetMapping;
|
||||
|
||||
/**
|
||||
* @author Thomas Darimont
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Entity
|
||||
@NoArgsConstructor
|
||||
@NamedNativeQueries({
|
||||
|
||||
// A query using a dedicated SQL result set mapping (see below)
|
||||
@NamedNativeQuery(name = "Subscription.findAllSubscriptionSummaries", //
|
||||
query = "select product_name as productName, count(user_id) as subscriptions from subscription group by product_name order by productName", //
|
||||
resultSetMapping = "subscriptionSummary"),
|
||||
|
||||
// A query using simple projections
|
||||
@NamedNativeQuery(name = "Subscription.findAllSubscriptionProjections", //
|
||||
query = "select product_name as product, count(user_id) as usageCount from subscription group by product_name order by product") })
|
||||
|
||||
@SqlResultSetMapping( //
|
||||
name="subscriptionSummary", //
|
||||
classes = @ConstructorResult(
|
||||
targetClass = SubscriptionSummary.class, //
|
||||
columns={
|
||||
@ColumnResult(name="productName", type=String.class), //
|
||||
@ColumnResult(name="subscriptions", type=long.class)
|
||||
}))
|
||||
@NamedNativeQuery(
|
||||
name="Subscription.findAllSubscriptionSummaries", //
|
||||
query="select product_name as productName, count(user_id) as subscriptions from subscription group by product_name order by productName", //
|
||||
resultSetMapping = "subscriptionSummary")
|
||||
name = "subscriptionSummary", //
|
||||
classes = @ConstructorResult(targetClass = SubscriptionSummary.class, //
|
||||
columns = { //
|
||||
@ColumnResult(name = "productName", type = String.class), //
|
||||
@ColumnResult(name = "subscriptions", type = long.class) //
|
||||
}))
|
||||
|
||||
@Entity
|
||||
@Data
|
||||
@NoArgsConstructor(force = true, access = AccessLevel.PRIVATE)
|
||||
@AllArgsConstructor
|
||||
public class Subscription {
|
||||
|
||||
@Id
|
||||
@GeneratedValue
|
||||
Long id;
|
||||
|
||||
String productName;
|
||||
|
||||
long userId;
|
||||
|
||||
public Subscription(String productName, long userId) {
|
||||
this.productName = productName;
|
||||
this.userId = userId;
|
||||
}
|
||||
private final @Id @GeneratedValue Long id = null;
|
||||
private String productName;
|
||||
private long userId;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package example.springdata.jpa.resultsetmappings;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
interface SubscriptionProjection {
|
||||
|
||||
String getProduct();
|
||||
|
||||
long getUsageCount();
|
||||
}
|
||||
@@ -15,22 +15,35 @@
|
||||
*/
|
||||
package example.springdata.jpa.resultsetmappings;
|
||||
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.SqlResultSetMapping;
|
||||
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
|
||||
/**
|
||||
* @author Thomas Darimont
|
||||
*/
|
||||
public interface SubscriptionRepository extends CrudRepository<Subscription, Long> {
|
||||
|
||||
/**
|
||||
* Returns an aggregated {@link SubscriptionSummary} by Product.
|
||||
* <p>
|
||||
* Note that this example uses a JPA 2.1 Constructor based {@link javax.persistence.SqlResultSetMapping}
|
||||
* in combination with native query defined in {@link Subscription}.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
List<SubscriptionSummary> findAllSubscriptionSummaries();
|
||||
/**
|
||||
* Returns an aggregated {@link SubscriptionSummary} by Product.
|
||||
* <p>
|
||||
* Note that this example uses a JPA 2.1 Constructor based {@link javax.persistence.SqlResultSetMapping} in
|
||||
* combination with native query defined in {@link Subscription}.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Query(nativeQuery = true)
|
||||
List<SubscriptionSummary> findAllSubscriptionSummaries();
|
||||
|
||||
/**
|
||||
* Returns an aggregated {@link SubscriptionProjection} using a named native query but does not require a dedicated
|
||||
* {@link SqlResultSetMapping}.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Query(nativeQuery = true)
|
||||
List<SubscriptionProjection> findAllSubscriptionProjections();
|
||||
}
|
||||
|
||||
@@ -23,7 +23,6 @@ import lombok.Value;
|
||||
@Value
|
||||
public class SubscriptionSummary {
|
||||
|
||||
private final String product;
|
||||
|
||||
private final Long usageCount;
|
||||
String product;
|
||||
Long usageCount;
|
||||
}
|
||||
|
||||
@@ -15,9 +15,10 @@
|
||||
*/
|
||||
package example.springdata.jpa.resultsetmappings;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static java.util.Arrays.*;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -25,8 +26,6 @@ import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Thomas Darimont
|
||||
*/
|
||||
@@ -35,26 +34,36 @@ import java.util.List;
|
||||
@Transactional
|
||||
public class SubscriptionRepositoryIntegrationTests {
|
||||
|
||||
private static final String SERVICE_1 = "Service 1";
|
||||
private static final String SERVICE_2 = "Service 2";
|
||||
private static final String SERVICE_1 = "Service 1";
|
||||
private static final String SERVICE_2 = "Service 2";
|
||||
|
||||
@Autowired
|
||||
SubscriptionRepository repository;
|
||||
@Autowired SubscriptionRepository repository;
|
||||
|
||||
@Test
|
||||
public void shouldReturnCorrectSubscriptionSummary() {
|
||||
@Before
|
||||
public void setUp() {
|
||||
|
||||
repository.save(new Subscription(SERVICE_1, 1));
|
||||
repository.save(new Subscription(SERVICE_1, 2));
|
||||
repository.save(new Subscription(SERVICE_1, 3));
|
||||
repository.save(new Subscription(SERVICE_2, 3));
|
||||
repository.save(new Subscription(SERVICE_2, 4));
|
||||
repository.save(new Subscription(SERVICE_1, 1));
|
||||
repository.save(new Subscription(SERVICE_1, 2));
|
||||
repository.save(new Subscription(SERVICE_1, 3));
|
||||
repository.save(new Subscription(SERVICE_2, 3));
|
||||
repository.save(new Subscription(SERVICE_2, 4));
|
||||
}
|
||||
|
||||
List<SubscriptionSummary> subscriptionSummaries = repository.findAllSubscriptionSummaries();
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void shouldReturnCorrectSubscriptionSummary() {
|
||||
|
||||
assertThat(subscriptionSummaries) //
|
||||
.flatExtracting(s -> asList(s.getProduct(), s.getUsageCount()))
|
||||
.contains(SERVICE_1, 3L, SERVICE_2, 2L);
|
||||
}
|
||||
assertThat(repository.findAllSubscriptionSummaries()) //
|
||||
.flatExtracting(s -> asList(s.getProduct(), s.getUsageCount())) //
|
||||
.contains(SERVICE_1, 3L, SERVICE_2, 2L);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void shouldReturnCorrectSubscriptionProjection() {
|
||||
|
||||
assertThat(repository.findAllSubscriptionProjections()) //
|
||||
.flatExtracting(s -> asList(s.getProduct(), s.getUsageCount())) //
|
||||
.contains(SERVICE_1, 3L, SERVICE_2, 2L);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user