jooq_SpringBoot:与JOOQ合作

jooq

在上一篇文章SpringBoot:与MyBatis一起工作中,我们学习了如何使用SpringBoot MyBatis Starter快速启动并运行Spring和MyBatis。 在本文中,我们将学习如何使用SpringBoot JOOQ Starter。

JOOQ(面向Java对象的查询)是包含SQL的持久性框架。

JOOQ提供以下功能:

  • 使用DSL API构建Typesafe SQL
  • 使用代码生成引用类型安全的数据库对象
  • 易于使用的API用于查询和数据提取
  • SQL记录和调试等

SpringBoot提供了一个启动程序spring-boot-starter-jooq ,以便能够与JOOQ快速集成。

在本文中,我们将逐步介绍如何使用spring-boot-starter-jooq

步骤1:创建SpringBoot Maven项目

创建一个基于SpringBoot Maven的项目并配置spring-boot-starter-jooq依赖项。

<?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/maven-v4_0_0.xsd"><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 / main / resources / schema.sql

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 / main / resources / data.sql

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) 
values(1, 1, 'User1', 'user1@gmail.com', 'This is comment 1 on post 1', '2016-01-07');insert into comments(id, post_id, name, email, content, created_on) 
values(2, 1, 'User2', 'user2@gmail.com', 'This is comment 2 on post 1', '2016-01-07');insert into comments(id, post_id, name, email, content, created_on) 
values(3, 2, 'User1', 'user1@gmail.com', 'This is comment 1 on post 2', '2016-01-07');

步骤3:配置JOOQ Maven Codegen插件以生成数据库工件

我们将使用Maven配置文件根据数据库类型配置jooq-codegen-maven配置属性。

<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>

我们已经使用适当的JDBC配置参数配置了两个配置文件( h2mysql )。

我们已指定生成代码工件,并将其放置gensrc / main / java目录下的 com.sivalabs.demo.jooq.domain包中。

我们可以如下运行maven激活h2mysql配置文件:

mvn clean install -P h2 (or)
mvn clean install -P mysql

步骤4:配置Maven build-helper-maven-plugin插件以将生成的源添加为sources文件夹

我们将配置build-helper-maven-plugin插件,以便maven将添加JOOQ生成的代码驻留在
gensrc / main / java目录作为源文件夹。

<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生成的数据库工件与数据库进行对话。

public class Post
{private Integer id;private String title;private String content;private Timestamp createdOn;private List<Comment> comments = new ArrayList<>();//setters & getters}
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实施数据持久化方法,如下所示。

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
{@Autowiredprivate 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测试。

@SpringBootApplication
public class SpringbootJooqDemoApplication
{public static void main(String[] args) {SpringApplication.run(SpringbootJooqDemoApplication.class, args);}
}
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(SpringbootJooqDemoApplication.class)
public class SpringbootJooqDemoApplicationTests
{@Autowiredprivate BlogService blogService;@Testpublic void findAllPosts()  {List<Post> posts = blogService.getAllPosts();assertNotNull(posts);assertTrue(!posts.isEmpty());for (Post post : posts){System.err.println(post);}}@Testpublic void findPostById()  {Post post = blogService.getPost(1);assertNotNull(post);System.out.println(post);List<Comment> comments = post.getComments();System.out.println(comments);}@Testpublic 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());}@Testpublic void createComment() {Integer postId = 1;Comment comment = new Comment(0, postId, "User4", "user4@gmail.com", "This is my new comment on post1", 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("user4@gmail.com", comm.getEmail());assertEquals("This is my new comment on post1", comm.getContent());}}}}

假设您已经使用H2概要文件生成了代码,那么我们可以在不进行任何其他配置的情况下运行JUnit测试。

但是,如果您已使用mysql配置文件生成了代码,则必须在application.properties中配置以下属性。

spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.username=root
spring.datasource.password=adminspring.jooq.sql-dialect=MYSQL


请注意,我们应该为数据库使用正确的SqlDialect ,否则在运行时可能会遇到SQL语法错误。

  • 您可以在我的Github存储库中找到本文的源代码
    https://github.com/sivaprasadreddy/springboot-tutorials/tree/master/springboot-jooq-demo

有关JOOQ的更多信息,请访问http://www.jooq.org/learn/

翻译自: https://www.javacodegeeks.com/2016/03/springboot-working-jooq.html

jooq

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/336245.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【WebRTC---入门篇】(十二)WebRTC传输协议

浏览器协议栈(左图传统HTTP 右图WebRTC) RTP/SRTP RTP是未加密的数据,SRTP是加密后的数据。 RTP协议

android4.0支持m3u8格式,【报Bug】安卓下无法播放M3U8格式音频,报错

详细问题描述(DCloud产品不会有明显的bug&#xff0c;所以你遇到的问题大都是在特定环境下才能重现的问题&#xff0c;请仔细描述你的环境和重现方式&#xff0c;否则DCloud很难排查解决你的问题)[内容]安卓下小程序音频播放器播放&#xff2d;3&#xff35;8格式文件报错重现步…

springcloud官方文档_通俗易懂!Spring Cloud简介:官方文档翻译版

什么是微服务&#xff1f;"微服务架构是一种架构模式&#xff0c;它提倡将单一应用程序划分成一组小的服务&#xff0c;服务之间相互协调、互相配合&#xff0c;为用户提供最终价值。每个服务运行在其独立的进程中&#xff0c;服务和服务之间采用轻量级的通信机制相互沟通…

【RTMP协议分析与抓包实测】

传输协议 RTMP基本通讯 RTMP基于TCP之上传输 TCP三次握手,相关文章链接&#xff0c;TCP三次握手流程 进行握手 c- --> s 发送c0c1 c ---> s 发送c2 s ---> c 发送s0s1s2 建立RTMP连接 真实建立连接的场景 c- --> s RTMP发送connect建立连接 s ---> c 协商(滑动…

autowired_@Autowired所有的东西!

autowired最近&#xff0c;我写了Autowired注释 &#xff0c;它使我们可以编写更少的代码&#xff0c;从而使我们的生活更轻松 。 但是&#xff0c;使用它通常会使您的设计更加复杂。 尤其是当我们谈论在类的属性上使用它时。 它更容易违反 单一责任原则 。 这样可以更容易地注…

android message 代码,Android Handler移除Message详解及实例代码

Android Handler移除Message详解问题&#xff1a;1.removeMessage(what)函数是否只能移除对应what值的Message&#xff1f;2.对于Delayed发送的Message&#xff0c;能否提前remove&#xff1f;代码测试&#xff1a;package javine.k.testhandler;import android.app.Activity;i…

python中如何调用或修改元组中的元素_python 元组的使用方法

元组——tuple 列表非常适合用于存储在程序运行期间可能变化的数据集。 列表是可以修改的&#xff0c;但元组是不可修改的 Python将不能修改的值称为不可变的&#xff0c;而不可变的列表被称为元组 1. 元组的创建和删除 &#xff08;1&#xff09;使用赋值运算符直接创建元组 语…

【WebRTC---入门篇】(十三)WebRTC音视频数据采集

音视频采集API false表示不采集,true表示采集 WebRTC API适配 获取音视频设备的访问权限 通过 return navigator.mediaDevices.enumerateDevices();/*返回一个promise,为了获取音视频的权限*/ 视频约束

android按钮点击toast,关于button点击事件中setOnClick等元素的解读以及方法?以及toast的位置以及作用?...

此文末参考链接&#xff1a;此段代码的教程以及使用接口的方式、switch语句的教程链接为链接1.汇总里说的有更多的实现方法&#xff0c;为链接2。文中链接为视觉统一&#xff0c;链接均于文末&#xff0c;以上为方便文中跳转&#xff0c;加了文中的跳转链接。以下代码为我学习b…

java用什么编译器_Java用Java编译

java用什么编译器在上一篇文章中&#xff0c;我写了关于如何在运行时生成代理的内容&#xff0c;我们已经了解到生成Java源代码的程度。 但是&#xff0c;要使用该类&#xff0c;必须对其进行编译&#xff0c;并将生成的字节码加载到内存中。 那是“编译”时间。 幸运的是&…

app登录界面背景 css_计算机毕业设计中Java web实现简登录页面(MyBatis+jsp+servlet+html+css+javascript)...

点击上方“蓝字”&#xff0c;关注我们.本文利用MyBatisjspservlethtmlcssjavascript实现了一个简单的登录页面。对用户输入的用户名和密码就行校验&#xff0c;校验通过则登录成功&#xff0c;密码和用户信息保存在mysql表中&#xff0c;通过MyBatis访问(MyBatis相关知识可参考…

android strm,Android 关于so文件的随记

1.背景&#xff1a;项目中要集成商汤的活体检测sdk&#xff0c;2.遇到的问题&#xff1a;商汤提供的demo 可以正常运行&#xff0c;但是将sdk集成至项目中时一直报错&#xff0c;但是商汤侧却没办法提供具体的报错原因3.解决问题&#xff1a;反编译商汤的源码发现&#xff0c;报…

工业互联网二级节点建设_建设者还是二传手?

工业互联网二级节点建设不用说&#xff0c;每个对象都需要先创建才能使用。 无论我们是在谈论域&#xff0c;框架&#xff0c;库还是任何其他类型的类&#xff0c;都没有关系。 当您的代码是面向对象的时&#xff0c;这些类仅是对象的定义。 创建对象之前&#xff0c;不能使用它…

android 指针是什么意思,Android系统的智能指针(轻量级指针、强指针和弱指针)的实现原理分析(3)...

提供引用计数器的类RefBase我们就暂时介绍到这里&#xff0c;后面我们再结合智能指针类一起分析&#xff0c;现在先来看看强指针类和弱指针类的定义。强指针类的定义我们在前面介绍轻量级指针的时候已经见到了&#xff0c;就是sp类了&#xff0c;这里就不再把它的代码列出来了。…

【WebRTC---入门篇】(十五)WebRTC信令服务器实现

如何使用socket.io发送消息 io代表整个节点

气味识别应用_代码气味–第二部分

气味识别应用在上一篇文章《代码气味–第一部分》中 &#xff0c;我谈到了膨胀器&#xff1a;它们是代码气味&#xff0c;可以识别为长方法&#xff0c;大型类&#xff0c;原始痴迷&#xff0c;长参数列表和数据块。 在这一篇中&#xff0c;我想深入研究面向对象的滥用者和变更…

activiti高亮显示图片_如今透明LED显示屏成为广告橱窗,它们之间有什么关联?...

如今我们在街道行走时&#xff0c;我们就会看到各种玻璃橱窗&#xff0c;这是商家想利用橱窗进行不同产品宣传角度。其实无论是海报、灯箱或是实物展示&#xff0c;这些都是商家通过橱窗广告进行来吸引消费者&#xff0c;而现在是5G时代到来使橱窗数字化营销成为了一种新的趋势…

theme editor android,谷歌宣布将于下月停用 Material Theme Editor

使用 Material Theme Editor&#xff0c;开发人员可创建和自定义 Material 主题&#xff0c;包括颜色、形状、版式等等。在 Material Theme Editor 中&#xff0c;可根据不同部分依次选择颜色&#xff0c;并应用于所有组件&#xff0c;还可调整对比度&#xff0c;根据单一颜色自…

【WebRTC---入门篇】(十六)端对端1V1传输基本流程

RTCPeerConnection 媒体协商 setLocalDescription方法 ,收集所有候选者。 setRemoteDescription方法, 放到远端的描述槽中。 协商状态变化