Add examples to use Single Query Loading.
Query by Id works via the repository. Query derivation doesn't since it side steps the DataAccessStrategy. Closes #675
This commit is contained in:
committed by
Mark Paluch
parent
cec144ea0b
commit
15783e4f7c
@@ -22,6 +22,7 @@
|
||||
<module>immutables</module>
|
||||
<module>jmolecules</module>
|
||||
<module>jooq</module>
|
||||
<module>singlequeryloading</module>
|
||||
<!-- <module>mybatis</module> -->
|
||||
<module>graalvm-native</module>
|
||||
</modules>
|
||||
|
||||
41
jdbc/singlequeryloading/pom.xml
Normal file
41
jdbc/singlequeryloading/pom.xml
Normal file
@@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>singlequeryloading</artifactId>
|
||||
<properties>
|
||||
<maven.compiler.source>21</maven.compiler.source>
|
||||
<maven.compiler.target>21</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.data.examples</groupId>
|
||||
<artifactId>spring-data-jdbc-examples</artifactId>
|
||||
<version>2.0.0.BUILD-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
<name>Spring Data JDBC - Demonstration of Single Query Loading</name>
|
||||
<description>Sample project demonstrating Single Query Loading with Spring Data JDBC</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jdbc</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.testcontainers</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2023 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
|
||||
*
|
||||
* https://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.jdbc.singlequeryloading;
|
||||
|
||||
/**
|
||||
* A simple entity for use in a collection of {@link PetOwner}.
|
||||
*
|
||||
* @author Jens Schauder
|
||||
*/
|
||||
record Cat(String name) {
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2023 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
|
||||
*
|
||||
* https://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.jdbc.singlequeryloading;
|
||||
|
||||
import org.springframework.boot.SpringBootConfiguration;
|
||||
import org.springframework.data.jdbc.core.convert.JdbcCustomConversions;
|
||||
import org.springframework.data.jdbc.core.mapping.JdbcMappingContext;
|
||||
import org.springframework.data.jdbc.repository.config.AbstractJdbcConfiguration;
|
||||
import org.springframework.data.jdbc.repository.config.EnableJdbcRepositories;
|
||||
import org.springframework.data.relational.RelationalManagedTypes;
|
||||
import org.springframework.data.relational.core.mapping.NamingStrategy;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Spring application context configuration that enables Single Query Loading.
|
||||
*
|
||||
* @author Jens Schauder
|
||||
*/
|
||||
@SpringBootConfiguration
|
||||
@EnableJdbcRepositories
|
||||
public class Config extends AbstractJdbcConfiguration {
|
||||
|
||||
|
||||
@Override
|
||||
public JdbcMappingContext jdbcMappingContext(Optional<NamingStrategy> namingStrategy, JdbcCustomConversions customConversions, RelationalManagedTypes jdbcManagedTypes) {
|
||||
|
||||
JdbcMappingContext jdbcMappingContext = super.jdbcMappingContext(namingStrategy, customConversions, jdbcManagedTypes);
|
||||
jdbcMappingContext.setSingleQueryLoadingEnabled(true);
|
||||
return jdbcMappingContext;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2023 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
|
||||
*
|
||||
* https://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.jdbc.singlequeryloading;
|
||||
|
||||
/**
|
||||
* A simple entity for use in a collection of {@link PetOwner}.
|
||||
*
|
||||
* @author Jens Schauder
|
||||
*/
|
||||
record Dog(String name) {
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2023 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
|
||||
*
|
||||
* https://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.jdbc.singlequeryloading;
|
||||
|
||||
/**
|
||||
* A simple entity for use in a collection of {@link PetOwner}.
|
||||
*
|
||||
* @author Jens Schauder
|
||||
*/
|
||||
record Fish(String name) {
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2023 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
|
||||
*
|
||||
* https://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.jdbc.singlequeryloading;
|
||||
|
||||
import org.springframework.data.annotation.Id;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* An aggregate with mutliple collections.
|
||||
*
|
||||
* @author Jens Schauder
|
||||
*/
|
||||
class PetOwner {
|
||||
|
||||
@Id
|
||||
Long Id;
|
||||
|
||||
String name;
|
||||
|
||||
List<Dog> dogs = new ArrayList<>();
|
||||
|
||||
List<Cat> cats = new ArrayList<>();
|
||||
|
||||
List<Fish> fish = new ArrayList<>();
|
||||
|
||||
public PetOwner(String name, List<Cat> cats, List<Dog> dogs, List<Fish> fish) {
|
||||
|
||||
this.name = name;
|
||||
this.cats = cats;
|
||||
this.dogs = dogs;
|
||||
this.fish = fish;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
PetOwner petOwner = (PetOwner) o;
|
||||
return Objects.equals(Id, petOwner.Id) && Objects.equals(name, petOwner.name) && Objects.equals(dogs, petOwner.dogs) && Objects.equals(cats, petOwner.cats) && Objects.equals(fish, petOwner.fish);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(Id, name, dogs, cats, fish);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2023 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
|
||||
*
|
||||
* https://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.jdbc.singlequeryloading;
|
||||
|
||||
import org.springframework.data.repository.ListCrudRepository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* Repository to access {@link PetOwner} instances.
|
||||
*
|
||||
* @author Jens Schauder
|
||||
*/
|
||||
interface PetOwnerRepository extends ListCrudRepository<PetOwner, Long> {
|
||||
List<PetOwner> findByName(String marry);
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
spring.datasource.url=jdbc:tc:postgresql:16.0:///test
|
||||
logging.level.org.springframework.jdbc.core.JdbcTemplate=DEBUG
|
||||
spring.sql.init.mode=always
|
||||
27
jdbc/singlequeryloading/src/main/resources/schema.sql
Normal file
27
jdbc/singlequeryloading/src/main/resources/schema.sql
Normal file
@@ -0,0 +1,27 @@
|
||||
CREATE TABLE PET_OWNER
|
||||
(
|
||||
ID SERIAL PRIMARY KEY,
|
||||
NAME VARCHAR(255)
|
||||
);
|
||||
|
||||
CREATE TABLE CAT
|
||||
(
|
||||
PET_OWNER INT,
|
||||
PET_OWNER_KEY INT,
|
||||
NAME VARCHAR(255)
|
||||
);
|
||||
|
||||
CREATE TABLE DOG
|
||||
(
|
||||
PET_OWNER INT,
|
||||
PET_OWNER_KEY INT,
|
||||
NAME VARCHAR(255)
|
||||
);
|
||||
|
||||
CREATE TABLE FISH
|
||||
(
|
||||
PET_OWNER INT,
|
||||
PET_OWNER_KEY INT,
|
||||
NAME VARCHAR(255)
|
||||
);
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright 2023 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
|
||||
*
|
||||
* https://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.jdbc.singlequeryloading;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
|
||||
import org.springframework.boot.test.autoconfigure.jdbc.JdbcTest;
|
||||
import org.springframework.data.jdbc.core.JdbcAggregateTemplate;
|
||||
import org.springframework.data.relational.core.query.Criteria;
|
||||
import org.springframework.data.relational.core.query.CriteriaDefinition;
|
||||
import org.springframework.data.relational.core.query.Query;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* Run tests demonstrating the use of Single Query Loading. You'll have to observe the executed queries.
|
||||
*
|
||||
* @author Jens Schauder
|
||||
*/
|
||||
@JdbcTest
|
||||
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
|
||||
class SingleQueryLoadingApplicationTests {
|
||||
|
||||
@Autowired
|
||||
PetOwnerRepository petOwners;
|
||||
@Autowired
|
||||
JdbcAggregateTemplate template;
|
||||
private PetOwner emil;
|
||||
private PetOwner marry;
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
petOwners.deleteAll();
|
||||
emil = petOwners.save(new PetOwner("Emil",
|
||||
List.of(
|
||||
new Cat("Edgar"),
|
||||
new Cat("Einstein"),
|
||||
new Cat("Elliot"),
|
||||
new Cat("Elton"),
|
||||
new Cat("Evan")
|
||||
),
|
||||
List.of(
|
||||
new Dog("Eric"),
|
||||
new Dog("Eddie"),
|
||||
new Dog("Eke"),
|
||||
new Dog("Echo")
|
||||
),
|
||||
List.of(
|
||||
new Fish("Floaty")
|
||||
)
|
||||
|
||||
));
|
||||
|
||||
marry = petOwners.save(new PetOwner("Marry",
|
||||
List.of(
|
||||
new Cat("Mars"),
|
||||
new Cat("Maverick"),
|
||||
new Cat("Max")
|
||||
),
|
||||
List.of(
|
||||
new Dog("Molly"),
|
||||
new Dog("Murphy"),
|
||||
new Dog("Madison"),
|
||||
new Dog("Macie")
|
||||
),
|
||||
List.of(
|
||||
new Fish("Mahi Mahi"),
|
||||
new Fish("Mr. Limpet")
|
||||
)
|
||||
));
|
||||
}
|
||||
|
||||
@Test
|
||||
void loadById() {
|
||||
|
||||
PetOwner emilReloaded = petOwners.findById(emil.Id).orElseThrow();
|
||||
|
||||
assertThat(emilReloaded).isEqualTo(emil);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
void loadByName() {
|
||||
|
||||
CriteriaDefinition criteria = Criteria.where("name").is("Marry");
|
||||
Query query = Query.query(criteria);
|
||||
List<PetOwner> marries = (List<PetOwner>) template.findAll(query, PetOwner.class);
|
||||
assertThat(marries).containsExactly(marry);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user