• 微服务架构


    在一次学习分布式跟踪系统zipkin中,发现了jooq这个组件,当时不知这个组件是干嘛的,后来抽空学习了一下,感觉这个组件还挺用的。它主要有以下作用:

    • 通过DSL(Domain Specific Language )风格,利用Java代码写sql。
    • 支持主流的RDMS和更多的特性,如self-joins,union,存储过程,复杂的子查询等。
    • 提供GenerationTool,能够通过表结构自动生成代码。

    Flyway是一款开源的数据库版本管理工具,它更倾向于规约优于配置的方式。Flyway可以独立于应用实现管理并跟踪数据库变更,支持数据库版本自动升级。说直白一点,Flyway就是做数据库版本控制的,在数据库版本升级中很有作用。

    本文通过一个整合实例,来简单说明Jooq的用法,该例子我也提交到GitHub上,链接为:https://github.com/lzj09/sw-jooq

    下面开始讲解整合的过程。

    1、pom.xml文件

    其实整合的过程,大部分的工作都是在pom文件里面完成,只要看懂了pom文件,整合过程基本上就明白了。pom文件如下:

    <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/xsd/maven-4.0.0.xsd">
    
    	<parent>
    		<groupId>org.springframework.boot</groupId>
    		<artifactId>spring-boot-starter-parent</artifactId>
    		<version>2.0.2.RELEASE</version>
    	</parent>
    
    	<modelVersion>4.0.0</modelVersion>
    	<groupId>com.swnote.jooq</groupId>
    	<artifactId>sw-jooq</artifactId>
    	<version>0.0.1-SNAPSHOT</version>
    	<packaging>jar</packaging>
    	<name>sw-jooq</name>
    	<url>http://maven.apache.org</url>
    
    	<properties>
    		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    	</properties>
    
    	<dependencies>
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-web</artifactId>
    		</dependency>
    
            <!-- jooq相关包 -->
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-jooq</artifactId>
    		</dependency>
    		<dependency>
    			<groupId>org.jooq</groupId>
    			<artifactId>jooq-meta</artifactId>
    		</dependency>
    		<dependency>
    			<groupId>org.jooq</groupId>
    			<artifactId>jooq-codegen</artifactId>
    		</dependency>
    
            <!-- flyway相关包 -->
            <dependency>
                <groupId>org.flywaydb</groupId>
                <artifactId>flyway-core</artifactId>
            </dependency>
            
            <!-- mysql驱动 -->
    		<dependency>
    			<groupId>mysql</groupId>
    			<artifactId>mysql-connector-java</artifactId>
    		</dependency>
    	</dependencies>
    
    	<build>
    		<plugins>
    			<plugin>
    				<groupId>org.apache.maven.plugins</groupId>
    				<artifactId>maven-compiler-plugin</artifactId>
    				<configuration>
    					<source>1.8</source>
    					<target>1.8</target>
    				</configuration>
    			</plugin>
    
    			<plugin>
    				<groupId>org.springframework.boot</groupId>
    				<artifactId>spring-boot-maven-plugin</artifactId>
    				<executions>
    					<execution>
    						<goals>
    							<goal>repackage</goal>
    						</goals>
    					</execution>
    				</executions>
    			</plugin>
    
                <!-- 用于加载application.yml信息,在pom文件可读取到application.yml中信息 -->
    			<plugin>
    				<groupId>it.ozimov</groupId>
    				<artifactId>yaml-properties-maven-plugin</artifactId>
    				<version>1.1.3</version>
    				<executions>
    					<execution>
    						<phase>initialize</phase>
    						<goals>
    							<goal>read-project-properties</goal>
    						</goals>
    						<configuration>
    							<files>
    								<file>src/main/resources/application.yml</file>
    							</files>
    						</configuration>
    					</execution>
    				</executions>
    			</plugin>
    
                <!-- flyway的插件配置 -->
    			<plugin>
    				<groupId>org.flywaydb</groupId>
    				<artifactId>flyway-maven-plugin</artifactId>
    				<executions>
    					<execution>
    						<phase>generate-sources</phase>
    						<goals>
    							<goal>migrate</goal>
    						</goals>
    					</execution>
    				</executions>
    				<configuration>
    				    <!-- 此处的信息是读取的application.yml中的信息 -->
    					<url>${spring.datasource.url}</url>
    					<user>${spring.datasource.username}</user>
    					<password>${spring.datasource.password}</password>
    					<locations>
    						<location>filesystem:src/main/resources/db/migration</location>
    					</locations>
    				</configuration>
    			</plugin>
    
                <!-- jooq插件配置 -->
    			<plugin>
    				<groupId>org.jooq</groupId>
    				<artifactId>jooq-codegen-maven</artifactId>
    				<executions>
    					<execution>
    						<id>jooq</id>
    						<phase>generate-sources</phase>
    						<goals>
    							<goal>generate</goal>
    						</goals>
    						<configuration>
    							<jdbc>
    								<driver>${spring.datasource.driverClassName}</driver>
    								<url>${spring.datasource.url}</url>
    								<user>${spring.datasource.username}</user>
    								<password>${spring.datasource.password}</password>
    							</jdbc>
    							<!-- 自动生成代码的配置 -->
    							<generator>
    								<database>
    									<name>org.jooq.util.mysql.MySQLDatabase</name>
    									<includes>.*</includes>
    									<excludes></excludes>
    									<dateAsTimestamp>true</dateAsTimestamp>
    									<!-- 连接的是数据库中jooq模式 -->
    									<inputSchema>jooq</inputSchema>
    								</database>
    								<generate>
    									<deprecated>false</deprecated>
    									<instanceFields>true</instanceFields>
    									<pojos>true</pojos>
    								</generate>
    								<target>
    								    <!-- 指定自动生成代码的位置 -->
    									<packageName>com.swnote.jooq.generator</packageName>
    									<directory>src/main/java</directory>
    								</target>
    							</generator>
    						</configuration>
    					</execution>
    				</executions>
    				<dependencies>
    					<dependency>
    						<groupId>mysql</groupId>
    						<artifactId>mysql-connector-java</artifactId>
    						<version>5.1.46</version>
    					</dependency>
    				</dependencies>
    			</plugin>
    		</plugins>
    
    		<resources>
    			<resource>
    				<directory>src/main/java</directory>
    				<excludes>
    					<exclude>**/*.java</exclude>
    				</excludes>
    			</resource>
    			<resource>
    				<directory>src/main/resources</directory>
    			</resource>
    		</resources>
    	</build>
    </project>
    

    其中需要说明的几个关键点:

    • yaml-properties-maven-plugin,该插件可以使在pom文件中读取到application.yml文件中的配置,这样可以避免同样的配置有多次配置的问题。
    • flyway-maven-plugin,该插件用于配置flyway,指定了创表的sql的位置为src/main/resources/db/migration
    • jooq-codegen-maven,配置了所连接的数据库信息,模式名,以及自动生成的代码的配置,比如要生成哪些代码、将生成的代码放在哪个目录中等。

    2、基于Jooq的CURD

    由于Jooq支持通过Java代码来写sql的逻辑,为此例子工程中没有Dao层,sql的逻辑全部在Service层,Service层的代码如下:

    用户信息服务接口:IUserService

    package com.swnote.jooq.service;
    
    import java.util.List;
    import java.util.Map;
    
    import com.swnote.jooq.generator.tables.pojos.User;
    
    /**
     * 用户信息服务接口
     * 
     * @author lzj
     * @date [2019-03-10]
     */
    public interface IUserService {
    
        /**
         * 创建用户
         * 
         * @param user
         */
        void create(User user);
    
        /**
         * 根据id删除用户
         * 
         * @param user_id
         */
        void delete(String user_id);
    
        /**
         * 更新用户
         * 
         * @param user
         */
        void update(User user);
        
        /**
         * 根据id获取用户
         * 
         * @param user_id
         * @return
         */
        User retrieve(String user_id);
    
        /**
         * 根据条件获取用户列表
         * 
         * @param params
         * @return
         */
        List<User> queryForList(Map<String, Object> params);
    }
    

    用户信息服务类:UserService

    package com.swnote.jooq.service.impl;
    
    import static com.swnote.jooq.generator.tables.User.USER;
    
    import java.util.List;
    import java.util.Map;
    import java.util.Map.Entry;
    
    import org.jooq.DSLContext;
    import org.jooq.UpdateQuery;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Propagation;
    import org.springframework.transaction.annotation.Transactional;
    
    import com.swnote.jooq.generator.tables.pojos.User;
    import com.swnote.jooq.generator.tables.records.UserRecord;
    import com.swnote.jooq.service.IUserService;
    
    /**
     * 用户信息服务类
     * 
     * @author lzj
     * @date [2019-03-10]
     */
    @Transactional
    @Service
    public class UserService implements IUserService {
    
        @Autowired
        private DSLContext dsl;
    
        @Override
        public void create(User user) {
        	// 构建insert语句
            dsl.insertInto(USER, USER.USER_ID, USER.NAME, USER.INTRO)
                .values(user.getUserId(), user.getName(), user.getIntro()).execute();
        }
    
        @Override
        public void delete(String user_id) {
        	// 构建delete语句
            dsl.delete(USER).where(USER.USER_ID.eq(user_id)).execute();
        }
    
        @Override
        public void update(User user) {
        	// 构建update语句
            UpdateQuery<UserRecord> update = dsl.updateQuery(USER);
            update.addValue(USER.NAME, user.getName());
            update.addValue(USER.INTRO, user.getIntro());
            update.addConditions(USER.USER_ID.eq(user.getUserId()));
            update.execute();
        }
    
        @Transactional(propagation = Propagation.NOT_SUPPORTED)
        @Override
        public User retrieve(String user_id) {
        	// 构建select语句
            List<User> users = dsl.select(USER.USER_ID, USER.NAME, USER.INTRO).from(USER).where(USER.USER_ID.eq(user_id))
                .fetch().into(User.class);
            
            if (users != null && !users.isEmpty()) {
                return users.get(0);
            }
            return null;
        }
    
        @Transactional(propagation = Propagation.NOT_SUPPORTED)
        @Override
        public List<User> queryForList(Map<String, Object> params) {
        	// 构建select语句
            StringBuilder builder = new StringBuilder();
            if (params != null) {
                for (Entry<String, Object> entry : params.entrySet()) {
                    if (builder.length() == 0) {
                        builder.append(entry.getKey()).append(" = ").append(entry.getValue());
                    } else {
                        builder.append(" and ").append(entry.getKey()).append(" = ").append(entry.getValue());
                    }
                }
            }
            
            List<User> users = dsl.select(USER.USER_ID, USER.NAME, USER.INTRO).from(USER).where(builder.toString()).fetch().into(User.class);
            return users;
        }
    }
    

    从上面的代码可以看到利用Jooq来写sql的逻辑,也很简单。

    3、测试

    Controller层代码在此就不写,感兴趣的可以我的GitHub中去看。在此通过PostMan测试Controller中暴露的REST接口。例如新增接口:

    执行后,数据库也就有了记录,即:

    关注我

    以你最方便的方式关注我:
    微信公众号:

  • 相关阅读:
    转几篇关于反射的文章
    几篇并发的文章
    线程池的使用(转)
    深入理解java不可变对象(转)
    收集的书
    BeanPostProcessor(转)
    JDK的动态代理深入解析(Proxy,InvocationHandler)(转)
    Java中InputStream和String之间的转换方法
    linux的一些常用命令
    Linux下查看文件内容的命令
  • 原文地址:https://www.cnblogs.com/atcloud/p/10571049.html
Copyright © 2020-2023  润新知