zoukankan      html  css  js  c++  java
  • Jooq配置与使用

    1.jooq是一个对象关系映射的轻量级框架,在sql执行方面的灵活性和对数据包装的严谨性方面都很优秀

    2.jooq的配置

    import com.alibaba.druid.pool.DruidDataSource;
    import com.alibaba.druid.pool.DruidDataSourceFactory;
    import com.alibaba.druid.pool.vendor.MySqlValidConnectionChecker;
    import java.util.Properties;
    import javax.sql.DataSource;
    import org.jooq.SQLDialect;
    import org.jooq.conf.RenderNameStyle;
    import org.jooq.conf.Settings;
    import org.jooq.impl.DataSourceConnectionProvider;
    import org.jooq.impl.DefaultConfiguration;
    import org.slf4j.Logger;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.core.env.Environment;
    import org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy;
    
    @Configuration
    @ConditionalOnProperty(
        value = {"jooq.enabled"},
        matchIfMissing = true
    )
    public class JooqConfiguration {
        private static final Logger logger = LogUtil.logger(JooqConfiguration.class);
        @Value("${jdbc.url}")
        private String url;
        @Value("${jdbc.driver}")
        private String driver;
        @Value("${jdbc.user}")
        private String user;
        @Value("${jdbc.password}")
        private String password;
        @Value("${jdbc.dialect:MYSQL}")
        private String dialect;
        @Autowired
        private Environment env;
    
        public JooqConfiguration() {
        }
    
        private String getMaxActive() {
            if (Tool.isNullOrEmpty(K8s.nameSpace())) {
                return this.env.getProperty("jdbc.dev.maxActive", "1");
            } else {
                String str = Env.get("jdbc.maxActive");
                if (Tool.isNullOrEmpty(str)) {
                    str = this.env.getProperty("jdbc.maxActive");
                }
    
                return Tool.isNullOrEmpty(str) ? "40" : str;
            }
        }
    
        @Bean(
            destroyMethod = "close"
        )
        public DataSource dataSource() throws Exception {
            Properties properties = new Properties();
            properties.put("url", Env.get("jdbc.url", this.url));
            properties.put("driverClassName", Env.get("jdbc.driver", this.driver));
            properties.put("username", Env.get("jdbc.user", this.user));
            properties.put("password", Env.get("jdbc.password", this.password));
            properties.put("initialSize", "1");
            properties.put("maxActive", this.getMaxActive());
            properties.put("maxWait", "10000");
            properties.put("minIdle", "1");
            properties.put("timeBetweenEvictionRunsMillis", "60000");
            properties.put("minEvictableIdleTimeMillis", "300000");
            properties.put("validationQuery", "SELECT 1");
            properties.put("testWhileIdle", "true");
            properties.put("testOnBorrow", "false");
            properties.put("testOnReturn", "false");
            properties.put("maxOpenPreparedStatements", "10");
            properties.put("removeAbandoned", "true");
            properties.put("removeAbandonedTimeout", "1800");
            properties.put("logAbandoned", "true");
            logger.info("data base connection info: " + properties);
            DruidDataSource dds = (DruidDataSource)DruidDataSourceFactory.createDataSource(properties);
            dds.setFilters("log4j");
            properties = new Properties();
            properties.put("druid.stat.slowSqlMillis", "3000");
            properties.put("druid.stat.logSlowSql", "true");
            properties.put("druid.stat.mergeSql", "true");
            dds.setConnectProperties(properties);
            dds.setValidConnectionChecker(new MySqlValidConnectionChecker());
            return dds;
        }
    
        @Bean
        public DataSourceConnectionProvider connectionProvider(DataSource dataSource) throws Exception {
            return new DataSourceConnectionProvider(new TransactionAwareDataSourceProxy(dataSource));
        }
    
        @Bean
        public DefaultConfiguration configuration(DataSourceConnectionProvider connectionProvider) throws Exception {
            DefaultConfiguration jooqConfiguration = new DefaultConfiguration();
            jooqConfiguration.set(connectionProvider);
            SQLDialect dia = SQLDialect.valueOf(this.dialect);
            jooqConfiguration.setSQLDialect(dia);
            Settings settings = (new Settings()).withExecuteLogging(true).withRenderFormatted(true);
            if (dia == SQLDialect.H2) {
                settings.withRenderSchema(false).withRenderNameStyle(RenderNameStyle.AS_IS);
            }
    
            jooqConfiguration.set(settings);
            return jooqConfiguration;
        }
    }

    3.配置yml

    server:
      port: 8085
      servlet:
        context-path: /customer
    
    jdbc:
      url: jdbc:mysql://113.140.12.194:13306/customer_tuiguang?useSSL=false
      datasource: customer_tuiguang
      driver: com.mysql.cj.jdbc.Driver
      user: chdsd
      password: Chdsd20#
      dialect: MYSQL
    dev:
      token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJ0b2dlZWsiLCJuYW1lIjoi5bGx5Lic566h55CG5ZGYIiwiaWQiOiJjaGRzZGFkbWluIn0.FmzO8352eVHKLkNnXx_eT6IgFeZmA2mZ6wxuZaWRxKR3jTT8WUgagjbvVbCcS6O5uAaBFrocXezudr00L6bQmi0KLm3dG7yOrj7RoWpn-dS1o8KaDn-z7MppTBaRBflROD42Mz9XjJNQGWcajrheJsCuAGW8EAgsR3KSrLvqqHDYooLXO8xL7imETx6OcMtv_wHJjauIkWKNyfVsgVzXBuUpZN7ORMZKYEp7DXjGHBPxPCPoDpZaVqYYUjWb98sNmSW2SpgfF3SQMC43W8yVbK8BcFQ9iwHzXiec1Wb0li_U-kJ5wXecDDnARvovVV3nx6Vr5ydtagsq0be-snlcFQ
    
    #service:
    #  host: http://113.140.12.194:18083/chd-dev/api
    #  url-contract: https://www.chdes.com.cn/chd-dev/api
    #  baidu-ak: Y9CacQfm6ZRFfKW7FOjia5lZdyjNvtBa
    #dev:
    #  token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJ0b2dlZWsiLCJuYW1lIjoi5bGx5Lic566h55CG5ZGYIiwiaWQiOiJjaGRzZGFkbWluIn0.FmzO8352eVHKLkNnXx_eT6IgFeZmA2mZ6wxuZaWRxKR3jTT8WUgagjbvVbCcS6O5uAaBFrocXezudr00L6bQmi0KLm3dG7yOrj7RoWpn-dS1o8KaDn-z7MppTBaRBflROD42Mz9XjJNQGWcajrheJsCuAGW8EAgsR3KSrLvqqHDYooLXO8xL7imETx6OcMtv_wHJjauIkWKNyfVsgVzXBuUpZN7ORMZKYEp7DXjGHBPxPCPoDpZaVqYYUjWb98sNmSW2SpgfF3SQMC43W8yVbK8BcFQ9iwHzXiec1Wb0li_U-kJ5wXecDDnARvovVV3nx6Vr5ydtagsq0be-snlcFQ
    
    service:
    #  host: http://113.140.12.194:18083/chd/api
      activiti:
        host: http://localhost:8080/activiti
      authentication:
        host: http://localhost:8082/authentication
    #  host: http://localhost:8080
      baidu-ak: Y9CacQfm6ZRFfKW7FOjia5lZdyjNvtBa
    
    spring:
      servlet:
        multipart:
          max-file-size: 30MB
          max-request-size: 30MB
      liquibase:
        changelog: classpath:/db/changelog/db.changelog-master.xml
      data:
        mongodb:
          host: 39.96.6.37
          port: 27027
          database: dev-attachment
          username: tuji
          password: tuji2018

    4.自己封装的Dbvisitor

    import lombok.AllArgsConstructor;
    import lombok.Data;
    import org.jooq.DSLContext;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.jdbc.core.JdbcTemplate;
    import org.springframework.stereotype.Component;
    
    import javax.sql.DataSource;
    
    @Configuration
    @Component
    public class DBvisitor {
    
        public static DSLContext dsl;
    
        public static JdbcTemplate jdbcTemplate;
    
        @Autowired
        private DSLContext dslContext;
    
        @Bean
        public JdbcTemplate jdbcTemplate(DataSource dataSource){
            return new JdbcTemplate(dataSource);
        }
    
        @Autowired
        public void setTemplate(JdbcTemplate template){
            DBvisitor.jdbcTemplate = template;
        }
    
        @Autowired
        public void setDsl() {
            DBvisitor.dsl = dslContext;
        }
    
    }

    5.gradle配置

    buildscript {
        repositories {
            mavenCentral()
            maven {
                url "${nexusUrl}/content/groups/public/"
            }
        }
        dependencies {
            classpath group: 'mysql', name: 'mysql-connector-java', version: '6.0.6'
            classpath("org.springframework.boot:spring-boot-gradle-plugin:2.0.0.RELEASE")
            classpath("cn.togeek.plugin:jooq:1.0.0-SNAPSHOT")
            classpath("cn.togeek.plugin:liquibase:1.0.0-SNAPSHOT")
        }
    }
    
    apply plugin: 'java'
    apply plugin: 'maven'
    apply plugin: 'idea'
    apply plugin: 'org.springframework.boot'
    apply plugin: 'io.spring.dependency-management'
    apply plugin: 'cn.togeek.plugin.jooq'
    apply plugin: 'cn.togeek.plugin.liquibase'
    bootJar {
        baseName = 'customer'
        version =  '2.0.0-SNAPSHOT'
    }
    
    repositories {
        mavenCentral()
    
        maven {
            url "${nexusUrl}/content/groups/public/"
        }
    }
    
    sourceCompatibility = 1.8
    targetCompatibility = 1.8
    
    dependencies {
    //    compile("cn.togeek.power-base:customer-base:chd-tuiguang-SNAPSHOT")
        compile group: 'org.liquibase', name: 'liquibase-core', version: '3.6.1'
        compile project(':customer-base')
        compile "axis:axis:1.4"
        compile "javax.ejb:ejb-api:3.0"
        compile "org.jxls:jxls:2.4.3"
        compile "org.jxls:jxls-jexcel:1.0.6"
        compile "org.jxls:jxls-poi:1.0.14"
        compile group: 'javax.xml.bind', name: 'jaxb-api', version: '2.3.0'
        compile group: 'org.freemarker', name: 'freemarker', version: '2.3.23'
        compile group: 'commons-httpclient', name: 'commons-httpclient', version: '3.1'
        compile group: 'org.springframework', name: 'spring-core', version: '5.0.20.RELEASE'
        compile 'cn.hutool:hutool-all:4.0.8'
        compile group: 'org.liquibase', name: 'liquibase-core', version: '3.6.1'
        runtime group: 'mysql', name: 'mysql-connector-java', version: '6.0.6'
        compile 'cn.afterturn:easypoi-base:3.0.3'
        compile 'cn.afterturn:easypoi-web:3.0.3'
        compile 'cn.afterturn:easypoi-annotation:3.0.3'
        compile 'org.apache.pdfbox:pdfbox:2.0.4'
        //compile 'org.apache.poi:ooxml-schemas:1.1'
        compile group: 'com.gexin.platform', name: 'gexin-rp-sdk-http', version: '4.1.0.5'
        compile fileTree(dir: 'libs', include: '*.jar')
    
        testCompile group: 'com.h2database', name: 'h2', version: '1.4.197'
    
        compile ('org.apache.poi:poi-ooxml:4.1.2'){
            exclude module: 'xmlbeans'
        }
        compile 'org.apache.xmlbeans:xmlbeans:3.1.0'
    }
    
    configurations {
        all*.exclude module: 'spring-boot-starter-logging'
        all*.exclude module: 'logback-core'
        all*.exclude module: 'logback-classic'
    }
    
    task buildTask(type: Jar, dependsOn: bootJar) {
        doLast {
            copy {
                from 'k8s'
                into 'build/k8s'
            }
            copy {
                from 'docker'
                into 'build/docker'
            }
            copy {
                from 'build/libs'
                into 'build/docker'
                include '*.jar'
            }
            copy {
                from 'src/main/resources/font'
                into 'build/docker/font'
            }
        }
    }
    
    task run(dependsOn: bootJar) << {
        javaexec { main="-jar"; args bootJar.archivePath }
    }
    
    compileJava {
        options.encoding = "UTF-8"
    }

    7.setting.gradle

    include ':customer-base'
    project(':customer-base').projectDir=file('D:\\ideaWorkspace\\customer-base')

    8.定时任务中使用Dbvisitor

    import lombok.AllArgsConstructor;
    import lombok.Data;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.BeanUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.scheduling.annotation.EnableScheduling;
    import org.springframework.scheduling.annotation.Scheduled;
    
    import java.util.List;
    import java.util.Map;
    import java.util.concurrent.CopyOnWriteArrayList;
    import java.util.concurrent.ExecutionException;
    import java.util.stream.Collectors;
    
    import static cn.togeek.jooq.Tables.*;
    
    @Configuration
    @EnableScheduling
    public class TaskPool {
    
        private final long MILLISECONDS = 1;
        private final long SECONDS = 1000;
        private final long MINUTES = 60 * SECONDS;
        private final long HOURS = 60 * MINUTES;
        private final long DAYS = 24 * HOURS;
        private final Logger logger = LoggerFactory.getLogger(TaskPool.class);
        private String METHOD = "";
        @Autowired
        private DBvisitor DBvisitor;
    
    
        @Scheduled(fixedRate= 1 * HOURS)
        private void configureTasks() throws ExecutionException, InterruptedException {
            syncTsorganizationTrorganizationTorganizationIndb();
        }
    
        /**
         * 客户数据维护
         * 维护auth.torganization,customer.trorganization,customer.tsorganization数据
         * 目标:定期扫描customer.tsorganization数据,维护到auth.torganization和trorganization,customer中
         * 解决:多种客户来源方式,包括但不限于客户导入,客户新增,微信+网厅新增关联企业过程微服务调用链路某个节点异常导致的数据缺失问题
         */
        private void syncTsorganizationTrorganizationTorganizationIndb() throws ExecutionException, InterruptedException {
            List<TSOrganizationRecord> records = DBvisitor.dsl.selectFrom(T_S_ORGANIZATION).where(T_S_ORGANIZATION.TYPE.eq(OrgType.DLYH.getValue())).fetchInto(TSOrganizationRecord.class);
            List<TROrganizationRecord> mappings = DBvisitor.dsl.selectFrom(T_R_ORGANIZATION).fetchInto(TROrganizationRecord.class);
            List<record> customersInAuth = (List<record>) Rest.get(ServiceUrl.AUTH.concat("/organizations/").concat(OrgType.DLYH.getValue()+"/").concat("all"), List.class).get().stream().map(x -> {
                return new record((String)(((Map) x).get("id")),(String)(((Map) x).get("name")));
            }).collect(Collectors.toList());
            List<String> tsIdMappings = mappings.stream().map(TROrganizationRecord::getOrganizationId).distinct().collect(Collectors.toList());
            List<TROrganizationRecord> missingMappings = new CopyOnWriteArrayList<>(); //映射缺省的数据
            List<record> missingTorgnizations = new CopyOnWriteArrayList<>(); //auth库缺省的数据
            List<String> customersName = customersInAuth.stream().map(record::getValue).distinct().collect(Collectors.toList());
            records.stream().forEach(record -> {
                String sId = record.getId();
                String name = record.getName();
                if (!customersName.contains(name)) { //auth 的客户库里没数据
                    String uuid = UUIDUtil.getUUID();
                    missingTorgnizations.add(new record(sId, uuid));
                    if (!tsIdMappings.contains(sId)) { //且customer无映射关系
                        missingMappings.add(buildTrorganization(record, uuid));
                    }
                } else { // auth 的客户库里有数据
                    if (!tsIdMappings.contains(sId)) { //但customer无映射关系
                        TaskPool.record data = customersInAuth.get(customersName.indexOf(name));
                        missingMappings.add(buildTrorganization(record, data.getKey()));
                    }
                }
            });
            String authSql = getSql(records,missingTorgnizations);
            if (!authSql.endsWith("VALUES;")) {
                logger.info("要操作的auth库sql:"+authSql);
                int row = DBvisitor.jdbcTemplate.update(authSql);
                logger.info("auth库插入了{}条数据",row);
            }
            if (!missingMappings.isEmpty()) {
                logger.info("要维护的customer.trorganiztion库的数据个数:"+missingMappings.size());
                StringBuilder stringBuilder = new StringBuilder();
                stringBuilder.append("INSERT INTO `customer_tuiguang`.`t_r_organization`(`id`,  `organization_id`) VALUES (");
                missingMappings.stream().forEach(x-> {
                    stringBuilder.append("'"+x.getId()+"',").append(""+x.getOrganizationId()+"'),(");
                });
                String mappingSql = stringBuilder.toString();
                mappingSql = mappingSql.substring(0,mappingSql.length()-2);
                int mappingInsert = DBvisitor.jdbcTemplate.update(mappingSql);
    //            int length = dsl.batchInsert(missingMappings).execute().length; 插入太耗时
    //            logger.info("customer.trorganiztion插入{}条数据",length);
                logger.info("customer.trorganiztion插入{}条数据",mappingInsert);
            }
        }
    
        private TROrganizationRecord buildTrorganization(TSOrganizationRecord record,String tId) {
            TROrganizationRecord organizationRecord = new TROrganizationRecord();
            BeanUtils.copyProperties(record,organizationRecord);
            organizationRecord.setId(tId);
            organizationRecord.setOrganizationId(record.getId());
            organizationRecord.setPkId(null);
            return organizationRecord;
        }
    
        private String getSql(List<TSOrganizationRecord> records,List<record> missingTorgnizations){
            StringBuilder sqlbuilder = new StringBuilder();
            /**
             * INSERT INTO `authentication_tuiguang`.`t_organization`(`pk`, `id`, `name`, `alias`, `status`, `type`, `parent_id`, `create_time`, `last_modified_time`, `province_code`, `city_code`, `county_code`, `audit_status`, `applicant`, `audit_reason`, `order`, `power_source`) VALUES (490, '7830A3EC-9610-4260-B29D-35935FA23613-00820', '山东新和成维生素有限公司', NULL, 1, 256, NULL, '2019-01-11 20:16:34', '2019-01-11 20:16:34', NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL);
             */
            List<String> keys = missingTorgnizations.stream().map(record::getKey).collect(Collectors.toList());
            List<String> values = missingTorgnizations.stream().map(record::getValue).collect(Collectors.toList());
            sqlbuilder.append("INSERT INTO `authentication_tuiguang`.`t_organization`(`id`, `name`, `status`, `type`, `create_time`, `last_modified_time`, `order`) VALUES (");
            records.stream().filter(x -> keys.contains(x.getId())).forEach(s -> {
                try {
                    sqlbuilder.append(Deal(values.get(keys.indexOf(s.getId())))).append(",")
                            .append(Deal(s.getName())).append(",")
                            .append(1).append(",")
                            .append(OrgType.DLYH.getValue()).append(",")
                            .append(Deal(s.getCreateTime().toString())).append(",")
                            .append(Deal(s.getLastModifiedTime().toString())).append(",")
                            .append(0).append("),(");
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            });
            String sql = sqlbuilder.toString();
            sql = sql.substring(0, sql.length()-2).concat(";");
            return sql;
        }
    
        private Object Deal(Object obj) throws InstantiationException, IllegalAccessException {
            if (obj == null) {
                if ((obj instanceof String)) {
                    return "''";
                } else {
                    return null;
                }
            } else {
                if ((obj instanceof String)) {
                    return "'"+ obj.toString()  +"'";
                } else {
                    return obj.toString();
                }
            }
        }
    
        @Data
        @AllArgsConstructor
        public class record {
            private String key;
            private String value;
        }
    }
  • 相关阅读:
    codeforces 985 F. Isomorphic Strings
    Educational Codeforces Round 44
    codeforces 979D
    ARC060 Digit Sum II
    Iroha and Haiku II
    Unhappy Hacking II
    Just h-index 2018湘潭邀请赛
    [HAOI2007]理想的正方形
    P1231 教辅的组成
    最小割数学形式
  • 原文地址:https://www.cnblogs.com/g177w/p/15588116.html
Copyright © 2011-2022 走看看