🏛🏛🏛 以下内容记录一次 Springboot 项目整和人大金仓数据库的过程 🏛🏛🏛

KingBaseES8

  人大金仓数据库管理系统 KingbaseES(KES) 是面向全行业、全客户关键应用的企业级大型通用数据库管理系统,适用于联机事务处理、查询密集型数据仓库、要求苛刻的互联网应用等场景,提供全部应用开发及系统管理功能,提供性能增强特性,可支持主备集群、读写分离集群、多活共享存储集群等全集群架构,具有高性能、高安全、高可用、易使用、易管理、易维护的特点,支持所有国内外主流CPU、操作系统与云平台部署。
  KES 可以兼容oracle和pgsql,在安装时可以选择兼容模式。
  人大金仓社区地址
  个人感觉目前KES的建设还未有其他国外成熟DB系统完善,因此如果在官网查询不到的问题解决方案的时候,可以尝试向KES兼容的数据库方向上做类似考虑。

SpringBoot整合KES8(pgsql)

以下KingBase兼容pgsql

修改pom文件

添加KES 8、Mybatis、MyBatis plus、Mybatis generator 等依赖

<properties>
    <java.version>11</java.version>
</properties>
<dependencies>
	<!--        其他依赖-->
	...
	<!--        mybatis-->
	<dependency>
	    <groupId>org.mybatis.spring.boot</groupId>
	    <artifactId>mybatis-spring-boot-starter</artifactId>
	    <version>2.1.3</version>
	</dependency>
	<!--        pgsql-->
	<dependency>
	    <groupId>org.postgresql</groupId>
	    <artifactId>postgresql</artifactId>
	    <version>42.5.1</version>
	</dependency>
	<!--        kingbase-->
	<dependency>
	    <groupId>cn.com.kingbase</groupId>
	    <artifactId>kingbase8</artifactId>
	    <version>8.6.0</version>
	</dependency>
</dependencies>
<build>
    <plugins>
        <plugin>
            <groupId>org.mybatis.generator</groupId>
            <configuration>
                <configurationFile>src/main/resources/generatorConfig.xml</configurationFile>
                <verbose>true</verbose>
                <overwrite>true</overwrite>
            </configuration>
            <artifactId>mybatis-generator-maven-plugin</artifactId>
            <version>1.4.0</version>
            <dependencies>
                <dependency>
                    <groupId>org.mybatis.generator</groupId>
                    <artifactId>mybatis-generator-core</artifactId>
                    <version>1.4.0</version>
                </dependency>
				<!--     设置数据源驱动-->
                <dependency>
                    <groupId>cn.com.kingbase</groupId>
                    <artifactId>kingbase8</artifactId>
                    <version>8.6.0</version>
                </dependency>
            </dependencies>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
                <compilerVersion>${java.version}</compilerVersion>
                <source>${java.version}</source>
                <target>${java.version}</target>
            </configuration>
        </plugin>
    </plugins>
</build>

配置多数据源

这里的多数据源配置是静态多数据源

配置文件

application.properties

################# KINGBASE CONFIG #################
spring.datasource.db1.jdbc-url=jdbc:kingbase8://ip:port/test?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&allowMultiQueries=true
spring.datasource.db1.driver-class-name=com.kingbase8.Driver
spring.datasource.db1.username=test
spring.datasource.db1.password=1q2w3e4rmb

spring.datasource.db2.jdbc-url=jdbc:kingbase8://ip2:port2/test?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&allowMultiQueries=true
spring.datasource.db2.driver-class-name=com.kingbase8.Driver
spring.datasource.db2.username=test
spring.datasource.db2.password=1q2w3e4rmb

配置类

db1配置文件,为不同业务的包设置不同的数据源
其中如果在DataSource类型的Bean上设置了@Primary属性,则表示该数据源为默认数据源

@Configuration
@MapperScan(basePackages = "com.xxx.xxx.mapper", sqlSessionFactoryRef = "db1SqlSessionFactory")
public class MybatisDB1Config {
    @Bean(name = "db1DataSource")
    // 表示这个数据源是默认数据源
    @Primary
    @ConfigurationProperties(prefix = "spring.datasource.db1")
    public DataSource getDateSourceDB1() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "db1SqlSessionFactory")
    @Primary
    // @Qualifier表示查找Spring容器中名字为test1DataSource的对象
    public SqlSessionFactory db1SqlSessionFactory(@Qualifier("db1DataSource") DataSource datasource)
            throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(datasource);
        //解决mapper 返回类型为Map 类型时,如果数据数据为空,则不显示列名的问题。
        org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
        configuration.setCallSettersOnNulls(true);
        bean.setConfiguration(configuration);
        return bean.getObject();
    }

    @Bean("db1SqlSessionTemplate")
    @Primary
    public SqlSessionTemplate db1SqlSessionTemplate(
            @Qualifier("db1SqlSessionFactory") SqlSessionFactory sessionFactory) {
        return new SqlSessionTemplate(sessionFactory);
    }
    
	//写事务时使用,使用事务时必须指定数据源
    @Bean(name = "db1TransactionManager")
    public DataSourceTransactionManager db1TransactionManager(@Qualifier("db1DataSource") DataSource datasource) {
        DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
        dataSourceTransactionManager.setDataSource(datasource);
        return dataSourceTransactionManager;
    }
}

@Bean(name = “db1TransactionManager”)用来使用事务时指定数据源,否则编译器会报错
使用时如下@Transactional(“db1TransactionManager”)

代码生成器配置

在POM文件中我们制定了生成器读取配置的文件位置
我们需要将我们生成的表配置一下
Springboot -- Mybatis + Mybatis Generate + KingbaseES8(pgsql) + 静态多数据源-LMLPHP

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
		PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
		"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">

<generatorConfiguration>
	<context id="auth" targetRuntime="MyBatis3">
		<plugin type="org.mybatis.generator.plugins.EqualsHashCodePlugin"></plugin>
		<plugin type="org.mybatis.generator.plugins.SerializablePlugin"></plugin>
		<commentGenerator type="com.qdeicc.base.db.MyCommentGenerator">
			<!--			&lt;!&ndash; 是否去除自动生成的注释 true:是 : false:否 &ndash;&gt;-->
			<!--&lt;!&ndash;			<property name="suppressAllComments" value="true" />&ndash;&gt;-->
			<property name="suppressDate" value="true"/>
		</commentGenerator>
		<!--数据库连接的信息:驱动类、连接地址、用户名、密码 -->
		<jdbcConnection driverClass="com.kingbase8.Driver"
						connectionURL="jdbc:kingbase8://ip:port/test?useUnicode=true&amp;characterEncoding=utf8&amp;serverTimezone=GMT%2B8&amp;allowMultiQueries=true&amp;stringtype=unspecified"
						userId="test"
						password="1q2w3e4rmb">
		</jdbcConnection>
		<!-- 默认false,把JDBC DECIMAL 和 NUMERIC 类型解析为 Integer,为 true时把JDBC DECIMAL 和
            NUMERIC 类型解析为java.math.BigDecimal -->
		<javaTypeResolver>
			<property name="forceBigDecimals" value="false"/>
		</javaTypeResolver>

		<!-- targetProject:生成PO类的位置 -->
		<javaModelGenerator targetPackage="com.xxx.xxx.db.pojo"
							targetProject=".\src\main\java\">
			<!-- enableSubPackages:是否让schema作为包的后缀 -->
			<property name="enableSubPackages" value="false"/>
			<!-- 从数据库返回的值被清理前后的空格 -->
			<property name="trimStrings" value="true"/>
		</javaModelGenerator>
		<!-- targetProject:mapper映射文件生成的位置 -->
		<sqlMapGenerator targetPackage="com.xxx.xxx.db.mapper"
						 targetProject=".\src\main\java\">
			<!-- enableSubPackages:是否让schema作为包的后缀 -->
			<property name="enableSubPackages" value="false"/>
		</sqlMapGenerator>
		<!-- targetPackage:mapper接口生成的位置 -->
		<javaClientGenerator type="ANNOTATEDMAPPER"
							 targetPackage="com.xxx.xxx.db.mapper"
							 targetProject=".\src\main\java\">
			<!-- enableSubPackages:是否让schema作为包的后缀 -->
			<property name="enableSubPackages" value="false"/>
		</javaClientGenerator>
		<!-- 指定数据库表 -->
		<table schema="" tableName="tb_sys_dict">
			<generatedKey column="id" sqlStatement="JDBC" identity="true"/>
		</table>
	</context>
</generatorConfiguration>

有些时候我们可能会用到数据库中特殊类型的字段
如jsonb,如果不在代码生成配置中做特殊处理,那么我们生成的代码将无法读取或写入此类字段
所以以jsonb类型字段为例,我们创建一个处理器,并在代码生成配置中使用它

JsonTypeHandler

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.kingbase8.util.KBobject;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class JsonTypeHandler<T extends Object> extends BaseTypeHandler<T> {
    private static final ObjectMapper mapper = new ObjectMapper();
    static {
        mapper.configure(JsonParser.Feature.ALLOW_MISSING_VALUES, false);
        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
    }

    private Class<T> clazz;

    public JsonTypeHandler(Class<T> clazz) {
        if (clazz == null) throw new IllegalArgumentException("Type argument cannot be null");
        this.clazz = clazz;
    }

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException {
        KBobject jsonbObject = new KBobject();
        jsonbObject.setType("jsonb");
        try {
            jsonbObject.setValue(this.toJson(parameter));
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        ps.setObject(i, jsonbObject);
    }

    @Override
    public T getNullableResult(ResultSet rs, String columnName) throws SQLException {
        return this.toObject(rs.getString(columnName), clazz);
    }

    @Override
    public T getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        return this.toObject(rs.getString(columnIndex), clazz);
    }

    @Override
    public T getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        return this.toObject(cs.getString(columnIndex), clazz);
    }

    private String toJson(T object) {
        try {
            return mapper.writeValueAsString(object);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private T toObject(String content, Class<?> clazz) {
        if (content != null && !content.isEmpty()) {
            try {
                return (T) mapper.readValue(content, clazz);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        } else {
            return null;
        }
    }
}

修改配置文件

如下,如果我们的jsonb字段中存储的是一个列表,那么我们可以使用以下设置读取出内容。

  <table schema="" tableName="tb_sys_role">
      <generatedKey column="id" sqlStatement="JDBC" identity="true"/>
      <columnOverride column="flag" jdbcType="VARCHAR"
                      typeHandler="com.xxx.xxx.xxx.typehandler.JsonTypeHandler"
                      javaType="java.util.List"></columnOverride>
  </table>

如此之后,我们就可以直接读取并写入flag字段
要注意在这里我们读取出来的结构是List<Object> 或者List<Map> 的格式,需要自己转换实体类。
也可以在生成代码时直接指定对应实体类类型,配置方法会复杂一些,后面会在开一篇文章记录一下。

-----------------------------------------------

至此,整合KingbaseES8的步骤就结束了,并可以mybatis-generator生成对应文件

07-12 12:48