Skip to content

Commit 835253f

Browse files
committed
Dto Via JDK14 Records And JdbcTemplate
1 parent 0395400 commit 835253f

File tree

10 files changed

+275
-0
lines changed

10 files changed

+275
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
**[DTO Via JDK14 Records And Spring Data Query Builder Mechanism](https://github.com/AnghelLeonard/Hibernate-SpringBoot/tree/master/HibernateSpringBootDtoRecordConstructor)**
2+
3+
**Description:** Fetching more data than needed is prone to performance penalities. Using DTO allows us to extract only the needed data. In this application we rely on JDK14 Records feature and Spring Data Query Builder Mechanism.
4+
5+
From Openjdk JEP359:
6+
7+
*Records provide a compact syntax for declaring classes which are transparent holders for shallowly immutable data.*
8+
9+
**Key points:**
10+
Define the `AuthorDto` as:
11+
12+
`public record AuthorDto(String name, int age) implements Serializable {}`
13+
14+
-----------------------------------------------------------------------------------------------------------------------
15+
<table>
16+
<tr><td><b>If you need a deep dive into the performance recipes exposed in this repository then I am sure that you will love my book "Spring Boot Persistence Best Practices"</b></td><td><b>If you need a hand of tips and illustrations of 100+ Java persistence performance issues then "Java Persistence Performance Illustrated Guide" is for you.</b></td></tr>
17+
<tr><td>
18+
<a href="https://www.apress.com/us/book/9781484256251"><p align="left"><img src="https://github.com/AnghelLeonard/Hibernate-SpringBoot/blob/master/Spring%20Boot%20Persistence%20Best%20Practices.jpg" height="500" width="450"/></p></a>
19+
</td><td>
20+
<a href="https://leanpub.com/java-persistence-performance-illustrated-guide"><p align="right"><img src="https://github.com/AnghelLeonard/Hibernate-SpringBoot/blob/master/Java%20Persistence%20Performance%20Illustrated%20Guide.jpg" height="500" width="450"/></p></a>
21+
</td></tr></table>
22+
23+
-----------------------------------------------------------------------------------------------------------------------
24+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4+
<modelVersion>4.0.0</modelVersion>
5+
6+
<groupId>com.jpa</groupId>
7+
<artifactId>HibernateSpringBootDtoRecordJbcTemplate</artifactId>
8+
<version>1.0</version>
9+
<packaging>jar</packaging>
10+
11+
<name>HibernateSpringBootDtoRecordJbcTemplate</name>
12+
<description>JPA project for Spring Boot</description>
13+
14+
<parent>
15+
<groupId>org.springframework.boot</groupId>
16+
<artifactId>spring-boot-starter-parent</artifactId>
17+
<version>2.2.6.RELEASE</version>
18+
<relativePath/> <!-- lookup parent from repository -->
19+
</parent>
20+
21+
<properties>
22+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
23+
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
24+
<java.version>1.8</java.version>
25+
<maven.compiler.source>14</maven.compiler.source>
26+
<maven.compiler.target>14</maven.compiler.target>
27+
</properties>
28+
29+
<dependencies>
30+
<dependency>
31+
<groupId>org.springframework.boot</groupId>
32+
<artifactId>spring-boot-starter-data-jpa</artifactId>
33+
</dependency>
34+
<dependency>
35+
<groupId>org.springframework.boot</groupId>
36+
<artifactId>spring-boot-starter-jdbc</artifactId>
37+
</dependency>
38+
<dependency>
39+
<groupId>org.springframework.boot</groupId>
40+
<artifactId>spring-boot-starter-web</artifactId>
41+
</dependency>
42+
<dependency>
43+
<groupId>mysql</groupId>
44+
<artifactId>mysql-connector-java</artifactId>
45+
<scope>runtime</scope>
46+
</dependency>
47+
<dependency>
48+
<groupId>org.springframework.boot</groupId>
49+
<artifactId>spring-boot-starter-test</artifactId>
50+
<scope>test</scope>
51+
</dependency>
52+
</dependencies>
53+
54+
<build>
55+
<plugins>
56+
<plugin>
57+
<groupId>org.springframework.boot</groupId>
58+
<artifactId>spring-boot-maven-plugin</artifactId>
59+
</plugin>
60+
<plugin>
61+
<groupId>org.apache.maven.plugins</groupId>
62+
<artifactId>maven-compiler-plugin</artifactId>
63+
<version>3.8.1</version>
64+
<configuration>
65+
<release>14</release>
66+
<compilerArgs>
67+
<arg>--enable-preview</arg>
68+
</compilerArgs>
69+
<forceJavacCompilerUse>true</forceJavacCompilerUse>
70+
<parameters>true</parameters>
71+
</configuration>
72+
</plugin>
73+
<plugin>
74+
<groupId>org.apache.maven.plugins</groupId>
75+
<artifactId>maven-surefire-plugin</artifactId>
76+
<version>3.0.0-M3</version>
77+
<configuration>
78+
<argLine>--enable-preview</argLine>
79+
</configuration>
80+
</plugin>
81+
</plugins>
82+
</build>
83+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package com.bookstore;
2+
3+
import com.bookstore.jdbcTemplate.dto.AuthorDto;
4+
import java.util.List;
5+
import com.bookstore.service.BookstoreService;
6+
import org.springframework.boot.ApplicationRunner;
7+
import org.springframework.boot.SpringApplication;
8+
import org.springframework.boot.autoconfigure.SpringBootApplication;
9+
import org.springframework.context.annotation.Bean;
10+
11+
@SpringBootApplication
12+
public class MainApplication {
13+
14+
private final BookstoreService bookstoreService;
15+
16+
public MainApplication(BookstoreService bookstoreService) {
17+
this.bookstoreService = bookstoreService;
18+
}
19+
20+
public static void main(String[] args) {
21+
SpringApplication.run(MainApplication.class, args);
22+
}
23+
24+
@Bean
25+
public ApplicationRunner init() {
26+
return args -> {
27+
28+
List<AuthorDto> authors = bookstoreService.fetchAuthorsWithBooksViaJdbcTemplateToDto();
29+
30+
System.out.println("Number of authors:" + authors.size());
31+
32+
for (AuthorDto author : authors) {
33+
System.out.println("Author name: " + author.name()
34+
+ " | Age: " + author.age() + " | Books: " + author.books());
35+
}
36+
};
37+
}
38+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package com.bookstore.jdbcTemplate.dto;
2+
3+
import java.util.List;
4+
5+
public record AuthorDto(Long id, String name, int age, List books) {
6+
7+
public void addBook(BookDto book) {
8+
books().add(book);
9+
}
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package com.bookstore.jdbcTemplate.dto;
2+
3+
import java.sql.ResultSet;
4+
import java.util.ArrayList;
5+
import java.util.HashMap;
6+
import java.util.List;
7+
import java.util.Map;
8+
import org.springframework.jdbc.core.JdbcTemplate;
9+
import org.springframework.stereotype.Repository;
10+
import org.springframework.transaction.annotation.Transactional;
11+
12+
@Repository
13+
@Transactional(readOnly = true)
14+
public class AuthorExtractor {
15+
16+
private final JdbcTemplate jdbcTemplate;
17+
18+
public AuthorExtractor(JdbcTemplate jdbcTemplate) {
19+
this.jdbcTemplate = jdbcTemplate;
20+
}
21+
22+
public List<AuthorDto> extract() {
23+
24+
String sql = "SELECT a.id, a.name, a.age, b.id, b.title "
25+
+ "FROM author a INNER JOIN book b ON a.id = b.author_id";
26+
27+
List<AuthorDto> result = jdbcTemplate.query(sql, (ResultSet rs) -> {
28+
29+
final Map<Long, AuthorDto> authorsMap = new HashMap<>();
30+
while (rs.next()) {
31+
Long authorId = (rs.getLong("id"));
32+
AuthorDto author = authorsMap.get(authorId);
33+
if (author == null) {
34+
author = new AuthorDto(rs.getLong("id"), rs.getString("name"),
35+
rs.getInt("age"), new ArrayList());
36+
}
37+
38+
BookDto book = new BookDto(rs.getLong("id"), rs.getString("title"));
39+
40+
author.addBook(book);
41+
authorsMap.putIfAbsent(author.id(), author);
42+
}
43+
44+
return new ArrayList<>(authorsMap.values());
45+
});
46+
47+
return result;
48+
}
49+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package com.bookstore.jdbcTemplate.dto;
2+
3+
import java.io.Serializable;
4+
5+
public record BookDto(Long id, String title) {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.bookstore.service;
2+
3+
import com.bookstore.jdbcTemplate.dto.AuthorDto;
4+
import com.bookstore.jdbcTemplate.dto.AuthorExtractor;
5+
import java.util.List;
6+
import org.springframework.stereotype.Service;
7+
8+
@Service
9+
public class BookstoreService {
10+
11+
private final AuthorExtractor authorExtractor;
12+
13+
public BookstoreService(AuthorExtractor authorExtractor) {
14+
this.authorExtractor = authorExtractor;
15+
}
16+
17+
public List<AuthorDto> fetchAuthorsWithBooksViaJdbcTemplateToDto() {
18+
19+
return authorExtractor.extract();
20+
}
21+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
spring.datasource.url=jdbc:mysql://localhost:3306/bookstoredb?createDatabaseIfNotExist=true
2+
spring.datasource.username=root
3+
spring.datasource.password=root
4+
5+
spring.jpa.hibernate.ddl-auto=create
6+
spring.jpa.show-sql=true
7+
8+
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
9+
10+
spring.datasource.initialization-mode=always
11+
spring.datasource.platform=mysql
12+
13+
spring.jpa.open-in-view=false
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
DELETE FROM book;
2+
DELETE FROM author;
3+
4+
INSERT INTO author (age, name, genre, id) VALUES (23, "Mark Janel", "Anthology", 1);
5+
INSERT INTO author (age, name, genre, id) VALUES (43, "Olivia Goy", "Horror", 2);
6+
INSERT INTO author (age, name, genre, id) VALUES (51, "Quartis Young", "Anthology", 3);
7+
INSERT INTO author (age, name, genre, id) VALUES (34, "Joana Nimar", "History", 4);
8+
9+
INSERT INTO book (isbn, title, author_id, id) VALUES ("001-JN", "A History of Ancient Prague", 4, 1);
10+
INSERT INTO book (isbn, title, author_id, id) VALUES ("002-JN", "A People's History", 4, 2);
11+
INSERT INTO book (isbn, title, author_id, id) VALUES ("001-MJ", "The Beatles Anthology", 1, 3);
12+
INSERT INTO book (isbn, title, author_id, id) VALUES ("001-OG", "Carrie", 2, 4);
13+
INSERT INTO book (isbn, title, author_id, id) VALUES ("002-OG", "House Of Pain", 2, 5);
14+
INSERT INTO book (isbn, title, author_id, id) VALUES ("003-JN", "History Of 2020", 4, 6);
15+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
CREATE TABLE author (
2+
id bigint(20) NOT NULL AUTO_INCREMENT,
3+
age int(11) NOT NULL,
4+
genre varchar(255) DEFAULT NULL,
5+
name varchar(255) DEFAULT NULL,
6+
PRIMARY KEY (id)
7+
);
8+
9+
CREATE TABLE book (
10+
id bigint(20) NOT NULL AUTO_INCREMENT,
11+
isbn varchar(255) DEFAULT NULL,
12+
title varchar(255) DEFAULT NULL,
13+
author_id bigint(20) DEFAULT NULL,
14+
PRIMARY KEY (id),
15+
KEY FKklnrv3weler2ftkweewlky958 (author_id),
16+
CONSTRAINT FKklnrv3weler2ftkweewlky958 FOREIGN KEY (author_id) REFERENCES author (id)
17+
);

0 commit comments

Comments
 (0)