SpringBoot集成Mybatis-Plus
简介
MyBatis-Plus(简称 MP)是一个 MyBatis的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
使用 MyBatis-Plus 时,它提供了许多内置的功能,如 CRUD 操作、分页插件、性能分析插件等,可以大大简化数据库操作代码。
因此,mybatis-plus包含mybatis的所有功能,因此无需再次引入mybatis。
MyBatis-Plus官网地址:https://baomidou.com
寄语
很多小伙伴在引入MyBatis后,发现在Controller层就能直接实现CRUD,于是就把所有代码都写在了Controller层中,这样写确实能达到目的,但还是要看情况;尽管 MyBatis-Plus 提供了很多便利的功能,但这并不意味着你可以完全抛弃 Service 层。Service 层在项目中扮演着非常重要的角色,它负责处理业务逻辑、封装服务、实现代码解耦等。即便使用 MyBatis-Plus,也建议根据项目实际情况和需求来决定是否使用 Service 层。在大多数情况下,使用 Service 层可以提高代码的可维护性、可读性和可扩展性。
需要 Service 层的情况
- 业务逻辑处理:即使使用了 MyBatis-Plus,业务逻辑仍然需要在 Service 层处理。这包括数据验证、业务规则检查、事务管理等。
- 服务封装:Service 层可以封装多个 Mapper 的操作,提供更高层次的服务接口,使得 Controller 层调用更加简单。
- 代码解耦:将业务逻辑放在 Service 层可以实现 Controller 层和 DAO 层的解耦,便于维护和扩展。
- 单元测试:Service 层更容易进行单元测试,因为你可以模拟依赖项并专注于业务逻辑的测试。
不需要 Service 层的情况
- 简单 CRUD 应用:如果你的应用非常简单,只涉及基本的 CRUD 操作,并且没有复杂的业务逻辑,那么可能不需要 Service 层。
- 快速原型开发:在快速原型开发阶段,为了加速开发过程,有时可能直接在 Controller 层调用 MyBatis-Plus 提供的 CRUD 方法。
- 代码量较小的项目:对于非常小的项目,为了简化代码结构,可能会选择不在 Service 层编写代码。
功能
无侵入
只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
损耗小
启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
强大的 CRUD 操作
内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
支持 Lambda 形式调用
通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
支持主键自动生成
支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
支持 ActiveRecord 模式
支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
支持自定义全局通用操作
支持全局通用方法注入( Write once, use anywhere )
内置代码生成器
采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
内置分页插件
基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
分页插件支持多种数据库
支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库
内置性能分析插件
可输出 Sql 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
内置全局拦截插件
提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作
添加依赖
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.1</version>
</dependency>
添加配置
# Mybatis-plus配置
mybatis-plus:
global-config:
db-config:
# 全局逻辑删除字段值,或在实体字段加上注解@TableLogic 都会当做逻辑删除字段,优先按照注解来判断
logic-delete-field: delFlag
logic-delete-value: 2 # 逻辑已删除值
logic-not-delete-value: 0 # 逻辑未删除值
# 配置mapper的扫描,找到所有的mapper.xml映射文件
mapper-locations: classpath*:mapper/**/*Mapper.xml
configuration:
# 使全局的映射器启用或禁用缓存
cache-enabled: true
# 允许JDBC 支持自动生成主键
use-generated-keys: true
# 指定 MyBatis 所用日志的具体实现
log-impl: org.apache.ibatis.logging.slf4j.Slf4jImpl
# 配置默认的执行器.SIMPLE就是普通执行器;REUSE执行器会重用预处理语句(prepared statements);BATCH执行器将重用语句并执行批量更新
default-executor-type: reuse
# 使用驼峰命名法转换字段
map-underscore-to-camel-case: true
# 搜索指定包别名
type-aliases-package: com.cn.**.domain
生成主键策略
全局id生成策略
mybatis-plus:
global-config:
db-config:
#主键类型(auto:"自增id",assign_id:"全局唯一id(雪花算法,Long或者String类型)",assign_uuid:"全局唯一id(无中划线的uuid)",input:"自行设置id,默认null",none:"不设置主键id")
id-type: assign_id
局部id生成策略
使用@TableId注解配置id生成类型
@TableId(type = IdType.AUTO)
private Long id;
注意事项:
-
同时配置了这两种策略时,局部字段的ID生成策略优先级高于全局的id生成策略
-
使用雪花算法生成ID后,再次切换为主键自增的ID生成策略后会导致起始序列过大(没有重置起始序列值)
-
另外如果原先指定了@TableId(type = IdType.AUTO),然后去除这部分代码,会发生Tuncate操作(即清空表并重置ID起始值)
分页插件使用
/**
* Mybatis-plus配置类
*/
@EnableTransactionManagement
@Configuration
// 根据实际情况修改扫描包路径规则
@MapperScan(basePackages = "com.cn.**.mapper)
public class MybatisPlusConfig {
/**
* Mybatis-Plus 3.5.1新版分页插件API(推荐)
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
//乐观锁
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
//分页锁
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
元数据处理
mybatis-plus处理公共字段-自定义元数据对象处理器。
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
Timestamp time=new Timestamp(System.currentTimeMillis());
this.setFieldValByName("createTime", time, metaObject);
this.setFieldValByName("createBy", SecurityUtils.getUsername(), metaObject);
this.setFieldValByName("delFlag", 0, metaObject);
}
@Override
public void updateFill(MetaObject metaObject) {
Timestamp time=new Timestamp(System.currentTimeMillis());
this.setFieldValByName("updateTime", time, metaObject);
this.setFieldValByName("updateBy", SecurityUtils.getUsername(), metaObject);
}
}
实体类对应的公共字段添加注解标注
public class BaseEntity{
/**创建时间*/
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
/** 创建者 */
@TableField(fill = FieldFill.INSERT)
private String createBy;
/**更新时间*/
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
/** 更新者 */
@TableField(fill = FieldFill.INSERT_UPDATE)
private String updateBy;
}
字段数据加密
添加数据库加解密处理类,指明加解密字段类型
package com.cn.handlers;
@MappedJdbcTypes(JdbcType.VARCHAR)
public class EncryptHandler extends BaseTypeHandler<String> {
/**
* 线上运行后勿修改,会影响已加密数据解密
* AES密钥为对称密钥,密钥的长度可以为16字节、24字节、32字节
*/
private static final byte[] KEYS = "shc987654321camp".getBytes(StandardCharsets.UTF_8);
/**
* 设置参数
*/
@Override
public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {
if (StringUtils.isEmpty(parameter)) {
ps.setString(i, null);
return;
}
AES aes = SecureUtil.aes(KEYS);
String encrypt = aes.encryptHex(parameter);
ps.setString(i, encrypt);
}
/**
* 获取值
*/
@Override
public String getNullableResult(ResultSet rs, String columnName) throws SQLException {
return decrypt(rs.getString(columnName));
}
/**
* 获取值
*/
@Override
public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
return decrypt(rs.getString(columnIndex));
}
/**
* 获取值
*/
@Override
public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
return decrypt(cs.getString(columnIndex));
}
public String decrypt(String value) {
if (null == value) {
return null;
}
return SecureUtil.aes(KEYS).decryptStr(value);
}
}
在需要加密存储的数据库表字段上添加typeHandler指定处理器,且必须开启autoResultMap = true
关于
autoResultMap
的说明
autoResultMap是mybatis中的一个配置项,当为true时,mybatis会根据查询结果的列名和结果对象的属性名进行自动映射。如果列名和属性名一致,那么mybatis会自动将查询结果的值赋给结果对象的对应属性。MyBatis Plus 会自动构建一个 ResultMap 并注入到 mybatis 里(一般用不上)。
因为 MyBatis Plus 底层是 mybatis,所以一些 mybatis 的常识你要知道,MyBatis Plus 只是帮你注入了常用 crud 到 mybatis 里。注入之前可以说是动态的(根据你 entity 的字段以及注解变化而变化),但是注入之后是静态的(等于你写在 xml 的东西)而对于直接指定typeHandler,mybatis 只支持你写在2个地方:1、定义在 resultMap 里,只作用于 select 查询的返回结果封装
2、定义在 insert 和 update sql 的 #{property} 里的 property 后面(例:#{property,typehandler=xxx.xxx.xxx}),只作用于设置值而除了这两种直接指定 typeHandler,mybatis 有一个全局的扫描你自己的 typeHandler 包的配置,这是根据你的 property的类型去找 typeHandler 并使用。
@TableName(value = "user", autoResultMap = true)
@Data
public class User implements Serializable {
/**
* 加密敏感信息-地址
*/
@TableField(value = "address", typeHandler = EncryptHandler.class)
private String address;
}
条件构造器使用
mybatis-plus中有查询条件构造器QueryWrapper,可以在对常见的CRUD条件进行一些常见的构造,真实API在AbstractWrapper类中(采用了工厂模式进行顶层API设计)。
可以封装sql对象,包括where条件,order by排序,select哪些字段等等 查询包装类,可以封装多数查询条件,泛型指定返回的实体类。
public class Test{
/**
* 条件构造器使用
*/
@DeleteMapping("/delete")
public void delUser(){
// 1. 根据ID删除
userMapper.deleteById(6);
userMapper.deleteBatchIds(Collections.singleton(7));
// 2. 根据map中的参数作为条件删除
Map<String, Object> map = new HashMap<>();
map.put("name", "testIdType");
map.put("id", 7);
userMapper.deleteByMap(map);
// 3. 条件构造器为参数的进行删除
// 3.1 普通条件构造器(注意不要添加<>,Entity转Object会报错)
QueryWrapper wrapper = new QueryWrapper();
wrapper.eq("id",6);
userMapper.delete(wrapper);
// 3.2 lmbda表达式条件构造器
LambdaQueryWrapper<User> lambdaQuery = Wrappers.lambdaQuery();
lambdaQuery.eq(User::getId, 7).or().eq(User::getName, "testIdType");
userMapper.delete(lambdaQuery);
}
}
实现逻辑删除之后怎么实现物理删除
切换物理删除方式:把实体类中的逻辑删除字段删掉即可
1、直接去手动写sql去实现
2、写一个公共的MyBaseMapper去继承BaseMapper,然后定义一个deleteAbsoluteById()方法。后面各个业务的mapper可以通过继承MyBaseMapper来使用。
public interface MyBaseMapper<T> extends BaseMapper<T> {
/**
* 物理删除
*
* @param id
* @return
*/
int deleteAbsoluteById(Serializable id);
/**
* 批量物理删除
*
* @param idList
* @return
*/
int deleteAbsoluteByIds(@Param(Constants.COLL) Collection<?> idList);
/**
* 查询包含被逻辑删除的数据
* @param queryWrapper
* @return
*/
List<T> selectListData(@Param("ew") Wrapper<T> queryWrapper);
}
然后建一个实现类继承AbstractMethod,去实现相关逻辑
public class DeleteAbsoluteById extends AbstractMethod {
public DeleteAbsoluteById() {
super(SqlMethod.DELETE_BY_ID.getMethod());
}
@Override
public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
String method = "deleteAbsoluteById";
SqlMethod sqlMethod = SqlMethod.DELETE_BY_ID;
String sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(), tableInfo.getKeyColumn(), tableInfo.getKeyProperty());
SqlSource sqlSource = this.languageDriver.createSqlSource(this.configuration, sql, Object.class);
return this.addDeleteMappedStatement(mapperClass, method, sqlSource);
}
}
public class DeleteAbsoluteByIds extends AbstractMethod {
public DeleteAbsoluteById() {
super(SqlMethod.DELETE_BATCH_BY_IDS.getMethod());
}
@Override
public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
String method = "deleteAbsoluteByIds";
SqlMethod sqlMethod = SqlMethod.DELETE_BATCH_BY_IDS;
String sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(), tableInfo.getKeyColumn(), SqlScriptUtils.convertForeach(SqlScriptUtils.convertChoose("@org.apache.ibatis.type.SimpleTypeRegistry@isSimpleType(item.getClass())", "#{item}", "#{item." + tableInfo.getKeyProperty() + "}"), "coll", (String) null, "item", ","));
SqlSource sqlSource = this.languageDriver.createSqlSource(this.configuration, sql, Object.class);
return this.addDeleteMappedStatement(mapperClass, method, sqlSource);
}
}
public class SelectListData extends AbstractMethod {
public SelectListData(){
super(SqlMethod.SELECT_LIST.getMethod());
}
@Override
public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
String method = "selectListData";
SqlMethod sqlMethod = SqlMethod.SELECT_LIST;
String sqlWhere = sqlWhereEntityWrapper(true, tableInfo).replaceAll("del_flag='0'", "1=1");
String sql = String.format(sqlMethod.getSql(), sqlFirst(), sqlSelectColumns(tableInfo, true), tableInfo.getTableName(), sqlWhere, sqlOrderBy(tableInfo), sqlComment());
SqlSource sqlSource = this.languageDriver.createSqlSource(this.configuration, sql, modelClass);
return this.addSelectMappedStatementForTable(mapperClass, method, sqlSource, tableInfo);
}
}
再自定义一个sql注入器继承DefaultSqlInjector,把DeleteAbsoluteById(),DeleteAbsoluteByIds()方法加入进去就大功告成。
public class CustomSqlInjector extends DefaultSqlInjector {
@Override
public List<AbstractMethod> getMethodList(Class<?> mapperClass, TableInfo tableInfo) {
List<AbstractMethod> methodList = super.getMethodList(mapperClass, tableInfo);
methodList.add(new DeleteAbsoluteById());
methodList.add(new DeleteAbsoluteByIds());
methodList.add(new SelectListData());
return methodList;
}
}
代码生成器使用
说明:freemarker是作为代码生成器的模板依赖,必须存在;而knife4j是兼容生成的代码带Swagger注释
引入依赖
<!-- mybatis-plus代码生成器 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.1</version>
</dependency>
<!--velocity代码生成使用模板 -->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity</artifactId>
<version>1.7</version>
</dependency>
<!-- swagger依赖 -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
代码实现
注意
适用版本:mybatis-plus-generator 3.5.1 及其以上版本,对历史版本不兼容!3.5.1 以下的请参考 代码生成器旧
public class MybatisPlusGenerator {
/**
* 执行 run
*/
public static void main(String[] args) {
String packageName = "com.cn",author = "hviger";
generateConfig("test","user",author,packageName);
}
private static void generateConfig(String context,String tableName,String author,String packageName){
FastAutoGenerator.create(DATA_SOURCE_CONFIG.getUrl(),DATA_SOURCE_CONFIG.getUsername(),DATA_SOURCE_CONFIG.getPassword())
// 全局配置
.globalConfig(builder -> {
builder // (重要)配置后再次执行覆盖原有文件,建议配置
.fileOverride()
// (重要)配置输出的文件夹,springboot项目可以使用如下方式
.outputDir(System.getProperty("user.dir") + "/src/main/java")
// (重要)时间类型
.dateType(DateType.TIME_PACK)
// 配置生成文件中的author
.author(author)
// 是否启用kotlin单例模式
// .enableKotlin()
// 是否启用swagger,比如启用后会在entity中自动生成字段ApiModel注释等等
.enableSwagger()
// 注释日期的格式
.commentDate("yyyy-MM-dd")
// 禁止打开目录
.disableOpenDir()
.build();
})
// 包配置
.packageConfig(builder -> {
builder.parent(packageName) // 设置父包名
.moduleName(null) // 设置父包模块名
.controller("controller")
.entity("entity")
.service("service")
.serviceImpl("service.impl")
// .xml("mapper.xml") //默认方式是存储在mapper/xml目录
.pathInfo(Collections.singletonMap(OutputFile.mapperXml, System.getProperty("user.dir") + "/src/main/resources/mapper")) // 设置mapperXml生成路径
.mapper("mapper");
})
// 策略配置
.strategyConfig(builder -> {
builder
// 表名,多个英文逗号分隔?所有输入 all
.addInclude(tableName)
// .addTablePrefix("t_", "c_") // 设置过滤表前缀
// 跳过视图的生成
.enableSkipView()
.entityBuilder()
.enableLombok()
// (重要)主键模式,这里设置自动模式,配合mysql的自增主键
.idType(IdType.AUTO)
// entity文件名,可以配置统一后缀:%sEntity
.formatFileName("%s")
// activeRecord模式,可以直接在entity对象上执行insert、update等操作
.enableActiveRecord()
.build();
// builder.entityBuilder().superClass(BaseEntity.class).addSuperEntityColumns("createBy","createTime","update_by","update_time");
builder.mapperBuilder().enableMapperAnnotation().build();// 为mapper添加mapper注释
builder.controllerBuilder().enableHyphenStyle().enableRestStyle();//开启驼峰转连字符,开启@restController控制器
})
// 注入配置
.injectionConfig((builder -> {
//自定义对象,如果配置自定义模板就通过这样传参
Map<String,Object> map = new HashMap<>();
map.put("packageName",packageName);
map.put("datetime", DateTime.now());
map.put("context", context); //@RequestMapping("test")
// 排除父类字段
map.put("list", new String[]{"create_by","create_time","update_by","update_time"});
setAttr(tableName, map);
builder.customMap(map);
}))
/*
模板引擎配置,默认 Velocity(vm) 可选模板引擎 Beetl(btl) 或 Freemarker(ftl) 或 Enjoy(html)
还需要引用相关的依赖
.templateEngine(new BeetlTemplateEngine())
.templateEngine(new FreemarkerTemplateEngine())
.templateEngine(new EnjoyTemplateEngine())
*/
.templateEngine(new VelocityTemplateEngine())
.templateConfig(builder -> {
builder
.controller("vm/java/controller.java.vm")
.entity("vm/java/entity.java.vm")
.service("vm/java/service.java.vm")
.serviceImpl("vm/java/serviceImpl.java.vm")
.mapper("vm/java/mapper.java.vm")
.mapperXml("vm/xml/mapper.xml.vm");
})
.execute();
}
/**
* 数据源配置
*/
private static final DataSourceConfig DATA_SOURCE_CONFIG = new DataSourceConfig
.Builder("jdbc:mysql://localhost:3306/user_service?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8","root","123456")
.build();
/**
* 组装模板属性
*
* @param tableName 表名
* @param map 模板里面 自定义的属性
*/
private static void setAttr(String tableName,Map<String, Object> map ){
List<Map<String, Object>> columns = new ArrayList<>();
// 获取表信息sql
String tableSql = "select table_name , table_comment from information_schema.tables where table_schema = (select database()) and table_name = '" + tableName + "'";
// 获取字段信息sql
String columnSql = "select column_name , data_type ,column_key, column_comment from information_schema.columns " +
"where table_name = '" + tableName + "' and table_schema = (select database()) and column_name != 'id_new'";
// 利用现有的dataSourceConfig来获取数据库连接,查询表字段及备注等信息
try(
Connection conn = DATA_SOURCE_CONFIG.getConn();
PreparedStatement psTable = conn.prepareStatement(tableSql);
ResultSet rsTable = psTable.executeQuery();
PreparedStatement pscolumns= conn.prepareStatement(columnSql);
ResultSet rscolumns = pscolumns.executeQuery();
){
if(rsTable.next()){
String table_name = rsTable.getString("table_name");
map.put("tableName",table_name);
map.put("modelName",rsTable.getString("table_comment"));
// 类名 大驼峰
map.put("ClassName", StrUtil.upperFirst(StrUtil.toCamelCase(table_name)));
// 对象名 小驼峰
map.put("className",StrUtil.toCamelCase(table_name));
}
while (rscolumns.next()){
Map<String, Object> columnMap = new HashMap<>();
// 列名字、数据类型、java属性名字、java属性类型、备注
columnMap.put("name",rscolumns.getString("column_name"));
columnMap.put("dataType",rscolumns.getString("data_type"));
columnMap.put("javaField",StrUtil.toCamelCase(rscolumns.getString("column_name")));
columnMap.put("javaType",columnTypeToJavaType(rscolumns.getString("data_type")));
columnMap.put("comment", rscolumns.getString("column_comment"));
columns.add(columnMap);
Map<String, Object> pkColumn = new HashMap<>();
String columnKey = rscolumns.getString("column_key");
if("PRI".equals(columnKey)){
pkColumn.put("javaField",columnMap.get("javaField"));
pkColumn.put("javaType",columnMap.get("javaType"));
map.put("pkColumn", pkColumn);
}
}
} catch (Exception e) {
e.printStackTrace();
}
map.put("columns",columns);
}
/**
* 数据库类型转换为java类型
*
* @param columnType 数据库类型
* @return java类型
*/
private static String columnTypeToJavaType(String columnType) {
if(StrUtil.isNotEmpty(columnType)){
if(Arrays.asList(GenerateConstant.COLUMN_TYPE_STR).contains(columnType)){
return GenerateConstant.TYPE_STRING;
}
if(Arrays.asList(GenerateConstant.COLUMN_TYPE_TIME).contains(columnType)){
return GenerateConstant.TYPE_DATE;
}
if (Arrays.asList(GenerateConstant.COLUMN_TYPE_NUMBER).contains(columnType)) {
return GenerateConstant.TYPE_INTEGER;
}
if (Arrays.asList(GenerateConstant.COLUMN_TYPE_BIGINT).contains(columnType)) {
return GenerateConstant.TYPE_LONG;
}
if (Arrays.asList(GenerateConstant.COLUMN_TYPE_FLOAT).contains(columnType)) {
return GenerateConstant.TYPE_DOUBLE;
}
if (Arrays.asList(GenerateConstant.COLUMN_TYPE_DOUBLE).contains(columnType)) {
return GenerateConstant.TYPE_DOUBLE;
}
if (Arrays.asList(GenerateConstant.COLUMN_TYPE_DECIMAL).contains(columnType)) {
return GenerateConstant.TYPE_BIGDECIMAL;
}
}
return null;
}
}
public class GenerateConstant {
/**
* 数据库字符串类型
*/
public static final String[] COLUMN_TYPE_STR = {"char", "varchar", "nvarchar", "varchar2", "tinytext", "text", "mediumtext", "longtext"};
/**
* 数据库时间类型
*/
public static final String[] COLUMN_TYPE_TIME = {"datetime", "time", "date", "timestamp"};
/**
* 数据库数字类型
*/
public static final String[] COLUMN_TYPE_NUMBER = {"tinyint", "smallint", "mediumint", "int", "number", "integer", "bit"};
/**
* 数据库bigint类型
*/
public static final String[] COLUMN_TYPE_BIGINT = {"bigint"};
/**
* 数据库float类型
*/
public static final String[] COLUMN_TYPE_FLOAT = {"float"};
/**
* 数据库double类型
*/
public static final String[] COLUMN_TYPE_DOUBLE = {"double"};
/**
* 数据库decimal类型
*/
public static final String[] COLUMN_TYPE_DECIMAL = {"decimal"};
/**
* 字符串类型
*/
public static final String TYPE_STRING = "String";
/**
* 整型
*/
public static final String TYPE_INTEGER = "Integer";
/**
* 长整型
*/
public static final String TYPE_LONG = "Long";
/**
* 浮点型
*/
public static final String TYPE_DOUBLE = "Double";
/**
* 高精度计算类型
*/
public static final String TYPE_BIGDECIMAL = "BigDecimal";
/**
* 时间类型
*/
public static final String TYPE_DATE = "Date";
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步