Merge branch 'eugenp:master' into master
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
Username,Id,First name,Last name
|
||||
doe1,7173,John,Doe
|
||||
smith3,3722,Dana,Smith
|
||||
john22,5490,John,Wang
|
||||
|
@@ -1,7 +1,5 @@
|
||||
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.baeldung.core-java-persistence-2</groupId>
|
||||
<artifactId>core-java-persistence-2</artifactId>
|
||||
@@ -41,6 +39,20 @@
|
||||
<artifactId>mssql-jdbc</artifactId>
|
||||
<version>${mssql.driver.version}</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>org.jooq</groupId>
|
||||
<artifactId>jooq</artifactId>
|
||||
<version>3.11.11</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.json</groupId>
|
||||
<artifactId>json</artifactId>
|
||||
<version>20220320</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
|
||||
+137
@@ -0,0 +1,137 @@
|
||||
package com.baeldung.resultset2json;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.ResultSetMetaData;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import org.jooq.Record;
|
||||
import org.jooq.RecordMapper;
|
||||
import org.jooq.impl.DSL;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.json.JSONArray;
|
||||
|
||||
public class ResultSet2JSON {
|
||||
|
||||
public static void main(String... args) throws ClassNotFoundException, SQLException {
|
||||
|
||||
ResultSet2JSON testClass = new ResultSet2JSON();
|
||||
testClass.convertWithoutJOOQ();
|
||||
}
|
||||
|
||||
public void convertWithoutJOOQ() throws ClassNotFoundException, SQLException {
|
||||
Class.forName("org.h2.Driver");
|
||||
Connection dbConnection = DriverManager.getConnection("jdbc:h2:mem:rs2jdbc", "user", "password");
|
||||
|
||||
// Create a table
|
||||
Statement stmt = dbConnection.createStatement();
|
||||
stmt.execute("CREATE TABLE words AS SELECT * FROM CSVREAD('./example.csv')");
|
||||
ResultSet resultSet = stmt.executeQuery("SELECT * FROM words");
|
||||
|
||||
JSONArray result1 = resultSet2JdbcWithoutJOOQ(resultSet);
|
||||
System.out.println(result1);
|
||||
|
||||
resultSet.close();
|
||||
}
|
||||
|
||||
public void convertUsingJOOQDefaultApproach() throws ClassNotFoundException, SQLException {
|
||||
Class.forName("org.h2.Driver");
|
||||
Connection dbConnection = DriverManager.getConnection("jdbc:h2:mem:rs2jdbc", "user", "password");
|
||||
// Create a table
|
||||
Statement stmt = dbConnection.createStatement();
|
||||
stmt.execute("CREATE TABLE words AS SELECT * FROM CSVREAD('./example.csv')");
|
||||
ResultSet resultSet = stmt.executeQuery("SELECT * FROM words");
|
||||
|
||||
JSONObject result1 = resultSet2JdbcUsingJOOQDefaultApproach(resultSet, dbConnection);
|
||||
System.out.println(result1);
|
||||
|
||||
resultSet.close();
|
||||
}
|
||||
|
||||
public void convertUsingCustomisedJOOQ() throws ClassNotFoundException, SQLException {
|
||||
Class.forName("org.h2.Driver");
|
||||
Connection dbConnection = DriverManager.getConnection("jdbc:h2:mem:rs2jdbc", "user", "password");
|
||||
// Create a table
|
||||
Statement stmt = dbConnection.createStatement();
|
||||
stmt.execute("CREATE TABLE words AS SELECT * FROM CSVREAD('./example.csv')");
|
||||
ResultSet resultSet = stmt.executeQuery("SELECT * FROM words");
|
||||
|
||||
JSONArray result1 = resultSet2JdbcUsingCustomisedJOOQ(resultSet, dbConnection);
|
||||
System.out.println(result1);
|
||||
|
||||
resultSet.close();
|
||||
}
|
||||
|
||||
public static JSONArray resultSet2JdbcWithoutJOOQ(ResultSet resultSet) throws SQLException {
|
||||
ResultSetMetaData md = resultSet.getMetaData();
|
||||
int numCols = md.getColumnCount();
|
||||
List<String> colNames = IntStream.range(0, numCols)
|
||||
.mapToObj(i -> {
|
||||
try {
|
||||
return md.getColumnName(i + 1);
|
||||
} catch (SQLException e) {
|
||||
|
||||
e.printStackTrace();
|
||||
return "?";
|
||||
}
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
|
||||
JSONArray result = new JSONArray();
|
||||
while (resultSet.next()) {
|
||||
JSONObject row = new JSONObject();
|
||||
colNames.forEach(cn -> {
|
||||
try {
|
||||
row.put(cn, resultSet.getObject(cn));
|
||||
} catch (JSONException | SQLException e) {
|
||||
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
result.put(row);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static JSONObject resultSet2JdbcUsingJOOQDefaultApproach(ResultSet resultSet, Connection dbConnection) throws SQLException {
|
||||
JSONObject result = new JSONObject(DSL.using(dbConnection)
|
||||
.fetch(resultSet)
|
||||
.formatJSON());
|
||||
return result;
|
||||
}
|
||||
|
||||
public static JSONArray resultSet2JdbcUsingCustomisedJOOQ(ResultSet resultSet, Connection dbConnection) throws SQLException {
|
||||
ResultSetMetaData md = resultSet.getMetaData();
|
||||
int numCols = md.getColumnCount();
|
||||
List<String> colNames = IntStream.range(0, numCols)
|
||||
.mapToObj(i -> {
|
||||
try {
|
||||
return md.getColumnName(i + 1);
|
||||
} catch (SQLException e) {
|
||||
|
||||
e.printStackTrace();
|
||||
return "?";
|
||||
}
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
|
||||
List<JSONObject> json = DSL.using(dbConnection)
|
||||
.fetch(resultSet)
|
||||
.map(new RecordMapper<Record, JSONObject>() {
|
||||
|
||||
@Override
|
||||
public JSONObject map(Record r) {
|
||||
JSONObject obj = new JSONObject();
|
||||
colNames.forEach(cn -> obj.put(cn, r.get(cn)));
|
||||
return obj;
|
||||
}
|
||||
});
|
||||
return new JSONArray(json);
|
||||
}
|
||||
}
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
package com.baeldung.resultset2json;
|
||||
|
||||
import static com.baeldung.resultset2json.ResultSet2JSON.resultSet2JdbcWithoutJOOQ;
|
||||
import static com.baeldung.resultset2json.ResultSet2JSON.resultSet2JdbcUsingJOOQDefaultApproach;
|
||||
import static com.baeldung.resultset2json.ResultSet2JSON.resultSet2JdbcUsingCustomisedJOOQ;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
public class ResultSet2JSONUnitTest {
|
||||
JSONObject object = new JSONObject(
|
||||
"{\"records\":[[\"doe1\",\"7173\",\"John\",\"Doe\"],[\"smith3\",\"3722\",\"Dana\",\"Smith\"],[\"john22\",\"5490\",\"John\",\"Wang\"]],\"fields\":[{\"schema\":\"PUBLIC\",\"name\":\"USERNAME\",\"type\":\"VARCHAR\",\"table\":\"WORDS\"},{\"schema\":\"PUBLIC\",\"name\":\"ID\",\"type\":\"VARCHAR\",\"table\":\"WORDS\"},{\"schema\":\"PUBLIC\",\"name\":\"First name\",\"type\":\"VARCHAR\",\"table\":\"WORDS\"},{\"schema\":\"PUBLIC\",\"name\":\"Last name\",\"type\":\"VARCHAR\",\"table\":\"WORDS\"}]}");
|
||||
|
||||
JSONArray array = new JSONArray(
|
||||
"[{\"USERNAME\":\"doe1\",\"First name\":\"John\",\"ID\":\"7173\",\"Last name\":\"Doe\"},{\"USERNAME\":\"smith3\",\"First name\":\"Dana\",\"ID\":\"3722\",\"Last name\":\"Smith\"},{\"USERNAME\":\"john22\",\"First name\":\"John\",\"ID\":\"5490\",\"Last name\":\"Wang\"}]");
|
||||
|
||||
@Test
|
||||
void whenResultSetConvertedWithoutJOOQ_shouldMatchJSON() throws SQLException, ClassNotFoundException {
|
||||
Class.forName("org.h2.Driver");
|
||||
Connection dbConnection = DriverManager.getConnection("jdbc:h2:mem:rs2jdbc1", "user", "password");
|
||||
|
||||
// Create a table
|
||||
Statement stmt = dbConnection.createStatement();
|
||||
stmt.execute("CREATE TABLE words AS SELECT * FROM CSVREAD('./example.csv')");
|
||||
ResultSet resultSet = stmt.executeQuery("SELECT * FROM words");
|
||||
|
||||
JSONArray result1 = resultSet2JdbcWithoutJOOQ(resultSet);
|
||||
|
||||
resultSet.close();
|
||||
|
||||
assertTrue(array.similar(result1));
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenResultSetConvertedUsingJOOQDefaultApproach_shouldMatchJSON() throws SQLException, ClassNotFoundException {
|
||||
Class.forName("org.h2.Driver");
|
||||
Connection dbConnection = DriverManager.getConnection("jdbc:h2:mem:rs2jdbc2", "user", "password");
|
||||
// Create a table
|
||||
Statement stmt = dbConnection.createStatement();
|
||||
stmt.execute("CREATE TABLE words AS SELECT * FROM CSVREAD('./example.csv')");
|
||||
ResultSet resultSet = stmt.executeQuery("SELECT * FROM words");
|
||||
|
||||
JSONObject result2 = resultSet2JdbcUsingJOOQDefaultApproach(resultSet, dbConnection);
|
||||
|
||||
resultSet.close();
|
||||
|
||||
assertTrue(object.similar(result2));
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenResultSetConvertedUsingCustomisedJOOQ_shouldMatchJSON() throws SQLException, ClassNotFoundException {
|
||||
Class.forName("org.h2.Driver");
|
||||
Connection dbConnection = DriverManager.getConnection("jdbc:h2:mem:rs2jdbc3", "user", "password");
|
||||
// Create a table
|
||||
Statement stmt = dbConnection.createStatement();
|
||||
stmt.execute("CREATE TABLE words AS SELECT * FROM CSVREAD('./example.csv')");
|
||||
ResultSet resultSet = stmt.executeQuery("SELECT * FROM words");
|
||||
|
||||
JSONArray result3 = resultSet2JdbcUsingCustomisedJOOQ(resultSet, dbConnection);
|
||||
|
||||
resultSet.close();
|
||||
|
||||
assertTrue(array.similar(result3));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -16,7 +16,7 @@
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<!-- Spring -->
|
||||
<!-- Spring -->
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
@@ -32,7 +32,7 @@
|
||||
<artifactId>hibernate-core</artifactId>
|
||||
<version>${hibernate-core.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<dependency>
|
||||
<groupId>org.hsqldb</groupId>
|
||||
<artifactId>hsqldb</artifactId>
|
||||
<version>${hsqldb.version}</version>
|
||||
|
||||
@@ -11,3 +11,4 @@ This module contains articles about use of Queries in Hibernate.
|
||||
- [Hibernate Query Plan Cache](https://www.baeldung.com/hibernate-query-plan-cache)
|
||||
- [Hibernate’s addScalar() Method](https://www.baeldung.com/hibernate-addscalar)
|
||||
- [Distinct Queries in HQL](https://www.baeldung.com/java-hql-distinct)
|
||||
- [JPA and Hibernate – Criteria vs. JPQL vs. HQL Query](https://www.baeldung.com/jpql-hql-criteria-query)
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<!-- Spring -->
|
||||
<!-- Spring -->
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
@@ -30,8 +30,7 @@
|
||||
<artifactId>tomcat-dbcp</artifactId>
|
||||
<version>${tomcat-dbcp.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- validation -->
|
||||
<!-- validation -->
|
||||
<!-- utils -->
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
@@ -45,7 +44,6 @@
|
||||
<version>${org.springframework.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-core</artifactId>
|
||||
@@ -81,8 +79,7 @@
|
||||
<artifactId>jmh-generator-annprocess</artifactId>
|
||||
<version>${jmh-generator.version}</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<org.springframework.version>5.0.2.RELEASE</org.springframework.version>
|
||||
|
||||
-1
@@ -32,5 +32,4 @@ public class EmployeeCriteriaIntegrationTest {
|
||||
session.close();
|
||||
assertArrayEquals(expectedSortCritEmployeeList.toArray(), employeeCriteriaQueries.getAllEmployees().toArray());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -50,4 +50,4 @@
|
||||
<morphia.version>1.5.3</morphia.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
</project>
|
||||
@@ -60,6 +60,7 @@
|
||||
<module>spring-boot-persistence</module>
|
||||
<module>spring-boot-persistence-h2</module>
|
||||
<module>spring-boot-persistence-mongodb</module>
|
||||
<module>spring-boot-persistence-mongodb-2</module>
|
||||
<module>spring-data-arangodb</module>
|
||||
<module>spring-data-cassandra</module>
|
||||
<module>spring-data-cassandra-test</module>
|
||||
@@ -108,4 +109,4 @@
|
||||
<postgresql.version>42.2.20</postgresql.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
</project>
|
||||
@@ -39,7 +39,7 @@
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<mysql-connector-java.version>8.0.12</mysql-connector-java.version>
|
||||
<mysql-connector-java.version>8.0.23</mysql-connector-java.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
@@ -1,6 +1,6 @@
|
||||
spring:
|
||||
datasource:
|
||||
url: jdbc:mysql://localhost:3306/test?useLegacyDatetimeCode=false
|
||||
url: jdbc:mysql://localhost:3306/test?
|
||||
username: root
|
||||
password:
|
||||
|
||||
@@ -9,6 +9,6 @@ spring:
|
||||
ddl-auto: update
|
||||
properties:
|
||||
hibernate:
|
||||
dialect: org.hibernate.dialect.MySQL5Dialect
|
||||
dialect: org.hibernate.dialect.MySQL8Dialect
|
||||
jdbc:
|
||||
time_zone: UTC
|
||||
@@ -0,0 +1,2 @@
|
||||
/.idea/
|
||||
/target/
|
||||
@@ -0,0 +1,4 @@
|
||||
# Relevant Articles
|
||||
|
||||
- [Logging MongoDB Queries with Spring Boot](https://www.baeldung.com/spring-boot-mongodb-logging)
|
||||
- More articles: [[<--prev]](../spring-boot-persistence-mongodb)
|
||||
@@ -0,0 +1,35 @@
|
||||
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>spring-boot-persistence-mongodb-2</artifactId>
|
||||
<name>spring-boot-persistence-mongodb-2</name>
|
||||
<packaging>war</packaging>
|
||||
<description>This is simple boot application for Spring boot persistence mongodb test</description>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>parent-boot-2</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<relativePath>../../parent-boot-2</relativePath>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-mongodb</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>de.flapdoodle.embed</groupId>
|
||||
<artifactId>de.flapdoodle.embed.mongo</artifactId>
|
||||
<version>${embed.mongo.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<embed.mongo.version>3.2.6</embed.mongo.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
package com.baeldung;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class SpringBootPersistenceApplication {
|
||||
|
||||
public static void main(String ... args) {
|
||||
SpringApplication.run(SpringBootPersistenceApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
spring.application.name=spring-boot-persistence-mongodb-2
|
||||
+2
-2
@@ -35,7 +35,7 @@ import de.flapdoodle.embed.mongo.distribution.Version;
|
||||
import de.flapdoodle.embed.process.runtime.Network;
|
||||
|
||||
@SpringBootTest
|
||||
@TestPropertySource(properties = { "logging.level.org.springframework.data.mongodb.core.MongoTemplate=DEBUG" })
|
||||
@TestPropertySource(properties = { "logging.level.org.springframework.data.mongodb.core.MongoTemplate=INFO" })
|
||||
public class LoggingUnitTest {
|
||||
|
||||
private static final String CONNECTION_STRING = "mongodb://%s:%d";
|
||||
@@ -51,7 +51,7 @@ public class LoggingUnitTest {
|
||||
@BeforeEach
|
||||
void setup() throws Exception {
|
||||
String ip = "localhost";
|
||||
int port = SocketUtils.findAvailableTcpPort();
|
||||
int port = Network.freeServerPort(Network.getLocalHost());
|
||||
|
||||
ImmutableMongodConfig mongodConfig = MongodConfig.builder()
|
||||
.version(Version.Main.PRODUCTION)
|
||||
+1
@@ -0,0 +1 @@
|
||||
spring.mongodb.embedded.version=4.4.9
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration scan="true" scanPeriod="15 seconds" debug="false">
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>[%d{ISO8601}]-[%thread] %-5level %logger - %msg%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<root level="INFO">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
</configuration>
|
||||
@@ -7,4 +7,4 @@
|
||||
- [ZonedDateTime with Spring Data MongoDB](https://www.baeldung.com/spring-data-mongodb-zoneddatetime)
|
||||
- [A Guide to @DBRef in MongoDB](https://www.baeldung.com/spring-mongodb-dbref-annotation)
|
||||
- [Import Data to MongoDB From JSON File Using Java](https://www.baeldung.com/java-import-json-mongodb)
|
||||
- [Logging MongoDB Queries with Spring Boot](https://www.baeldung.com/spring-boot-mongodb-logging)
|
||||
- More articles: [[next-->]](../spring-boot-persistence-mongodb-2)
|
||||
|
||||
@@ -4,6 +4,7 @@ This module contains articles about querying data using Spring Data JPA.
|
||||
|
||||
### Relevant Articles:
|
||||
- [Query Entities by Dates and Times with Spring Data JPA](https://www.baeldung.com/spring-data-jpa-query-by-date)
|
||||
- [JPA and Hibernate – Criteria vs. JPQL vs. HQL Query](https://www.baeldung.com/jpql-hql-criteria-query)
|
||||
- More articles: [[<-- prev]](../spring-data-jpa-query-2)
|
||||
|
||||
### Eclipse Config
|
||||
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
package com.baeldung.spring.data.jpa.query.specifications.join;
|
||||
|
||||
import javax.persistence.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Entity
|
||||
public class Author {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
private String firstName;
|
||||
|
||||
private String lastName;
|
||||
|
||||
@OneToMany(cascade = CascadeType.ALL)
|
||||
private List<Book> books;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getFirstName() {
|
||||
return firstName;
|
||||
}
|
||||
|
||||
public void setFirstName(String firstName) {
|
||||
this.firstName = firstName;
|
||||
}
|
||||
|
||||
public String getLastName() {
|
||||
return lastName;
|
||||
}
|
||||
|
||||
public void setLastName(String lastName) {
|
||||
this.lastName = lastName;
|
||||
}
|
||||
|
||||
public List<Book> getBooks() {
|
||||
return books;
|
||||
}
|
||||
|
||||
public void setBooks(List<Book> books) {
|
||||
this.books = books;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Author{" + "id=" + id + ", firstName='" + firstName + '\'' + ", lastName='" + lastName + '\'' + ", books=" + books + '}';
|
||||
}
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
package com.baeldung.spring.data.jpa.query.specifications.join;
|
||||
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
|
||||
import javax.persistence.criteria.*;
|
||||
|
||||
public class AuthorSpecifications {
|
||||
|
||||
public static Specification<Author> hasFirstNameLike(String name) {
|
||||
return (root, query, criteriaBuilder) -> criteriaBuilder.like(root.<String>get("firstName"), "%" + name + "%");
|
||||
}
|
||||
|
||||
public static Specification<Author> hasLastName(String name) {
|
||||
return (root, query, cb) -> cb.equal(root.<String>get("lastName"), name);
|
||||
}
|
||||
|
||||
public static Specification<Author> hasBookWithTitle(String bookTitle) {
|
||||
return (root, query, criteriaBuilder) -> {
|
||||
Join<Book, Author> authorsBook = root.join("books");
|
||||
return criteriaBuilder.equal(authorsBook.get("title"), bookTitle);
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package com.baeldung.spring.data.jpa.query.specifications.join;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface AuthorsRepository extends JpaRepository<Author, Long>, JpaSpecificationExecutor<Author> {
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
package com.baeldung.spring.data.jpa.query.specifications.join;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
|
||||
@Entity
|
||||
public class Book {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
private String title;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Book{" + "id=" + id + ", title='" + title + '\'' + '}';
|
||||
}
|
||||
}
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
package com.baeldung.spring.data.jpa.query.specifications.join;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static com.baeldung.spring.data.jpa.query.specifications.join.AuthorSpecifications.*;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@DataJpaTest
|
||||
public class SpecificationsJoinIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
private AuthorsRepository repository;
|
||||
|
||||
@Before
|
||||
public void beforeEach() {
|
||||
saveTestData();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenSearchingByLastName_thenOneAuthorIsReturned() {
|
||||
|
||||
List<Author> authors = repository.findAll(hasLastName("Martin"));
|
||||
|
||||
assertThat(authors).hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenSearchingByLastNameAndFirstNameLike_thenOneAuthorIsReturned() {
|
||||
|
||||
Specification<Author> specification = hasLastName("Martin").and(hasFirstNameLike("Robert"));
|
||||
|
||||
List<Author> authors = repository.findAll(specification);
|
||||
|
||||
assertThat(authors).hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenSearchingByBookTitle_thenOneAuthorIsReturned() {
|
||||
|
||||
Specification<Author> specification = hasBookWithTitle("Clean Code");
|
||||
|
||||
List<Author> authors = repository.findAll(specification);
|
||||
|
||||
assertThat(authors).hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenSearchingByBookTitleAndAuthorName_thenOneAuthorIsReturned() {
|
||||
|
||||
Specification<Author> specification = hasLastName("Martin").and(hasBookWithTitle("Clean Code"));
|
||||
|
||||
List<Author> authors = repository.findAll(specification);
|
||||
|
||||
assertThat(authors).hasSize(1);
|
||||
}
|
||||
|
||||
private void saveTestData() {
|
||||
Author uncleBob = new Author();
|
||||
uncleBob.setFirstName("Robert");
|
||||
uncleBob.setLastName("Martin");
|
||||
|
||||
Book book1 = new Book();
|
||||
book1.setTitle("Clean Code");
|
||||
Book book2 = new Book();
|
||||
book2.setTitle("Clean Architecture");
|
||||
|
||||
uncleBob.setBooks(Arrays.asList(book1, book2));
|
||||
repository.save(uncleBob);
|
||||
}
|
||||
}
|
||||
@@ -195,7 +195,7 @@
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
<org.jooq.version>3.12.4</org.jooq.version>
|
||||
<org.jooq.version>3.14.15</org.jooq.version>
|
||||
<lifecycle-mapping.version>1.0.0</lifecycle-mapping.version>
|
||||
<sql-maven-plugin.version>1.5</sql-maven-plugin.version>
|
||||
<properties-maven-plugin.version>1.0.0</properties-maven-plugin.version>
|
||||
|
||||
+8
-1
@@ -76,7 +76,14 @@ public class CountQueryIntegrationTest {
|
||||
int count = dsl.fetchCount(AUTHOR, conditions);
|
||||
Assert.assertEquals(1, count);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void givenValidData_whenFetchCountWithMultipleConditionsUsingAndOperator_thenSucceed() {
|
||||
int count = dsl.fetchCount(AUTHOR, AUTHOR.FIRST_NAME.equalIgnoreCase("Bryan").and(AUTHOR.ID.notEqual(1)));
|
||||
Assert.assertEquals(1, count);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenValidData_whenFetchCountWithConditionsInVarargs_thenSucceed() {
|
||||
Condition firstCond = AUTHOR.FIRST_NAME.equalIgnoreCase("Bryan");
|
||||
|
||||
Reference in New Issue
Block a user