SpringCloud系列----->SpringBoot项目中整合jooq和postgresql数据库

本文涉及的产品
云原生数据库 PolarDB PostgreSQL 版,标准版 2核4GB 50GB
云原生数据库 PolarDB MySQL 版,通用型 2核8GB 50GB
简介: 前言: 公司的BI项目采取的是SpringBoot + Jooq + postgresql 组织形势,现在将这个配置过程,详细记录下来。 Jooq和MyBatis和spring data jpa作用是一样的,都是用来链接操作数据库的。
前言:
    公司的BI项目采取的是SpringBoot + Jooq + postgresql 组织形势,现在将这个配置过程,详细记录下来。
    Jooq和MyBatis和spring data jpa作用是一样的,都是用来链接操作数据库的。
    Jooq的优点:
        (1)、DSL(Domain Specific Language )风格,代码够简单和清晰。遇到不会写的sql可以充分利用IDEA代码提示功能轻松完成。
        (2)、保留了传统ORM 的优点,简单操作性,安全性,类型安全等。不需要复杂的配置,并且可以利用Java 8 Stream API 做更加复杂的数据转换。
        (3)、支持主流的RDMS和更多的特性,如self-joins,union,存储过程,复杂的子查询等等。
        (4)、丰富的Fluent API和完善文档。
        (5)、runtime schema mapping 可以支持多个数据库schema访问。简单来说使用一个连接池可以访问N个DB schema,使用比较多的就是SaaS应用的多租户场景。
    好了,不多啰嗦了,Jooq的详细文档还是请大家,看官方文档:https://www.jooq.org/
    公司的项目是采用gradle 组织的,gradle和maven是一样的,但是gradle的配置文件更清晰,maven的xml组织形式,啰嗦长,看着就晕,不简洁。有关gradle和maven的相关详细使用方法的请参考gradle和maven的官网。
    闲话少劳聊,直接上build.gradle代码,在代码注释中详细说明每个配置的详细的作用:
    
    plugins {
      id 'org.springframework.boot' version '2.1.3.RELEASE'   #springboot版本
        id 'java'                                               #标识是java项目
         id 'nu.studer.jooq' version '3.0.3'                     #jooq的版本号
    }

    apply plugin: 'io.spring.dependency-management'
    apply plugin: 'jacoco'                                        #引入生成文档的jar包
    group = 'com.jingdata.asset.manage.bi'                        #略
    version = '0.0.1-SNAPSHOT'                                    #略
    sourceCompatibility = '1.8'                                   #java版本

    repositories {
      mavenLocal()
      mavenCentral()
    }

    dependencies {
            implementation 'org.springframework.boot:spring-boot-starter-data-redis'
            implementation 'org.springframework.boot:spring-boot-starter-jooq'      #springboot对jooq直接支持,jooq的springboot的starter
            implementation 'org.springframework.boot:spring-boot-starter-web'
            implementation 'org.springframework.boot:spring-boot-starter-aop'
            implementation 'org.springframework.boot:spring-boot-starter-actuator'
            implementation 'org.aspectj:aspectjrt:1.6.11'
            implementation 'org.aspectj:aspectjweaver:1.6.11'
            implementation 'cglib:cglib:2.1'
            implementation 'org.springframework:spring-aop:4.3.9.RELEASE'
            implementation 'io.springfox:springfox-swagger2:2.8.0'
            implementation 'io.springfox:springfox-swagger-ui:2.8.0'
            compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.1'
            compile("org.togglz:togglz-spring-boot-starter:2.6.1.Final")
            runtimeOnly 'org.postgresql:postgresql'                                  #postgresql的链接支持
            testImplementation 'org.springframework.boot:spring-boot-starter-test'
            compileOnly 'org.projectlombok:lombok:1.18.2'
            jooqRuntime 'postgresql:postgresql:9.1-901-1.jdbc4'                       #postgresql的链接支持
    }
  
    test {
     include '**/*Test.class'                                            #单元测试命令,执行gradle   test命令只会执行测试文件中以Test结尾的文件中的所有的测试方法。
    }
  
    task testInteg(type: Test) {    
      include '**/*Integ.class'                                          #单元测试命令,执行gradle testInteg命令只会执行测试文件中以Integ结尾的文件中的所有的测试方法。
    
    #之所以需要gradle test , gradle testInteg两个命令,是因为有些我们这里需要区分涉及外部依赖(redis,mongodb,pg数据库,elasticsearch等)的单元测试,和不涉及外部依赖的单元测试(内存中执行就行),几十个组件的集成测试时,组件之间彼此需要依赖彼此产生的数据时,h2之类的内存数据库,就不能满足测试需要了,跑一次gradle testInteg 命令,把需要的数据保存在redis,mongodb,pg数据库,elasticsearch 等中。
    #公司的项目要求,每次git push提交代码和jenkins部署项目的时候需要执行一下gradle test 命令,确认修改的代码没有破坏以前的功能。
    #测试同事在整个系统集成的时候,需要执行gradle test , gradle testInteg两个命令,其中gradle test经常执行,gradle testInteg 在系统几十个模块集成的时候,会执行。
    
    }
    
    #jooq配置,自动生成数据库表和字段的对应关系的一系列的java class文件
    jooq {
    version = '3.11.9'
    edition = 'OSS'
    sample(sourceSets.main) {
    jdbc {     
            driver = 'org.postgresql.Driver'                      #jooq链接数据库的驱动 
            url = 'jdbc:postgresql://127.0.0.1:5432/invest111'    #数据库链接地址
            user = 'inves111'                                     #连接数据库的用户名
            password = 'invest111'                                #连接数据库的密码
         }
    generator {
        name = 'org.jooq.codegen.DefaultGenerator'
        strategy {
            name = 'org.jooq.codegen.DefaultGeneratorStrategy'
            // ...
        }
        database() {
                    name = 'org.jooq.meta.postgres.PostgresDatabase'
                    inputSchema = 'public'                     #只生成public schema中的表
                        includes='paas_bi_.*|paas_datarights_.*|paas_mt_.*|paas_auth_.*|paas_org_.*'    #只需要paas_bi 、 paas_datarights、paas_mt、paas_auth、paas_org 开头的一系列的表。
            
                    } 
        generate() {}
        target {
                packageName = 'com.jingdata.asset.manage.bi.assetmanagesystem.bidb'                          #生成文件夹的名字
                directory = 'src/main/java'                   #生成文件所在的目录
                  }
            }
        }
    }

  settings.gradle文件的内容:
  
  pluginManagement {
    repositories {
    gradlePluginPortal()
    }
  }
  rootProject.name = 'asset-manage-system'       
  
  所有这些配置完成后,就会如图所示,执行这个命令,就会把数据库中的表自动生成出来:
  ![1564371259390](https://yqfile.alicdn.com/23bcb12200ad1136ea627ee340584ecdcae8e30d.jpeg)

  我们执行gradle  test命令结果如下:
  ![2222](https://yqfile.alicdn.com/0457c862e6b19e4203ba81d8e772391c194d0730.jpeg)
  
  会在项目的目录下生成一个build文件夹,这个目录下会有本次执行单元测试生成的单元测试报告,单元测试报告打开后是这样一个效果:
  ![4444](https://yqfile.alicdn.com/4d75c24182206129c9e068eaf038c909b314981b.jpeg)

  gradle testInteg命令生成的单元测试也在这里,我这里就不赘述了。
  
  这一部分是jooq自动生成的对应的数据库的表的java文件:
  ![6666](https://yqfile.alicdn.com/c209be982f43530097f82b35871a919929a8ea30.jpeg)
  
  项目的src/main/resources下的application.properties文件中的配置内容:
  server.port=8006
  spring.datasource.url = jdbc:postgresql://127.0.0.1:5432/invest111
  spring.datasource.driver-class-nam = org.postgresql.Driver
  spring.datasource.username = invest111
  spring.datasource.password = invest111
  spring.datasource.minIdle = 5
  spring.datasource.maxActive = 50
  spring.datasource.maxWait = 60000
  spring.datasource.timeBetweenEvictionRunsMillis = 60000
  spring.datasource.minEvictableIdleTimeMillis = 300000
  spring.datasource.validationQuery = SELECT 1 FROM DUAL
  spring.datasource.testWhileIdle = true
  spring.datasource.testOnBorrow = false
  spring.datasource.testOnReturn = false
  spring.datasource.poolPreparedStatements = true
  spring.datasource.maxPoolPreparedStatementPerConnectionSize = 20
  spring.datasource.connectionProperties = druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
  spring.jooq.sql-dialect = postgres
  bi.http.port =  8006
  bi.client.host = clientbi.2222.com
  #日志相关配置
  logging.file= ./logs/jingdata-bi-pg
  logging.level.root= ERROR
  logging.level.com.jingdata= DEBUG
  logging.level.org.springframework.web= DEBUG
  logging.level.com.netflix.discovery.DiscoveryClien= OFF
  logging.level.com.netflix.discovery.InstanceInfoReplicator= OFF
  
  基本是一看就行,也就不啰嗦了。
  
  下面再给出,一些使用jooq在postgresql 数据中的表中做CURD操作的代码,不啰嗦,直接上,几乎是一看就懂:
  
  package com.jingdata.asset.manage.bi.assetmanagesystem.system.impl;

  import com.jingdata.asset.manage.bi.assetmanagesystem.system.function.IAnnouncementReferencesService;
  import com.jingdata.asset.manage.bi.assetmanagesystem.system.impl.base.BaseImpl;
  import com.jingdata.asset.manage.bi.assetmanagesystem.transform.ReferenceInfoVo;
  import com.jingdata.asset.manage.bi.assetmanagesystem.transform.ReferenceTransform;
  import org.jooq.Record;
  import org.jooq.Result;
  import org.jooq.impl.DSL;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  import org.springframework.stereotype.Service;
  import java.sql.Timestamp;
  import java.util.List;
  import static com.jingdata.asset.manage.bi.assetmanagesystem.bidb.Tables.PAAS_BI_ANNOUNCEMENT_REFERENCES;

  /**
   * @date   2019-02-28
   *
   */
  @Service
  public class AnnouncementReferencesImpl extends BaseImpl implements IAnnouncementReferencesService {

      private final Logger logger = LoggerFactory.getLogger(this.getClass());
      private ReferenceTransform referenceTransform = new ReferenceTransform();

      @Override
      public List<ReferenceInfoVo> getOneAnnouncementReferences(Integer announcementId) {
            Result<Record> records = getDSLContext().select().from(PAAS_BI_ANNOUNCEMENT_REFERENCES)
            .where(DSL.field(PAAS_BI_ANNOUNCEMENT_REFERENCES.USER_ID).eq("5bcfd9f06faa7b79fd28c304"))
            .and(DSL.field(PAAS_BI_ANNOUNCEMENT_REFERENCES.IS_DELETED).eq(0))
            .and(DSL.field(PAAS_BI_ANNOUNCEMENT_REFERENCES.REFERENCE_ID).eq(announcementId))
            .orderBy(DSL.field(PAAS_BI_ANNOUNCEMENT_REFERENCES.ID).desc())
            .fetch();

            return  referenceTransform.transformReferenceRecord(records);
      }

      @Override
      public Integer addOneAnnouncementReferences(Integer announcementId, String reportList, String chartList) {
            return getDSLContext().insertInto(PAAS_BI_ANNOUNCEMENT_REFERENCES)
                .set(DSL.field(PAAS_BI_ANNOUNCEMENT_REFERENCES.APP_ID), "1111122222")
                .set(DSL.field(PAAS_BI_ANNOUNCEMENT_REFERENCES.USER_ID), "1111122222")
                .set(DSL.field(PAAS_BI_ANNOUNCEMENT_REFERENCES.TENANT_ID), "1111122222")
                .set(DSL.field(PAAS_BI_ANNOUNCEMENT_REFERENCES.CREATED_BY), "1111122222")
                .set(DSL.field(PAAS_BI_ANNOUNCEMENT_REFERENCES.UPDATED_BY), "1111122222")
                .set(DSL.field(PAAS_BI_ANNOUNCEMENT_REFERENCES.IS_DELETED), 0)
                .set(DSL.field(PAAS_BI_ANNOUNCEMENT_REFERENCES.UPDATED_AT), new Timestamp(System.currentTimeMillis()))
                .set(DSL.field(PAAS_BI_ANNOUNCEMENT_REFERENCES.CREATED_AT), new Timestamp(System.currentTimeMillis()))
                //1表示报表,2表示图表
                .set(DSL.field(PAAS_BI_ANNOUNCEMENT_REFERENCES.REFERENCE_TYPE), 1)
                //1表示报表,2表示图表
                .set(DSL.field(PAAS_BI_ANNOUNCEMENT_REFERENCES.REFERENCE_ID), Integer.parseInt("111"))
                //1表示报表,2表示图表
                .set(DSL.field(PAAS_BI_ANNOUNCEMENT_REFERENCES.SOURCE_ID), announcementId)
                .execute();
          }

          @Override
          public Integer deleteOneAnnouncementReferences(String referenceIds) {
                return getDSLContext().delete(PAAS_BI_ANNOUNCEMENT_REFERENCES)
          .where(DSL.field(PAAS_BI_ANNOUNCEMENT_REFERENCES.ID).eq(Integer.parseInt(referenceIds))).execute();
          }
          
          @Override
          public void deleteByMasterChartId(Long masterId, Context context) {
                dslContext.update(PAAS_BI_DASHBOARD_LINKAGE)
                  .set(PAAS_BI_DASHBOARD_LINKAGE.IS_DELETED, 1)
                  .set(PAAS_BI_DASHBOARD_LINKAGE.UPDATE_BY, context.getUserId())
                  .set(PAAS_BI_DASHBOARD_LINKAGE.UPDATE_TIME, System.currentTimeMillis())
                  .where(PAAS_BI_DASHBOARD_LINKAGE.MASTER_CHART_ID.eq(masterId))
                  .and(PAAS_BI_DASHBOARD_LINKAGE.TENANT_ID.eq(context.getTenantId()))
                  .and(PAAS_BI_DASHBOARD_LINKAGE.APP_ID.eq(context.getAppId()))
                  .and(PAAS_BI_DASHBOARD_LINKAGE.IS_DELETED.eq(0))
                  .execute();
            }
  }
  
  基本上增、删、改、查都有了。
  
  更高级的用法,jion 、union等相关写法,请参考jooq的官方文档。

  本周会给出在码云上的git 源码的链接地址,如果有疑问的,请参考源码,代码胜千言!!!!!
  
相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
相关文章
|
7天前
|
关系型数据库 数据库 PostgreSQL
【赵渝强老师】PostgreSQL的模板数据库
在PostgreSQL中,创建新数据库时,默认通过拷贝`template1`实现。`template1`包含标准系统对象,可自定义以影响新数据库内容;而`template0`是纯净模板,仅含预定义对象且不应修改。视频讲解和代码示例展示了如何查看现有数据库信息及标识字段的作用。 ![图示](https://ucc.alicdn.com/pic/developer-ecology/yub6x2mlkqwck_398ed06397a44c2d9bfbb5ae5c90bbc0.png) [视频链接](https://www.bilibili.com/video/BV1szyfY4EQn)
【赵渝强老师】PostgreSQL的模板数据库
|
21天前
|
Cloud Native Java Nacos
springcloud/springboot集成NACOS 做注册和配置中心以及nacos源码分析
通过本文,我们详细介绍了如何在 Spring Cloud 和 Spring Boot 中集成 Nacos 进行服务注册和配置管理,并对 Nacos 的源码进行了初步分析。Nacos 作为一个强大的服务注册和配置管理平台,为微服务架构提供
262 14
|
22天前
|
前端开发 Java Nacos
🛡️Spring Boot 3 整合 Spring Cloud Gateway 工程实践
本文介绍了如何使用Spring Cloud Alibaba 2023.0.0.0技术栈构建微服务网关,以应对微服务架构中流量治理与安全管控的复杂性。通过一个包含鉴权服务、文件服务和主服务的项目,详细讲解了网关的整合与功能开发。首先,通过统一路由配置,将所有请求集中到网关进行管理;其次,实现了限流防刷功能,防止恶意刷接口;最后,添加了登录鉴权机制,确保用户身份验证。整个过程结合Nacos注册中心,确保服务注册与配置管理的高效性。通过这些实践,帮助开发者更好地理解和应用微服务网关。
75 0
🛡️Spring Boot 3 整合 Spring Cloud Gateway 工程实践
|
1月前
|
存储 关系型数据库 数据库
华为数据库openGauss与PostgreSQL使用对比
华为openGauss数据库基于PostgreSQL内核演进,进行了多项增强。密码认证从MD5升级为SHA256;字符串存储中,char(n)、varchar(n)的n由字符改为字节,新增nvarchar2(n)表示字符,最大存储100MB;且将空字符&#39;&#39;统一转换为null,提升了数据处理的一致性和安全性。
136 12
|
2月前
|
JavaScript NoSQL Java
基于SpringBoot+Vue实现的冬奥会科普平台设计与实现(系统源码+文档+数据库+部署)
面向大学生毕业选题、开题、任务书、程序设计开发、论文辅导提供一站式服务。主要服务:程序设计开发、代码修改、成品部署、支持定制、论文辅导,助力毕设!
|
2月前
|
JavaScript NoSQL Java
基于SpringBoot+Vue实现的大学生体质测试管理系统设计与实现(系统源码+文档+数据库+部署)
面向大学生毕业选题、开题、任务书、程序设计开发、论文辅导提供一站式服务。主要服务:程序设计开发、代码修改、成品部署、支持定制、论文辅导,助力毕设!
|
2月前
|
JavaScript NoSQL Java
基于SpringBoot+Vue实现的大学生就业服务平台设计与实现(系统源码+文档+数据库+部署等)
面向大学生毕业选题、开题、任务书、程序设计开发、论文辅导提供一站式服务。主要服务:程序设计开发、代码修改、成品部署、支持定制、论文辅导,助力毕设!
|
2月前
|
JavaScript NoSQL Java
基于SpringBoot+Vue的班级综合测评管理系统设计与实现(系统源码+文档+数据库+部署等)
✌免费选题、功能需求设计、任务书、开题报告、中期检查、程序功能实现、论文辅导、论文降重、答辩PPT辅导、会议视频一对一讲解代码等✌
|
2月前
|
前端开发 Java 数据库连接
Java后端开发-使用springboot进行Mybatis连接数据库步骤
本文介绍了使用Java和IDEA进行数据库操作的详细步骤,涵盖从数据库准备到测试类编写及运行的全过程。主要内容包括: 1. **数据库准备**:创建数据库和表。 2. **查询数据库**:验证数据库是否可用。 3. **IDEA代码配置**:构建实体类并配置数据库连接。 4. **测试类编写**:编写并运行测试类以确保一切正常。
93 2
|
2月前
|
存储 关系型数据库 分布式数据库
PolarDB PostgreSQL版:商业数据库替换与企业上云首选
PolarDB PostgreSQL版是商业数据库替换与企业上云的首选。其技术架构实现存储计算分离,具备极致弹性和扩展性,支持Serverless、HTAP等特性。产品在弹性、性能、成本优化和多模处理方面有显著提升,如冷热数据自动分层、Ganos多模引擎等。已在汽车、交通、零售等行业成功应用,典型案例包括小鹏汽车、中远海科等,帮助企业大幅降低运维成本并提高业务效率。
62 13