В моей предыдущей статье SpringBoot: Работа с MyBatis мы узнали, как использовать SpringBoot MyBatis Starter для быстрого начала работы с Spring и MyBatis. В этой статье мы узнаем, как использовать SpringBoot JOOQ Starter.
JOOQ (Java Object-Oriented Querying) — это постоянная среда, охватывающая SQL.
JOOQ предоставляет следующие возможности:
- Построение Typesafe SQL с использованием DSL API
- Обращение к объектам базы данных Typesafe с использованием Code Generation
- Простой в использовании API для запросов и извлечения данных
- Логирование и отладка SQL и т. Д.
SpringBoot предоставляет стартер spring-boot-starter-jooq для быстрой интеграции с JOOQ.
В этой статье мы увидим, как использовать spring-boot-starter-jooq, используя пошаговый подход.
Шаг 1. Создание проекта SpringBoot Maven
Создайте проект на основе SpringBoot maven и настройте зависимость spring-boot-starter-jooq .
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
<? xml version = "1.0" encoding = "UTF-8" ?> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 < modelVersion >4.0.0</ modelVersion > < groupId >com.sivalabs</ groupId > < artifactId >springboot-jooq-demo</ artifactId > < packaging >jar</ packaging > < version >1.0-SNAPSHOT</ version > < parent > < groupId >org.springframework.boot</ groupId > < artifactId >spring-boot-starter-parent</ artifactId > < version >1.3.3.RELEASE</ version > </ parent > < properties > < project.build.sourceEncoding >UTF-8</ project.build.sourceEncoding > < java.version >1.8</ java.version > </ properties > < build > < plugins > < plugin > < groupId >org.springframework.boot</ groupId > < artifactId >spring-boot-maven-plugin</ artifactId > </ plugin > </ plugins > </ build > < dependencies > < dependency > < groupId >org.springframework.boot</ groupId > < artifactId >spring-boot-starter-test</ artifactId > < scope >test</ scope > </ dependency > < dependency > < groupId >org.springframework.boot</ groupId > < artifactId >spring-boot-starter-jooq</ artifactId > </ dependency > < dependency > < groupId >com.h2database</ groupId > < artifactId >h2</ artifactId > </ dependency > < dependency > < groupId >mysql</ groupId > < artifactId >mysql-connector-java</ artifactId > </ dependency > </ dependencies > </ project > |
Сначала мы собираемся использовать базу данных H2 в памяти, позже мы увидим, как использовать MySQL.
Шаг 2: Создайте сценарии инициализации базы данных.
Мы собираемся создать простую базу данных с 2 таблицами.
SRC / главная / ресурсы / schema.sql
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
|
DROP TABLE IF EXISTS POSTS; CREATE TABLE POSTS ( ID int ( 11 ) NOT NULL AUTO_INCREMENT, TITLE varchar( 200 ) NOT NULL, CONTENT LONGTEXT DEFAULT NULL, CREATED_ON datetime DEFAULT NULL, PRIMARY KEY (ID) ); DROP TABLE IF EXISTS COMMENTS; CREATE TABLE COMMENTS ( ID int ( 11 ) NOT NULL AUTO_INCREMENT, POST_ID int ( 11 ) NOT NULL, NAME varchar( 200 ) NOT NULL, EMAIL varchar( 200 ) NOT NULL, CONTENT LONGTEXT DEFAULT NULL, CREATED_ON datetime DEFAULT NULL, PRIMARY KEY (ID), FOREIGN KEY (POST_ID) REFERENCES POSTS(ID) ); |
Мы будем заполнять некоторые примеры данных, используя скрипт data.sql .
SRC / главная / ресурсы / data.sql
01
02
03
04
05
06
07
08
09
10
11
12
|
insert into posts(id, title, content, created_on) values( 1 , 'Post 1' , 'This is post 1' , '2016-01-03' ); insert into posts(id, title, content, created_on) values( 2 , 'Post 2' , 'This is post 2' , '2016-01-05' ); insert into posts(id, title, content, created_on) values( 3 , 'Post 3' , 'This is post 3' , '2016-01-07' ); insert into comments(id, post_id, name, email, content, created_on) insert into comments(id, post_id, name, email, content, created_on) insert into comments(id, post_id, name, email, content, created_on) |
Шаг 3. Настройте плагин JOOQ Maven Codegen для создания артефактов базы данных.
Мы будем использовать профили Maven для настройки свойств конфигурации jooq-codegen-maven в зависимости от типа базы данных.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
|
< profiles > < profile > < id >h2</ id > < build > < plugins > < plugin > < groupId >org.jooq</ groupId > < artifactId >jooq-codegen-maven</ artifactId > < executions > < execution > < goals > < goal >generate</ goal > </ goals > </ execution > </ executions > < dependencies > < dependency > < groupId >com.h2database</ groupId > < artifactId >h2</ artifactId > < version >${h2.version}</ version > </ dependency > </ dependencies > < configuration > < jdbc > < driver >org.h2.Driver</ driver > < url >jdbc:h2:~/springbootjooq</ url > </ jdbc > < generator > < name >org.jooq.util.DefaultGenerator</ name > < database > < name >org.jooq.util.h2.H2Database</ name > < includes >.*</ includes > < excludes /> < inputSchema >PUBLIC</ inputSchema > </ database > < target > < packageName >com.sivalabs.demo.jooq.domain</ packageName > < directory >gensrc/main/java</ directory > </ target > </ generator > </ configuration > </ plugin > </ plugins > </ build > </ profile > < profile > < id >mysql</ id > < build > < plugins > < plugin > < groupId >org.jooq</ groupId > < artifactId >jooq-codegen-maven</ artifactId > < executions > < execution > < goals > < goal >generate</ goal > </ goals > </ execution > </ executions > < dependencies > < dependency > < groupId >mysql</ groupId > < artifactId >mysql-connector-java</ artifactId > < version >${mysql.version}</ version > </ dependency > </ dependencies > < configuration > < jdbc > < driver >com.mysql.jdbc.Driver</ driver > < url >jdbc:mysql://localhost:3306/test</ url > < user >root</ user > < password >admin</ password > </ jdbc > < generator > < name >org.jooq.util.DefaultGenerator</ name > < database > < name >org.jooq.util.mysql.MySQLDatabase</ name > < includes >.*</ includes > < excludes /> < inputSchema >test</ inputSchema > </ database > < target > < packageName >com.sivalabs.demo.jooq.domain</ packageName > < directory >gensrc/main/java</ directory > </ target > </ generator > </ configuration > </ plugin > </ plugins > </ build > </ profile > </ profiles > |
Мы настроили два профиля ( h2 и mysql ) с соответствующими параметрами конфигурации JDBC.
Мы указали, что нужно сгенерировать артефакты кода и поместить их в пакет com.sivalabs.demo.jooq.domain в каталоге gensrc / main / java .
Мы можем запустить сборку maven, активирующую профиль h2 или mysql, следующим образом:
1
|
mvn clean install -P h2 (or) |
1
|
mvn clean install -P mysql |
Шаг 4: Настройте плагин Maven build-helper-maven-plugin для добавления сгенерированного источника в качестве папки с исходными текстами
Мы настроим плагин build-helper-maven- plugin таким образом, чтобы maven добавлял сгенерированный JOOQ код, находящийся в
Каталог gensrc / main / java в качестве исходной папки.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
|
< plugin > < groupId >org.codehaus.mojo</ groupId > < artifactId >build-helper-maven-plugin</ artifactId > < executions > < execution > < phase >generate-sources</ phase > < goals > < goal >add-source</ goal > </ goals > < configuration > < sources > < source >gensrc/main/java</ source > </ sources > </ configuration > </ execution > </ executions > </ plugin > |
Шаг 5: Создайте доменные объекты.
Мы можем использовать эти доменные объекты для передачи данных через слой и сгенерированные JOOQ артефакты базы данных для связи с базой данных.
01
02
03
04
05
06
07
08
09
10
|
public class Post { private Integer id; private String title; private String content; private Timestamp createdOn; private List<Comment> comments = new ArrayList<>(); //setters & getters } |
01
02
03
04
05
06
07
08
09
10
|
public class Comment { private Integer id; private Post post; private String name; private String email; private String content; private Timestamp createdOn; //setters & getters } |
Шаг 6: Реализуйте методы сохранения данных, используя JOOQ, следующим образом.
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
|
package com.sivalabs.demo; import static com.sivalabs.demo.jooq.domain.tables.Posts.POSTS; import static com.sivalabs.demo.jooq.domain.tables.Comments.COMMENTS; import java.sql.Timestamp; import java.util.ArrayList; import java.util.List; import org.jooq.DSLContext; import org.jooq.Record; import org.jooq.Result; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import com.sivalabs.demo.entities.Comment; import com.sivalabs.demo.entities.Post; import com.sivalabs.demo.jooq.domain.tables.records.CommentsRecord; import com.sivalabs.demo.jooq.domain.tables.records.PostsRecord; @Service @Transactional public class BlogService { @Autowired private DSLContext dsl; public Post createPost(Post post){ PostsRecord postsRecord = dsl.insertInto(POSTS) .set(POSTS.TITLE, post.getTitle()) .set(POSTS.CONTENT, post.getContent()) .set(POSTS.CREATED_ON, post.getCreatedOn()) .returning(POSTS.ID) .fetchOne(); post.setId(postsRecord.getId()); return post; } public List<Post> getAllPosts(){ List<Post> posts = new ArrayList<>(); Result<Record> result = dsl.select().from(POSTS).fetch(); for (Record r : result) { posts.add(getPostEntity(r)); } return posts ; } public Post getPost(Integer postId){ Record record = dsl.select(). from(POSTS) .where(POSTS.ID.eq(postId)) .fetchOne(); if (record != null ) { Post post = getPostEntity(record); Result<Record> commentRecords = dsl.select(). from(COMMENTS) .where(COMMENTS.POST_ID.eq(postId)) .fetch(); for (Record r : commentRecords) { post.addComment(getCommentEntity(r)); } return post; } return null ; } public Comment createComment(Comment comment){ CommentsRecord commentsRecord = dsl.insertInto(COMMENTS) .set(COMMENTS.POST_ID, comment.getPost().getId()) .set(COMMENTS.NAME, comment.getName()) .set(COMMENTS.EMAIL, comment.getEmail()) .set(COMMENTS.CONTENT, comment.getContent()) .set(COMMENTS.CREATED_ON, comment.getCreatedOn()) .returning(COMMENTS.ID) .fetchOne(); comment.setId(commentsRecord.getId()); return comment; } public void deleteComment(Integer commentId){ dsl.deleteFrom(COMMENTS) .where(COMMENTS.ID.equal(commentId)) .execute(); } private Post getPostEntity(Record r){ Integer id = r.getValue(POSTS.ID, Integer. class ); String title = r.getValue(POSTS.TITLE, String. class ); String content = r.getValue(POSTS.CONTENT, String. class ); Timestamp createdOn = r.getValue(POSTS.CREATED_ON, Timestamp. class ); return new Post(id, title, content, createdOn); } private Comment getCommentEntity(Record r) { Integer id = r.getValue(COMMENTS.ID, Integer. class ); Integer postId = r.getValue(COMMENTS.POST_ID, Integer. class ); String name = r.getValue(COMMENTS.NAME, String. class ); String email = r.getValue(COMMENTS.EMAIL, String. class ); String content = r.getValue(COMMENTS.CONTENT, String. class ); Timestamp createdOn = r.getValue(COMMENTS.CREATED_ON, Timestamp. class ); return new Comment(id, postId, name, email, content, createdOn); } } |
Обратите внимание, что мы автоматически подключаем экземпляр DSLContext к нашему Spring Bean и используем его для построения запросов TypeSafe.
Шаг 7: Создайте класс точки входа и тест JUnit.
1
2
3
4
5
6
7
|
@SpringBootApplication public class SpringbootJooqDemoApplication { public static void main(String[] args) { SpringApplication.run(SpringbootJooqDemoApplication. class , args); } } |
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
|
@RunWith (SpringJUnit4ClassRunner. class ) @SpringApplicationConfiguration (SpringbootJooqDemoApplication. class ) public class SpringbootJooqDemoApplicationTests { @Autowired private BlogService blogService; @Test public void findAllPosts() { List<Post> posts = blogService.getAllPosts(); assertNotNull(posts); assertTrue(!posts.isEmpty()); for (Post post : posts) { System.err.println(post); } } @Test public void findPostById() { Post post = blogService.getPost( 1 ); assertNotNull(post); System.out.println(post); List<Comment> comments = post.getComments(); System.out.println(comments); } @Test public void createPost() { Post post = new Post( 0 , "My new Post" , "This is my new test post" , new Timestamp(System.currentTimeMillis())); Post savedPost = blogService.createPost(post); Post newPost = blogService.getPost(savedPost.getId()); assertEquals( "My new Post" , newPost.getTitle()); assertEquals( "This is my new test post" , newPost.getContent()); } @Test public void createComment() { Integer postId = 1 ; Comment comment = new Comment( 0 , postId, "User4" , new Timestamp(System.currentTimeMillis())); Comment savedComment = blogService.createComment(comment); Post post = blogService.getPost(postId); List<Comment> comments = post.getComments(); assertNotNull(comments); for (Comment comm : comments) { if (savedComment.getId() == comm.getId()){ assertEquals( "User4" , comm.getName()); assertEquals( "This is my new comment on post1" , comm.getContent()); } } } } |
Предполагая, что вы сгенерировали код, используя профиль H2 , мы можем запустить тест JUnit без дальнейшей настройки.
Но если вы сгенерировали код, используя профиль mysql, вам придется настроить следующие свойства в application.properties .
1
2
3
4
5
6
|
spring.datasource.driver- class -name=com.mysql.jdbc.Driver spring.datasource.url=jdbc:mysql: //localhost:3306/test spring.datasource.username=root spring.datasource.password=admin spring.jooq.sql-dialect=MYSQL |
Обратите внимание, что мы должны использовать правильный SqlDialect для базы данных, иначе вы можете получить ошибки синтаксиса SQL во время выполнения.
- Вы можете найти исходный код этой статьи в моем репозитории Github.
https://github.com/sivaprasadreddy/springboot-tutorials/tree/master/springboot-jooq-demo
Для получения дополнительной информации о JOOQ вы можете посмотреть на http://www.jooq.org/learn/
Ссылка: | SpringBoot: Работа с JOOQ от нашего партнера по JCG Шивы Редди в блоге « Мои эксперименты по технологии» . |