人大金仓数据库KingbaseES支持的开发框架(基于JDBC)的介绍和使用之二之Mybaits篇

1
人大金仓数据库
KingbaseES
简介

        参见 https://blog.csdn.net/kangming7508/article/details/131983465

2 KES
支持的开发框架(基于
JDBC

        参见 https://blog.csdn.net/kangming7508/article/details/131983465

3 KES

Mybaits

3.1 Mybaits
简介

        MyBatis 是一个开源的持久层框架,它提供了将 SQL 语句与 Java 对象之

间的映射关系进行配置的功能。它的目标是简化数据库访问的开发过程,提供灵

活性和高性能。

        MyBatis 的核心思想是将 SQL 语句与 Java 对象进行映射,通过配置文件

或注解的方式,将 SQL 语句与数据库操作进行绑定。开发人员可以通过编写简

单的 SQL 语句,将数据的增删改查操作与 Java 对象的属性进行关联,从而实

现数据的持久化操作。

        MyBatis 提供了以下主要特点:

        灵活的 SQL 映射:MyBatis 允许开发人员使用 XML 配置文件或注解的方式, 将 SQL 语句与 Java 对象进行映射。这样可以灵活地编写和管理 SQL 语句,使 得开发人员可以更好地控制和优化数据库访问。

        参数映射:MyBatis 支持将 Java 对象的属性与 SQL 语句中的参数进行映 射,开发人员可以直接在 SQL 语句中使用对象的属性,而不需要手动拼接 SQL 语句。

        结果映射:MyBatis 支持将 SQL 查询结果与 Java 对象进行映射,开发人
员可以将查询结果直接映射为 Java 对象,简化了数据的处理过程。

        缓存支持:MyBatis 提供了一级缓存和二级缓存的支持,可以提高数据库访问的性能。

        插件扩展:MyBatis 允许开发人员编写插件来扩展框架的功能,可以在 SQL 执行前后进行拦截和处理,实现自定义的功能扩展。

        总的来说,MyBatis 是一个简单、灵活且功能强大的持久层框架,它通过将 SQL 语句与 Java 对象进行映射,提供了方便的数据库访问方式,同时也提供了缓存支持和插件扩展等功能,使得开发人员可以更高效地进行数据库操作。

3.2 Mybaits
原理

        Mybatis 是非常流行的 ORM 框架,主要着力点在于 POJO 与 SQL 之间的映 射关系。然后通过映射配置文件,将 SQL 所需的参数,以及返回的结果字段映射 到指定 POJO 。相对 Hibernate“O/R”而言,Mybatis 是一种“Sql Mapping” 的 ORM 实现。

        配置文件:配置数据库连接参数。

        映射文件:配置 SQL 语句和 JAVA 核心类 SqlSession 的映射。

人大金仓数据库KingbaseES支持的开发框架(基于JDBC)的介绍和使用之二之Mybaits篇

3.3 Mybatis
支持的驱动形态

框架名称

方言包

支持的驱动形态

Mybatis

 –

KES、PG形态

3.4 Mybatis 使用场景

        Mybatis 可以单独使用,直接操作 jdbc。也可以由 spring,spring-boot 等 框架整合使用。 Mybatis 主要应用于需求多变的互联网项目,例如电商项目等。

人大金仓数据库KingbaseES支持的开发框架(基于JDBC)的介绍和使用之二之Mybaits篇

3.5 Mybatis

KES
配置使用说明

        Mybatis 的 jar 包可以从官方网站下载,Mybatis 所使用的 JDBC 包 kingbase8-8.6.0.jar 位于$KINGBASE_HOME/Interface/jdbc 目录下。使用时将 Mybatis 包和 JDBC 包导入到项目的 Libraries 中并定义相关配置项即可。

3.5.1
定义
Mybatis
配置文件

        根据用户选择,更改配置文件。在 config.xml 中配置 JDBC 的驱动信息参数, 数据库服务器信息参数和登陆用户信息参数。当然,这些参数也可以根据用户应 用需求,单独生成 property 文件,针对不用的应用场景,导入不同的属性文件。

        这里以 property 为例说明下 config.xml 的配置使用。

        在property 中增加如下声明:

jdbc.driverClassName=com.kingbase8.Driver

jdbc.url=jdbc:kingbase8://localhost:54321/TEST

jdbc.username=登录名

jdbc.password=登录密码

        在config.xml 中增加如下声明:

    

        

        

            

            

            

            

        

    

        

3.5.2
配置
mapper.xml

        主要是配置 SQL 映射关系,根据用户的需求,自定义映射关系。这里以一个 简单的配置为例。

        在 mapper.xml 中增加如下声明:

   

        DROP TABLE IF EXISTS ${sql} CASCADE

   

   

        ${sql}

   

   

       

       

       

       

       

   

   

        select * from t_num

   

    <select id="selectNumTableByID" parameterType="int"

    resultMap=”NumTableMap”>

        select * from t_num where id=#{value}

   

    <select id="selectNumTableByAge" parameterType="int"

    resultMap=”NumTableMap”>

        select * from t_num where age=#{value}

   

    <select id="selectNumTableByName" parameterType="string"

    resultMap=”NumTableMap”>

        select * from t_num where name=#{value}

   

    <insert id="insertNumTable" parameterType="NumEntity"

    keyProperty=”userId”>

        insert into t_num(id,age,name,wage,cost)

            values(#{userId},#{userAge},#{userName},#{userWage},#{userCost})

   

   

        update t_num set age=#{userAge},name=#{userName},wage=#{userWage},

            cost=#{userCost}where id=#{userId}

   

   

        delete from t_num where id=#{value}

   

   

        delete from t_num

   

3.6 Mybatis
程序示例

3.6.1
接口和实例开发示例


1
) 在
Java
中 读 取
property

config
属 性 , 配 置 到
sqlSessionFactory

@BeforeClass

public static void setUpClass() throws Exception {

    InputStream fis = null;

    InputStream inputStream = null;

    try {

        /* 创建一个 sqlSessionFactory */

        Properties prop = new Properties();

        fis = Resources.getResourceAsStream(“propertty”);

        prop.load(fis);

        inputStream = Resources.getResourceAsStream(“MyConfig.xml”);

        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream,

        “development”, prop);

    } catch(Exception e) {

        e.printStackTrace();

    }

}


2
) 在
Java
中配置
mapper.xml
对应的
namespace
,为
Interface
类型

public interface MybatisDao {

    int createNewTableMap(Map param);

    int dropTable(Map param);

    /*

     * new number table

     */

    public List selectNumTable();

    public NumEntity selectNumTableByID(int id);

    public List selectNumTableByAge(int age);

    public List selectNumTableByName(String name);

    public void insertNumTable(NumEntity user);

    public void updateNumTableById(NumEntity user);

    public void deleteNumTableById(int id);

    public void deleteNumTable();

}


3
) 在
Java
中进行表的查询操作

public void testNumTable() {

    SqlSession session = sqlSessionFactory.openSession();

    int i = 1;

    try {

        MybatisDao userOperation = session.getMapper(MybatisDao.class);

        List users = userOperation.selectNumTable();

        for (NumEntity user : users) {

            System.out.println(user);

            Assert.assertEquals(i, user.getId());

            Assert.assertEquals(AGE+i, user.getUserAge());

            Assert.assertEquals(name[i], user.getUserName());

            Assert.assertEquals(“yes”,WAGE+(double)(i*100)/(double)(3.0),

            user.getUserWage(),0.000001);

            Assert.assertEquals(“yes”,COST+(double)(i*100)/(double)(3.0),

            user.getUserCost(),0.01);

            i++;

        }

    } finally {

        session.close();

    }

}


4
) 在
Java
中进行表的插入操作

public void testInsertNumTable() {

    int i = 1 ;

    SqlSession session = sqlSessionFactory.openSession();

    try {

        MybatisDao userOperation = session.getMapper(MybatisDao.class);

        NumEntity user = new NumEntity();

        name[1] = “张三”;

        name[2] = “李四”;

        name[3] = “王五”;

        name[4] = “赵二”;

        name[5] = “小北”;

        name[6] = “小东”;

        name[7] = “小西”;

        name[8] = “小南”;

        name[9] = “小明”;

        for (i=1;i<10;i++) {

            user.setId(i);

            user.setUserAge(AGE+i);

            user.setUserName(name[i]);

            user.setUserWage(WAGE+(double)(i*100)/(double)(3.0));

            user.setUserCost(COST+(double)(i*100)/(double)(3.0));

            userOperation.insertNumTable(user);

            session.commit();

            System.out.println(user);

        }

    } finally {

        session.close();

    }

}


5
) 在
Java
中进行表的更新操作

public void testUpdateNumTable() {

    int i = 1 ;

    SqlSession session = sqlSessionFactory.openSession();

    try {

        MybatisDao userOperation = session.getMapper(MybatisDao.class);

        NumEntity user = new NumEntity();

        /* 更新一行新的数据id=1 */

        user = userOperation.selectNumTableByID(1);

        user.setUserAge(AGE+i);

        user.setUserName(name[0]);

        user.setUserWage(WAGE+(double)(i*100)/(double)(3.0));

        user.setUserCost(COST+(double)(i*100)/(double)(3.0));

        userOperation.updateNumTableById(user);

        session.commit();

    } finally {

        session.close();

    }

}


6
) 在
Java
中进行表的删除操作

public void testDeleteNumTable() {

    int i = 1 ;

    SqlSession session = sqlSessionFactory.openSession();

    try {

        MybatisDao userOperation = session.getMapper(MybatisDao.class);

        userOperation.deleteNumTable();

        session.commit();

    } finally {

        session.close();

    }

}

3.6.2
存储过程的使用


1
) 如果开发过程中需使用数据库的存储过程,可在
mapper.xml
中增加如下内容:

<select id="getPerson" resultType="java.util.Map"

     statementType=”CALLABLE”>

     {

     call getPerson(

     #{a,mode=IN,jdbcType=INTEGER},

     #{b,mode=OUT,jdbcType=VARCHAR},

     

     #{param2,mode=OUT,javaType=ResultSet,jdbcType=OTHER,resultMap=cursorMap}

     )

     }


2
) 创建表和数据:

create or replace function getPerson(b out refcursor)

as $$

begin

open b for select * from person;

end;

$$ language plsql;


3
) 调用存储过程:

Map map = mapper.getPerson2(null, null, null);

ResultSet o = (ResultSet) map.get(“getperson2”);

o.next();

System.out.println(o.getString(1));

System.out.println(o.getString(2));

System.out.println(o.getString(3));

3.7
注意事项

         KingbaseES
支持
array
数据类型,在
MyBatis
中需要增加
ArrayTypeHandler 来处理这一特殊类型;

        KingbaseES 支持
json
数据类型,在
Mybatis
中需要增加
JsonTypeHandler 来处理这一特殊类型;

        KingbaseES 支持
hstore
数据类型,在
Mybatis
中需要增加 HstoreTypeHandler来处理这一特殊类型;

        KingbaseES 支持
XML
数据类型,在
Mybatis
的映射中,需要对 xml 数据类型做标注,如: insert into t_xml(value) values ((#{content})::xml)

        KingbaseES 适配
Mybatis

pagehelper 插件时,由于无法通过连接自动获取数据库类型,需要将
helperDialect
设置成
postgresql
,配置如下:

3.8
常见问题

3.8.1 Mybatis
设置
SQL
超时时间

  mybatis 如果不指定
,
默认超时时间是不做限制的
,
默认值为 0. mybatis sql
配置超时时间有两种方法
:

1
、全局配置

        在 mybatis
配置文件的
settings
节点中
,
增加如下配置

        以秒为单位的全局 SQL
超时时间设置
,
当超出了设置的超时时间时
,会抛出SQLTimeoutException

2

Mapper XML
配置

 在 mapper xml
文 件 中 对 具 体 一 个
sql
进 行 设 置
, 方 法 为 在select/update/insert
节点中配置
timeout
属性
,
超时时间并只作用于这一个
sql.

3.8.2 Mybatis
非法
long
值问题

答:
1
:这个问题是由于
V7

JDBC
默认把
TEXT
类型对应为
LONGVARCHAR,而
Mybatis
又把
LONGVARCHAR
类型默认按照
CLOB
对象处理,造成和 Hibernate非法
long
值的情形类似,但是
Mybatis
没有提供方言机制,所以无法像 Hibernate 那样同过方言包控制,只能把
V7

JDBC

TEXT
类的值对应到
Varchar 来处理,就解决非法值问题。

2
:如果用新的
JDBC
还出此问题,说明用户自己把
string
类型的
jdbcType 手动设置为
LONGVARCHAR
了。解决办法:就是把
jdbcType
去掉或者设置为 VARCAHR即可。

3.8.3
Mybatis
报错:字段的类型为
TEXT,
但表达式的类型

BYTEA
你需要重写或转换表达式

答:
1
:这个问题需要查看出错
SQL

mapper
文件,需要知道 mapper 中参数是否指定了类型,从正常逻辑上来说不应该出现这样的转换,应该可通过调整参数类型解决。

2
:这个也可以从
JDBC
入手,把所有
Bind
参数设置
Oid.BYTEA
的全都改为
0,让服务器自己推断类型。

3.8.4 Mybatis
控制
JDBC
底层不走预编译

答:在
mapper
文件中可以使用
statementType
标记使用什么的对象操作 SQL语句。
statementType
:标记操作
SQL
的对象 ,如 statementType=”STATEMENT” 要实现动态传入表名、列名,需要做如下修改,
sql 里的所有变量取值都改成${xxxx}
,而不是
#{xxx}

取值说明:

1

STATEMENT:
直接操作
sql
,不进行预编译,获取数据:
$—Statement

2

PREPARED:
预处理,参数,进行预编译,获取数据:#—–PreparedStatement: 默认

3

CALLABLE:
执行存储过程
————CallableStatement

3.8.5 Mybatis
控制
Bind
参数

答:
#{}
:相当于
JDBC
中的
PreparedStatement
,走
Bind 报文。 ${}
:是输出变量的值,字串替换,不走
Bind。 简单说,
#{}
是经过预编译的,是安全的;
${}
是未经过预编译的,仅仅是取变量

的值,是非安全的,存在
SQL
注入。

3.8.6
Mybatis
使用
pagehelper
插件

Mybatis 使用该插件需要将 helperDialect 设置成 postgresql,如不指定,会报错:com.github.pagehelper.PageException
无法自动获取数据库类型,请通过 helperDialect

数指定!

1.直接使用 Mybatis 设置如下:

2.springboot
整合
mybatis
使用如下:


pom
文件中引入
Pagehelper
分页插件:

com.github.pagehelper

pagehelper-spring-boot-starter

1.2.5

配置分页插件,打开 application.properties,添加如下配置信息:

#分页插件

pagehelper.helper-dialect=postgresql

如果需要通过 url 自动识别方言,配置 dialectAlias 参数,具体的实现类和 pg的映射保持一致即可,根据不同的 pagehelper 版本来定。以 pagehelper-5.1.10为例,如下:

pagehelper:

        dialectAlias: kingbase8=com.github.pagehelper.dialect.helper.HsqldbDialect

3.8.7
Mybatis
使用自动返回主键功能

该功能使用在 V7 仅支持 insert 语句建表语句,要求表含有主键,且主键自增:

create table t_user (id int identity primary key,username text,password text,sex bo

olean);

在 mapper 文件里配置:

insert into t_user (username,password,sex) values

(#{username},#{password},#{sex})

注意:如果使用tk-mybatis提供的mapper接口,V7需要mapper包的版本在3.4.0及以上,否则使用 update 相关的接口时,会报“不能返回 generatedkeys 或没有指定返回”的错误。

3.8.8 Mybatis
配置
databaseId

SELECT * FROM product3

3.8.9 Mybatis
使用匿名块插入语句报错

Mybatis中使用begin insert …;insert…; end;格式的语句插入数据,报无法识别的GBK编码:’0x00’或者指定了连接参数prepareThreshold=-1报Can‘t change resolved type for param:1 from 1043 to 25.该问题属于plsql问题需要升级数据库版本。

在升级数据库版本后,如果出现类型转换错误,则使用强转(例如?::bytea)把其转换为对应类型,出现该错误的原因为匿名块无法识别oid绑定类型为0的参数,会将其默认识别为text,传给下层时无法转换为对应类型,就会报错。特别地,如果字段类型为二进制,如bytea、blob,如果参数内容有数据库无法识别的编码的话,转换成text就会报无法转换的编码错误,此时指定连接参数bytestype=bytea即可。

3.8.10Mybatis
使用
ScriptRunner
执行含
plsql

sql
脚本报错

1. ScriptRunner默认按照自定义的分隔符每行执行,分隔符默认为分号,如果sql脚本中包含plsql语句,按照分号分割出来的语句是不正确的,所以可以使用setDelimiter(String)来设置自定义的分隔符,如设置分隔符为”/”,则sql脚本中的每条语句后都添加”/”,ScriptRunner将会按照此对语句进行分割,连接KingbaseES时,普通语句之间无需使用分隔符,驱动会对普通语句进行分割;

2. 或者可以通过runner.setSendFullScript(true);设置将sql脚本一次发送,但是由于驱动不会对包含plsql的多语句进行分割,所以会报”无法插入多条命令到一个准备好的语句中“,此时指定jdbc连接参数preferQueryMode=simple走简单查询报文即可。

3.8.11Mybatis
使用游标的注册方式

        {#{out_return,mode=OUT,javaType=ResultSet,jdbcType=OTHER, resultMap=tempMap} = call proc_aaaaa() }

    

注意:

1.jdbcType只能设置为OTHER,不能设置为CURSOR,Mybatis的CURSOR的值为-10,是OracleCURSOR的值,不是Types.REF_CURSOR的值,我们不支持;

 如果没有设置javaType的类型,返回值的类型为ResultSet,如果设置了返回值的类型为ResultSet,则返回值为List对象。

3.8.12Mybatis

json
类型示例

建表:

create table t_json(id serial,content json);

实体类:

package com.test.entity;

public class JsonEntity {

    private int id;

    private Object fcontent;

    public  int getId() {

        return id;

    }

    public void setId( int id) {

        this.id =  id;

    }

    public  Object getContent() {

        return fcontent;

    }

    public void setContent(Object b) {

        this.fcontent =  b;

    }

    @Override  

    public String toString() {  

        return “id=” + this.id ;  

    }  

}

JsonTypeHandler.java

package com.test.handler;

import java.sql.CallableStatement;

import java.sql.PreparedStatement;

import java.sql.ResultSet;

import java.sql.SQLException;

import org.apache.ibatis.type.BaseTypeHandler;

import org.apache.ibatis.type.JdbcType;

import com.test.utils.JsonUtil;

// 继承自BaseTypeHandler 使用Object是为了让JsonUtil可以处理任意类型

public class JsonTypeHandler extends BaseTypeHandler {

    @Override

    public void setNonNullParameter(PreparedStatement ps, int i, Object parameter,

            JdbcType jdbcType) throws SQLException {

        ps.setString(i, JsonUtil.stringify(parameter));

    }

    @Override

    public Object getNullableResult(ResultSet rs, String columnName)

            throws SQLException {

        return JsonUtil.parse(rs.getString(columnName), Object.class);

    }

    @Override

    public Object getNullableResult(ResultSet rs, int columnIndex) throws SQLException {

        return JsonUtil.parse(rs.getString(columnIndex), Object.class);

    }

    @Override

    public Object getNullableResult(CallableStatement cs, int columnIndex)

            throws SQLException {

        return JsonUtil.parse(cs.getString(columnIndex), Object.class);

    }

}

JsonUtil.java

package com.test.utils;

import java.io.OutputStream;

import java.text.SimpleDateFormat; 

import org.apache.ibatis.logging.Log;

import org.apache.ibatis.logging.LogFactory;

import org.codehaus.jackson.map.DeserializationConfig;

import org.codehaus.jackson.map.ObjectMapper;

import org.codehaus.jackson.map.annotate.JsonFilter;

import org.codehaus.jackson.map.ser.impl.SimpleBeanPropertyFilter;

import org.codehaus.jackson.map.ser.impl.SimpleFilterProvider;

import org.springframework.core.annotation.AnnotationUtils;

import org.codehaus.jackson.map.SerializationConfig;

public class JsonUtil {

    private static Log log = LogFactory.getLog(JsonUtil.class);

    private static ObjectMapper objectMapper = null;

    static {

        objectMapper = new ObjectMapper();

        objectMapper.setDateFormat(new SimpleDateFormat(“yyyy-mm-dd”));

        objectMapper.disable(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES);

        objectMapper.configure(SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS, false);

        objectMapper.setFilters(new SimpleFilterProvider().setFailOnUnknownId(false));

    }

    public static String stringify(Object object) {

        try {

            return objectMapper.writeValueAsString(object);

        } catch (Exception e) {

            log.error(e.getMessage(), e);

        }

        return null;

    }

    public static String stringify(Object object, String… properties) {

        try {

            return objectMapper

                    .writer(new SimpleFilterProvider().addFilter(AnnotationUtils.getValue(

                            AnnotationUtils.findAnnotation(object.getClass(), JsonFilter.class)).toString(), 

                                SimpleBeanPropertyFilter.filterOutAllExcept(properties)))

                    .writeValueAsString(object);    

        } catch (Exception e) {

            log.error(e.getMessage(), e);

        }

        return null;

    }

    public static void stringify(OutputStream out, Object object) {

        try {

            objectMapper.writeValue(out, object);

        } catch (Exception e) {

            log.error(e.getMessage(), e);

        }

    }

    public static void stringify(OutputStream out, Object object, String… properties) {

        try {

            objectMapper.writer(new SimpleFilterProvider().addFilter(

                        AnnotationUtils.getValue(AnnotationUtils.findAnnotation(object.getClass(), JsonFilter.class)).toString(), 

                            SimpleBeanPropertyFilter.filterOutAllExcept(properties))).writeValue(out, object);    

        } catch (Exception e) {

            log.error(e.getMessage(), e);

        }

    }

    public static T parse(String json, Class clazz) {

        if (json == null || json.length() == 0) {

            return null;

        }

        try {

            return objectMapper.readValue(json, clazz);

        } catch (Exception e) {

            log.error(e.getMessage(), e);

        }

        return null;

    }

}

映射文件:

 

   

   

    

    

        

        

      

    

          select * from ${name}

    

    

          select * from t_json where id=#{id}

    

     

        insert into t_json (content) values ((#{fcontent, typeHandler=com.test.handler.JsonTypeHandler})::json)

   

   

        update t_json set content=(#{fcontent, typeHandler=com.test.handler.JsonTypeHandler})::json where t_json.id=#{id}

   

   

        delete from ${name}

   

 

3.8.13 Mybatis 一次插入参数过多问题

KES数据库一次最大能绑定的参数个数是32767,如果一次绑定参数个数超过就会报错

下面是一个一次绑定N个参数的SQL配置:

INSERT INTO testtable(

a,b,c,d

)

SELECT 

#{item.parma1,jdbcType=BIGINT},

#{item.parma2,jdbcType=INTEGER},

#{item.parma3,jdbcType=INTEGER},

#{item.parma4,jdbcType=VARCHAR},

FROM DUAL

当list很大时,就会拼接一个超过最大参数个数限制的SQL,这里提供两种思路解决类似问题;

1:不使用参数绑定,使用参数注入,把#换成$,就没有参数个数限制,性能和当前基本一致。

2:依然使用参数绑定,但SQL需要改写为常规Insert的SQL,需要使用ExecutorType.BATCH模式,批处理性能更好,具体例子:

SqlSession session = sessionFactory.openSession(ExecutorType.BATCH);

for (Model model : list) {

    session.insert(“insertStatement”, model);

}

session.flushStatements();

4 KES 与 MyBatis-Plus

4.1 Mybaits-Plus
简介

        MyBatis-Plus 是基于 MyBatis 的增强工具库,旨在简化 MyBatis 的开发流程,提供更便捷的数据库访问操作。它是对 MyBatis 的扩展,提供了一系列的增强功能和便利的开发特性。

        MyBatis-Plus 的主要特点包括:

        简化的 CRUD 操作:MyBatis-Plus 提供了一套简化的 API,可以通过少量的代码实现常见的增删改查操作,无需手动编写 SQL 语句。

        自动生成代码:MyBatis-Plus 提供了代码生成器,可以根据数据库表结构自动生成实体类、Mapper 接口和 XML 配置文件,减少了手动编写重复代码的工作量。

        Lambda 表达式支持:MyBatis-Plus 支持使用 Lambda 表达式进行条件构造,可以更直观地编写查询条件,提高代码的可读性和维护性。

        分页查询支持:MyBatis-Plus 提供了方便的分页查询功能,可以轻松地进行分页查询操作。

        逻辑删除支持:MyBatis-Plus 支持逻辑删除,可以通过配置实现软删除功能,将删除操作转换为更新操作,保留数据的完整性。

        自动填充字段:MyBatis-Plus 支持自动填充字段,可以在插入或更新操作时自动填充指定的字段,如创建时间、更新时间等。

        乐观锁支持:MyBatis-Plus 提供了乐观锁的支持,可以通过版本号或时间戳等方式实现并发控制,避免数据冲突。

        总的来说,MyBatis-Plus 是一个功能强大、易于使用的 MyBatis 增强工具库,它简化了数据库访问的开发流程,提供了诸多便利的特性和功能,使得开发人员可以更高效地进行数据库操作。

4.2 Mybatis-Plus
支持的驱动形态

框架名称

方言包

支持的驱动形态

Mybatis-Plus

 –

KES、PG形态

4.3 Mybatis-Plus
框架结构

人大金仓数据库KingbaseES支持的开发框架(基于JDBC)的介绍和使用之二之Mybaits篇

4.4 Mybatis-Plus
配置说明

         Mybatis-Plus 的 jar 包可以从官方网站下载,Mybatis-Plus 所使用的 JDBC包 kingbase8-8.6.0.jar 位于$KINGBASE_HOME/Interface/jdbc 目录下。使用时将 Mybatis-Plus 包和 JDBC 包导入到项目的 Libraries 中并定义相关配置项即可。

4.4.1
配置
Spring
配置文件


1
) 配置
MapperScan


2
) 调

SqlSessionFactory

Mybatis-Plus

SqlSessionFactory

4.4.2
配置实体类

@TableName(value = “tb_employee”) /* 指定表名 */

public class Employee {

    /*  value与数据库主键列名一致,若实体类属性名与表主键列名一致可省略value */

    @TableId(value = “id”, type = IdType.AUTO) /* 指定自增策略 */

    private Integer id;

    /*  若没有开启驼峰命名,或者表中列名不符合驼峰规则,可通过该注解 */

    /*  指定数据库表中的列名,exist标明数据表中有没有对应列 */

    @TableField(value = “last_name”, exist = true)

    private String lastName;

    private String email;

    private boolean gender;

    private Integer age;

    private Date date;

    public Integer getId() {

        return id;

    }

    public void setId(Integer id) {

        this.id = id;

    }

    public String getLastName() {

        return lastName;

    }

    public void setLastName(String lastName) {

        this.lastName = lastName;

    }

    public String getEmail() {

        return email;

    }

    public void setEmail(String email) {

        this.email = email;

    }

    public boolean isGender() {

        return gender;

    }

    public void setGender(boolean gender) {

        this.gender = gender;

    }

    public Integer getAge() {

        return age;

    }

    public void setAge(Integer age) {

        this.age = age;

    }

    public Date getDate() {

        return date;

    }

    public void setDate(Date date) {

        this.date = date;

    }

    @Override

    public String toString() {

        return “Employee [id=” + id + “, lastName=” + lastName + “,

        email=” + email + “, gender=” + gender +”, age=” + age + “,

        date=” + date + “]”;

    }

}

4.4.3
定义
Mapper
接口

@Mapper

public interface EmplopyeeDao extends BaseMapper {

}

4.4.4

Java
中进行表的增删改查操作

@RunWith(SpringJUnit4ClassRunner.class)

@ContextConfiguration({ “classpath:spring/spring-dao.xml” })

public class test {

    @Autowired

    private DataSource dataSource;

    @Test

    public void testDataSource() throws SQLException {

        System.out.println(dataSource.getConnection());

    }

    @Autowired

    private EmplopyeeDao emplopyeeDao;

    @Test

    public void testInsert() {

        Employee employee = new Employee();

        employee.setLastName(“tom”);

        employee.setEmail(“dfbb@163.com”);

        employee.setGender(false);

        employee.setAge(22);

        employee.setDate(new Date(System.currentTimeMillis()));

        emplopyeeDao.insert(employee);

        /*  mybatisplus会自动把当前插入对象在数据库中的id写回到该实体中 */

        System.out.println(employee.getId());

    }

    @Test

    public void testUpdate() {

        Employee employee = new Employee();

        employee.setId(1);

        employee.setLastName(“更新测试”);

        /* 根据id进行更新,没有传值的属性就不会更新 */

        emplopyeeDao.updateById(employee);

        /* 根据id进行更新,没传值的属性就更新为null */

        emplopyeeDao.update(employee, null);

    }

    @Test

    public void testSelectById() {

        Employee employee = emplopyeeDao.selectById(2);

        System.out.println(employee.toString());

    }

    @Test

    public void testSelect() {

        Map columnMap = new HashMap();

        /* 写表中的列名 */

        columnMap.put(“last_name”, “更新测试”);

        columnMap.put(“gender”, false);

        List employees = emplopyeeDao.selectByMap(columnMap);

        System.out.println(employees.size());

    }

    @Test

    public void testSelectByPage() {

        IPage employees = emplopyeeDao.selectPage(new Page(1, 5),

                new QueryWrapper().between(“age”, 18, 50).eq(“gender”,

                false).eq(“last_name”, “更新测试”));

        System.out.println(employees);

    }

    @Test

    public void testDeleteById() {

        System.out.println(emplopyeeDao.deleteById(1));

    }

    @Test

    public void testDelete() {

        Map columnMap = new HashMap();

        columnMap.put(“gender”, false);

        columnMap.put(“age”, 18);

        emplopyeeDao.deleteByMap(columnMap);

    }

    @Test

    public void testSelectByPage1() {

        Integer[] ints = { 1, 18, 19, 20, 21, 22, 23, 24, 25 };

        IPage employees = emplopyeeDao.selectPage(new Page(1, 5),

                new QueryWrapper().between(“age”, 18, 50).eq(“gender”,

                false).eq(“last_name”, “更新测试”).in(true,

                        “age”, Arrays.asList(ints)));

        System.out.println(employees.toString());

        System.out.println(employees.getTotal());

        System.out.println(employees.getPages());

        System.out.println(employees.getRecords());

    }

}

4.5 注意事项

        Mybatis-Plus2.x 和 Mybatis-Plus3.x 的包结构不同,注意引用时的包路径的区别;        

        KingbaseES 适配 Mybatis-Plus
时,由于
Mybatis-Plus
无法识别
KingbaseES
数据库类

型,故在相关配置中需将其配置成
postgresql
,如:

在使用分页插件时,配置方言类型为postgresql示例:

   

       

       

           

       

   

Mybatis-Plus2.x和Mybatis-Plus3.x的包结构不同,注意引用时的包路径的区别;

KingbaseES适配Mybatis-Plus时,由于Mybatis-Plus无法识别KingbaseES数据库类型,故在相关配置中需将其配置成postgresql,如:

在使用分页插件时,配置方言类型为postgresql示例:

   

       

       

           

       

   

本文来自网络,不代表协通编程立场,如若转载,请注明出处:https://net2asp.com/36c82d2780.html