sql2java是一个轻量级数据库(SQL)访问代码(java)生成器,是在国外一款同名开源项目(https://sourceforge.net/projects/sql2java)的基础上重写的ORM工具,以maven 插件方式运行,目前在mysql下测试通过已经应用于实际项目开发中
编译要求 JDK 1.7,Maven 3.5 以上版本
# 下载源码
git clone https://gitee.com/l0km/sql2java.git
cd sql2java
# 编译全部
mvn install
sql2java的maven插件已经发布到maven中央仓库,如果只是要运行maven插件无需编译本项目
如下创建一个最简的参数配置文件(mysql2java.properties),用于告诉sql2java如何生成java代码, "#"起始的行为注释
# 指定 JDBC driver,告诉sql2java如何连接数据
jdbc.driver=com.mysql.jdbc.Driver
# 对于 mysql 数据库,如果 useInformationSchema=false 或没指定,则无法获取表中的注释信息
jdbc.url=jdbc:mysql://localhost:3306/test?characterEncoding=utf8&useInformationSchema=true
jdbc.username=root
jdbc.password=
jdbc.schema=test
# 定义生成代码的包名
codewriter.package=sql2java.test
执行如下maven插件,即开始从数据库中读取表结构信息并生成对应的java代码到当前文件夹下(src/main)
$ mvn com.gitee.l0km:sql2java-maven-plugin:generate \
-Dsql2java.classpath=lib/mysql-connector-java-5.1.43-bin.jar \
-Dsql2java.propfile=mysql2java.properties
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building sql2java test 0.0.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- sql2java-maven-plugin:1.0.6-SNAPSHOT:generate (default-cli) @ sql2java-test ---
database properties initialization
[INFO] classpath: [file:/D:/j/sql2java.test/lib/mysql-connector-java-5.1.43-bin.jar]
Connecting to root on jdbc:mysql://localhost:3306/test?characterEncoding=utf8&useInformationSchema=true ...
Connected.
Database server :MySQL.
Loading table list according to pattern t_% ...
table t_book found
table t_user found
samePrefix = [t_]
Loading columns ...
t_book.id INT default value: null
t_book.name VARCHAR default value: null
t_book.borrower INT default value: null
t_book found 3 columns
t_user.id INT AUTOINCREMENT default value: null
t_user.name VARCHAR default value: null
t_user.birthdate DATE default value: null
t_user.phone VARCHAR default value: null
t_user.address VARCHAR default value: null
t_user found 5 columns
Database::loadPrimaryKeys
Found primary key (seq,name) (1,id) for table 't_book'
Found primary key (seq,name) (1,id) for table 't_user'
Loading imported keys ...
t_book.id -> t_user.id found seq:1 foreign key name:fk_id
UPDATE_RULE:NO_ACTION DELETE_RULE:RESTRICT
Loading indexes ...
Found interesting index phone_UNIQUE on phone for table t_user
Loading procedures ...
Generating template /templates/velocity/java5g/perschema/constant.java.vm
.... writing to src/main\java\sql2java\test\Constant.java
java\sql2java\test\Constant.java done.
Generating template /templates/velocity/java5g/perschema/database.properties.vm
.... writing to src/main\resources/conf\database.properties
resources/conf\database.properties done.
Generating template /templates/velocity/java5g/perschema/gu.sql2java.irowmetadata.vm
.... writing to src/main\resources/META-INF/services\gu.sql2java.IRowMetaData
resources/META-INF/services\gu.sql2java.IRowMetaData done.
Generating template /templates/velocity/java5g/pertable/bean.java.vm
.... writing to src/main\java\sql2java\test\BookBean.java
java\sql2java\test\BookBean.java done.
Generating template /templates/velocity/java5g/pertable/manager.interface.java.vm
.... writing to src/main\java\sql2java\test\IBookManager.java
java\sql2java\test\IBookManager.java done.
Generating template /templates/velocity/java5g/pertable/metadata.java.vm
.... writing to src/main\java\sql2java\test\BookMetaData.java
java\sql2java\test\BookMetaData.java done.
Generating template /templates/velocity/java5g/pertable/bean.java.vm
.... writing to src/main\java\sql2java\test\UserBean.java
java\sql2java\test\UserBean.java done.
Generating template /templates/velocity/java5g/pertable/manager.interface.java.vm
.... writing to src/main\java\sql2java\test\IUserManager.java
java\sql2java\test\IUserManager.java done.
Generating template /templates/velocity/java5g/pertable/metadata.java.vm
.... writing to src/main\java\sql2java\test\UserMetaData.java
java\sql2java\test\UserMetaData.java done.
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.248 s
[INFO] Finished at: 2019-12-16T13:51:20+08:00
[INFO] Final Memory: 13M/308M
[INFO] ------------------------------------------------------------------------
com.gitee.l0km:sql2java-maven-plugin插件已经发布到maven中央仓库,无需编译本项目就可直接运行,上面的例子中没有指定插件的版本,则默认使用最新版本的插件
参数说明:
name | description |
---|---|
sql2java.classpath | 指定连接数据库的JDBC driver jar包 |
sql2java.propfile | 指定sql2java生成代码必须的配置文件 |
参见sql2java演示项目: sql2java-example: sql2java调用示例 (gitee.com)
用户可以在此演示项目的基础上修改完成自己的ORM代码项目结构
参见开源项目 facelog: https://gitee.com/l0km/facelog/tree/master/db2
为了控制java代码的生成方式,sql2java有几十个控制参数,默认情况下大部分可以不用修改,如果需要需要修改,就需要获取这些参数名字及说明,如下执行 maven 插件,显示所有配置说明以及插件本身的参数说明:
mvn com.gitee.l0km:sql2java-maven-plugin:help
如下执行 maven 插件,则在当前文件夹下生成一份名为my.properties的默认参数配置文件,你可以在此文件的基础上修改自己的代码生成配置:
$ mvn com.gitee.l0km:sql2java-maven-plugin:help -Dsql2java.output=my.properties
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building sql2java test 1.0.2
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- sql2java-maven-plugin:1.0.2:help (default-cli) @ sql2java-test ---
[INFO] OUTPUT PROPRETIES TO J:\sql2java.test\my.properties
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.495 s
[INFO] Finished at: 2019-11-20T15:25:27+08:00
[INFO] Final Memory: 10M/308M
[INFO] ------------------------------------------------------------------------
SQL2JAVA的参数配置及说明如下
参数以
参数名
=参数值
形式定义,所有#
开始的行皆为注释行
#______________________________________________
#
# (1/8) 数据库访问配置(必填)
#______________________________________________
# JDBC驱动类名
#jdbc.driver=org.hsqldb.jdbcDriver
# 数据库访问的URL
#jdbc.url=jdbc:hsqldb:hsql://localhost
# 访问数据库的用户名
#jdbc.username=sa
# 访问数据库的密码
#jdbc.password=
# 访问的数据库名
#jdbc.schema=null
#______________________________________________
#
# (2/8) 配置自增长键的检索方式(可选)
#______________________________________________
# 此部分配置用于在插入记录时获取自增长键的值
# 对于JDBC 3.0以上支持PreparedStatement.getGeneratedKeys方法
# (DatabaseMetaData.supportsGetGeneratedKeys()返回true)的JDBC 驱动不需要配置此部分
#
# generatedkey.retrieve 可选值:
#
# auto - [默认值]getGeneratedKeys方法自动获取,当使用JDBC 3.0 driver时适用.
#
# before - 在插入(insert)记录之前获取自增长键值
#
# after - 在插入(insert)记录之后获取自增长键值
#
# generatedkey.statement用于定义获取自增长键值的SQL语句
# If you set it to before or after you also need to configure the
# autogeneratedkey.statement properties.
# <TABLE> 占位符用于取代当前表名
# <KEY> 占位符用于取代当前自增长键字段名
#
#generatedkey.retrieve=auto
#generatedkey.statement=
#______________________________________________
#
# (3/8) 生成代码配置(可选)
#______________________________________________
# 生成java代码的包名
codewriter.package=gu.sql2java.demo
# 生成java代码的文件夹
codewriter.destdir=src/main
# 生成扩展java代码的文件夹
#codewriter.destdir.extension=
# 生成扩展java代码的包名
#codewriter.package.extension=
# 定义被bean.converter.utils.java.vm 模板忽略的字段名
#general.beanconverter.tonative.ignore=create_time,update_time
# 生成的java bean是否支持facebook/swift 注释(annotation)
#swift.annotation.bean = true
# 生成的java bean是否支持swagger 注释(annotation)
#swagger.annotation.bean = true
# 对于有primitive 类型(Integer,Long,Double...)的字段是否生成primitive类型的setter方法
codewriter.bean.primitiveSetter = true
# generate Long setter for Date type
# 对于 java.util.Date 类型的字段是否生成 Long类型的setter方法
codewriter.bean.dateLongSetter = true
# Date 类型的JSON 序列化类型 :
# Long 系统时间(毫秒)
# String ISO8601 时间日期格式的字符串
# 当指定了 swift或jackon注解时有效
codewriter.bean.dateSerializeType = Long
# 当 dateSerializeType 为 String 的日期格式,默认为IS8601 格式
codewriter.bean.dateStringFormat=yyyy-MM-dd'T'HH:mm:ss.SSSZ
# modified,initialized 字段的类型(不要修改)
bitstate.type = int
# 字节数对应的java类型:
# byte[]
# java.nio.ByteBuffer
# default byte[] if not specialized
#binary.type = byte[]
# add @JsonRawValue @JsonDeserialize annotation for JSON field
#json.jackson.rawvalue = false
#set properties file name for database
database.properties.env=config_folder
database.properties.isdebug=false
database.properties.dir=resources/conf
database.properties=database.properties
#flag for compatible with axis2
#bean.compatible_axis2=true
# Property file to use when initializing Velocity
#codewriter.velocityprops=somefile
# 默认加载模板的路径(不要修改)
velocity.templates.loadingpath=/templates/velocity/includes
# 为每张表(pertable)和每个方案(perschema)加载子模板的加载起始路径(不要修改)
velocity.templates=/templates/velocity/
############ 扩展模板 ###############
# 用户可以通过下面的扩展模板参数,指定自己定义的模板(.vm)文件的位置
# sql2java generator会根据指定的参数执行扩展模板生成代码
# 扩展模板的加载路径
#velocity.templates.loadingpath.extension=
# 为每张表(pertable)和每个方案(perschema)加载扩展模板的加载起始路径
#velocity.templates.extension =
# sets a prefix to prepend to all generated classes
# useful if you are worried about namespace collision with reserved words
# or java.lang classes
codewriter.classprefix=
# 是否为字段生成默认值
codewriter.generate.defaultvalue=true
#______________________________________________
#
# (4/8) 表和模板过滤配置(可选)
#______________________________________________
#
# 通过表类型过滤
# 用于指定需要生成代码的表类型(用逗号分隔的表类型列表)
# 表类型定义为:TABLE, VIEW, SYSTEM TABLE, SYNONYM
jdbc.tabletypes=TABLE, VIEW
# 通过表名过滤
# 使用通配%来过滤需要生成代码的表名
# 你可以指定一个逗号分割的通配符过滤列表
# 比如 %_name,ul_% 只对后缀为_name,或前缀为ul_的表名生成代码
# 默认对schema中所有的表生成代码
jdbc.tablenamepattern=%
# 表名白名单/名单过滤(此特性暂未启用)
# 白名单
# 空格分隔的表名列表,只在此名单中的表才会被生成代码
# 黑名单
# 空格分隔的表名列表,在此名单中的表不会被生成代码
# 白名单和黑名单只能定义一个,如果同时指定了白名单和黑名单则忽略黑名单
# 白名单过滤
tables.include=
# 黑名单过滤
tables.exclude=
# 模板文件夹名白名单/名单过滤
# 白名单
# 空格分隔的表名列表,只在此名单中的模板文件夹中的模板才会被生成代码
# 黑名单
# 空格分隔的表名列表,在此名单中的模板文件夹中的模板不会被生成代码
# 白名单和黑名单只能定义一个,如果同时指定了白名单和黑名单则忽略黑名单
template.folder.exclude=
template.folder.include=java5g
# java5g : general bean & manager templates for java5
# (6/8) WHAT SHOULD BE DISPLAYED/NOT DISPLAYED ON THE FRONTEND ?
# empty means all fields
#______________________________________________
# 逗号分割的字段名列表定义只能本地可见的字段
# A comma separated list of field names in a specified table that can only be accessed locally
# Equivalent to defining in the annotation of a field: ' SCOPE@LOCAL@EPOSC '
# Example:
# table.user_info.scope.local=private_time,password
# 逗号分割的字段名列表定义THRIFT可见的字段
# A comma separated list of field names in a specified table that can be transmitted by RPC
# in addition to being accessible locally
# Equivalent to defining in the annotation of a field: ' SCOPE@THRIFT@EPOSC '
# Example:
# table.user_info.scope.thrift=password
# 逗号分割的字段名列表定义JSON可见的字段
# A comma separated list of field names in a specified table that can be serialized by JSON
# in addition to being accessible locally
# Equivalent to defining in the annotation of a field: ' SCOPE@JSON@EPOSC '
# Example:
# table.user_info.scope.json=private_time,password
#______________________________________________ # # (7/8) JDBC 类型映射(可选) #______________________________________________ # # jdbc DATE类型映射的java类型,可选值: # java.sql.Date # java.util.Date jdbc2java.date=java.util.Date # jdbc TIME类型映射的java类型,可选值: # java.sql.Time # java.util.Date jdbc2java.time=java.util.Date
# jdbc TIMESTAMP类型映射的java类型,可选值:
# java.sql.Timestamp
# java.util.Date
jdbc2java.timestamp=java.util.Date
#______________________________________________
#
# (8/8) 乐观锁配置(可选)
#______________________________________________
# optimisticlock.type 有两个可选项值:
# none - 乐观锁机制未启用(default).
# timestamp - 乐观锁字段包含 System.currentTimeMillis() 值.
#
# optimisticlock.column 定义乐观锁的字段名,如果字段名不存在则乐观锁机制不会启用
# 乐观锁的字段类型可以是java.lang.Long or java.lang.String.
optimisticlock.type=timestamp
optimisticlock.column=version_time
从 3.21.0 开始,sql2java增加了ColumnCodec接口用于应用层自定义对数据字段的序列化和反序列化,序列化方法(ColumnCodec.serialize
)用于将自定义类型数据转换为数据库字段存储类型,反序列化方法(ColumnCodec.deserialize
)则将字段存储类型转换为自定义数据类型。对于JSON类型的支持使用JsonColumnCodec实现,应用层可以参照JsonColumnCodec
基于 BaseColumnCodec 实现自定义的数据库字段编解码器。
从 3.21.0 开始,增加数据库字段注释标记 ANN@@NNA
和TYPE@@EPYT
,应用层定义数据库字段的类型和编解码器,sql2java在生成代码时会自动根据此标记在生成指定类型的Java成员以及@ColumnCodecConfig
注解。
定义字段类型,如ATYPE@net.facelib.eam.interpreter.Rectangle@EPYT
,将字段类型定义为net.facelib.eam.interpreter.Rectangle
定义字段的注解,可定义多个,如ANN@gu.sql2java.annotations.ColumnCodecConfig(net.facelib.eam.interpreter.sql2java.EamPlayColumnCodec.class)@NNA
,将在Java成员上生成注解@gu.sql2java.annotations.ColumnCodecConfig(net.facelib.eam.interpreter.sql2java.EamPlayColumnCodec.class)
下面的表中rect
字段定义了TYPE@@EPYT
和ANN@@NNA
CREATE TABLE IF NOT EXISTS dc_device_channel (
`device_id` int NOT NULL COMMENT 'X@NAME:设备ID@X',
`sid` int NOT NULL DEFAULT 0 COMMENT 'X@NAME:物理屏幕ID@x',
`area` varchar(32) NOT NULL COMMENT 'X@NAME:显示区域ID@x',
`rect` varchar(256) DEFAULT NULL COMMENT 'ANN@gu.sql2java.annotations.ColumnCodecConfig(net.facelib.eam.interpreter.sql2java.EamPlayColumnCodec.class)@NNATYPE@net.facelib.eam.interpreter.Rectangle@EPYTX@NAME:显示区域坐标@x,对应EamPlayer的defineChannel语法',
`channel` varchar(32) NOT NULL COMMENT 'X@NAME:频道ID@x,显示区域对应的频道',
`run_tasks` text DEFAULT NULL COMMENT 'X@NAME:播放任务@X描述,设备实际播放的任务描述,由设备端写入,对应EamPlayer的definePlanTask和defineTrigger语法',
PRIMARY KEY(`device_id`,`sid`,`area`),
FOREIGN KEY (device_id) REFERENCES dc_device(id) ON DELETE CASCADE,
INDEX (channel)
)COMMENT 'X@NAME:设备显示区域频道记录@X' DEFAULT CHARSET=utf8;
生成的java类中对应rect
的示例
/** comments:X@NAME:显示区域坐标@x,对应EamPlayer的defineChannel语法 */
@ApiModelProperty(value = "X@NAME:显示区域坐标@x,对应EamPlayer的defineChannel语法" ,dataType="Rectangle")
@CodegenLength(max=256)@CodegenInvalidValue
@ExcelColumn(sort=4)
@gu.sql2java.annotations.ColumnCodecConfig(net.facelib.eam.interpreter.sql2java.EamPlayColumnCodec.class)
private net.facelib.eam.interpreter.Rectangle rect;
getter/setter方法的对应类型为net.facelib.eam.interpreter.Rectangle
getter方法
@ThriftField(value=7)
@JsonProperty("rect")
public net.facelib.eam.interpreter.Rectangle getRect(){
return rect;
}
setter方法
@ThriftField(name="rect")
@JsonProperty("rect")
public void setRect(net.facelib.eam.interpreter.Rectangle newVal)
{
modified |= DC_DEVICE_CHANNEL_ID_RECT_MASK;
initialized |= DC_DEVICE_CHANNEL_ID_RECT_MASK;
if (Objects.equals(newVal, rect)) {
return;
}
rect = newVal;
}
read/write方法对应的类型为rect字段的数据存储类型
read方法
public String readRect(){
return metaData.columnCodecs[DC_DEVICE_CHANNEL_ID_RECT].serialize(rect,String.class);
}
write方法
public void writeRect(String newVal){
modified |= DC_DEVICE_CHANNEL_ID_RECT_MASK;
initialized |= DC_DEVICE_CHANNEL_ID_RECT_MASK;
rect = metaData.columnCodecs[DC_DEVICE_CHANNEL_ID_RECT].deserialize(newVal,metaData.fieldOf(DC_DEVICE_CHANNEL_ID_RECT).getGenericType());
}
字段注释标记 SCOPE@@EPOSC
用于定义字段可见度,具体格式为
SCOPE@(LOCAL|JSON|THRIFT)@EPOSC
可定义三种可见度
如下示例,下面的表定义中,private_time
字段定义了SCOPE@@EPOSC
注释标记,指定了该字段仅本地可见。也就是说只有服务端本身可以读写该字段。
CREATE TABLE IF NOT EXISTS dc_device (
`id` int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT 'X@NAME:设备id@X',
`name` varchar(32) DEFAULT NULL COMMENT 'X@NAME:设备名称@X,用户指定',
`physical_address` varchar(32) NOT NULL UNIQUE COMMENT '设备X@NAME:物理地址@X,MAC地址,IMEI或其他设备识别码',
`private_time` bigint DEFAULT 0 COMMENT 'SCOPE@LOCAL@EPOSC设备令牌创建的时间戳(毫秒),每次创建设备令牌都会修改此字段',
`os_arch` varchar(64) DEFAULT NULL COMMENT 'X@NAME:操作系统平台@X,操作系统名称及版本及硬件架构名称,例如:Windows-x86_64,Linux-x86_64,Android-arm...'
) COMMENT 'X@NAME:前端设备记录@X,前端设备基本信息' DEFAULT CHARSET=utf8;
sql2java-generator生成的DeviceBean
对象中dc_device.private_time
字段的对应成员privateTime
定义代码如下:
/** comments:设备令牌创建的时间戳(毫秒),每次创建设备令牌都会修改此字段 */
@ApiModelProperty(value = "设备令牌创建的时间戳(毫秒),每次创建设备令牌都会修改此字段" ,dataType="Long")
@CodegenDefaultvalue("0")@CodegenInvalidValue("-1")
@ExcelColumn(sort=9)
@com.alibaba.fastjson.annotation.JSONField(serialize = false,deserialize = false)
@com.fasterxml.jackson.annotation.JsonIgnore
private Long privateTime;
/**
* Getter method for {@link #privateTime}.<br>
* Meta Data Information (in progress):
* <ul>
* <li>full name: dc_device.private_time</li>
* <li>comments: 设备令牌创建的时间戳(毫秒),每次创建设备令牌都会修改此字段</li>
* <li>default value: '0'</li>
* <li>column size: 19</li>
* <li>JDBC type returned by the driver: Types.BIGINT</li>
* </ul>
*
* @return the value of privateTime
*/
@JsonIgnore
public Long getPrivateTime(){
return privateTime;
}
可以看到,privateTime
成员定义的Jackson注解@JsonIgnore
和fastjson注解@JSONField
指定该字段在JSON序列化和反序列化时忽略应该字段。同时privateTime
的getter方法上也没有thrift字段注解@ThriftField
,代表应该字段也没有被定义为Thrift成员字段。
swift2thrift-maven-plugin插件生成的IDL中就不会有privateTime
字段:
struct DeviceBean {
1: required bool _new;
2: required i32 modified;
3: required i32 initialized;
4: optional i32 id;
5: optional string name;
6: optional string physicalAddress;
7: optional string osArch;
}
3.19.0之前不论是TINYINT,SMALLINT,INT
类型对应的Java类型都是Integer
,3.19.0版本之后,细分了整数类型字段生成的Java数据类型,如下表
SQL 类型 | Java字段类型 | 说明 |
---|---|---|
TINYINT/BOOL/BOOLEAN | Byte /Boolean |
如果数据库字段注释(COMMENT)中定义了[NUM,Boolean] ,则生成的Java成员类型为Boolean ,否则为Byte |
SMALLINT | Short |
|
INT | Integer |
示例:
CREATE TABLE IF NOT EXISTS dc_device (
`id` int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT '设备id',
`online` boolean DEFAULT false COMMENT '[NUM,Boolean],是否在线标记'
);
如上定义boolean/bool
或TINYINT
类型字段在生成的Java Bean中online
字段将被定义为Boolean
类型。
**注意:**在注释中
[NUM,Boolean]
标记必须在字符串起始位置。
从3.8版本之后,sql2java支持对保存JSON数据的String字段自动序列化和反序列。
要开启此特性,需要做如下两步简单的设置
开启此特性生成的代码需要fastjson,jackson库的支持
修改 sql2java.properties
将json.jackson.rawvalue
置为true
,即增加如下设置
#
# add @JsonRawValue @JsonDeserialize annotation for JSON field
#json.jackson.rawvalue = true
修改建表语句
在需要定义为保存JSON数据的字段的注释中增加[JSON_STR,...]前缀,通过此前缀指定该字段要保存JSON数据(只对Java类型为String的字段有效)
示例如下:
CREATE TABLE IF NOT EXISTS dc_device_group (
`id` int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT '设备组id',
`name` varchar(32) NOT NULL COMMENT '设备组名',
`address` varchar(128) DEFAULT NULL COMMENT '设备组详细地址:区/街道门牌',
`props` text DEFAULT NULL COMMENT '[JSON_STR,obj]JSON格式的扩展字段(最大64KB),用于定义扩展信息,online_time:开机时间,offline_time:关机时间,close_time:闭站时间,operator:操作人',
`create_time` timestamp DEFAULT CURRENT_TIMESTAMP,
`update_time` timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) COMMENT '设备组信息' DEFAULT CHARSET=utf8;
上面的示例中props
字段的注释以[JSON_STR,obj]
为前缀,即定义该字段为JSON字段,JSON字段的类型为Object
只要做了上面两项目修改,重新执行Sql2java生成代码就可以了。
生成代码时会根据[JSON_STR,...]
来确定JSON字段的类型
[JSON_STR]格式 | JSON字段类型 |
---|---|
[JSON_STR,array] | com.alibaba.fastjson.JSONArray |
[JSON_STR,object] | com.alibaba.fastjson.JSONObject |
[JSON_STR,obj] | com.alibaba.fastjson.JSONObject |
[JSON_STR] | com.alibaba.fastjson.JSON |
[JSON_STR,com.mycompany.product.User] | com.mycompany.product.User |
props 字段定义代码:
/** comments:[JSON_STR]JSON格式的扩展字段(最大64KB),用于定义扩展信息,online_time:开机时间,offline_time:关机时间,close_time:闭站时间,operator:操作人 */
@ApiModelProperty(value = "[JSON_STR]JSON格式的扩展字段(最大64KB),用于定义扩展信息,online_time:开机时间,offline_time:关机时间,close_time:闭站时间,operator:操作人" ,dataType="String")
@CodegenLength(max=65535)@CodegenInvalidValue
@com.fasterxml.jackson.annotation.JsonRawValue
@com.fasterxml.jackson.databind.annotation.JsonDeserialize(using = gu.sql2java.json.RawJsonDeserializer.class)
private com.alibaba.fastjson.JSONObject props;
getter/setter方法代码,以String类型对字段进行读写:
@ThriftField(value=16)
@JsonProperty("props")
public String getProps(){
return null == props ? null : props.toJSONString();
}
@ThriftField(name="props")
@JsonProperty("props")
public void setProps(String newVal)
{
modified |= DC_DEVICE_GROUP_ID_PROPS_MASK;
initialized |= DC_DEVICE_GROUP_ID_PROPS_MASK;
props = com.alibaba.fastjson.JSONObject.parseObject(newVal,com.alibaba.fastjson.JSONObject.class);
}
额外生成的read/write方法代码,提供对JSON对象直接读写:
/**
* read method for {@link #props}<br>
* @return the JSON value of props
*/
public com.alibaba.fastjson.JSONObject readProps(){
return props;
}
/**
* write method for {@link #props} with JSON object.<br>
*/
public void writeProps(com.alibaba.fastjson.JSONObject newVal){
modified |= DC_DEVICE_GROUP_ID_PROPS_MASK;
initialized |= DC_DEVICE_GROUP_ID_PROPS_MASK;
if (Objects.equals(newVal, props)) {
return;
}
props = newVal;
}
{
"modified": 0,
"initialized": 65535,
"new": false,
"id": 5,
"name": "连平客运总站",
"address": null,
"props": {
"offline_time": "22:00",
"online_time": "8:00",
"operator": "unknow"
},
"createTime": "2022-07-06T12:41:56.000+0800",
"updateTime": "2022-07-06T12:41:56.000+0800"
}
自从3.10开始,sql2java提供基于apache/poi实现的数据记录导出为Excel格式数据流或文件的功能.参见sql2java-excel/README.md.
sql2java-excel支持注解方式配置每张表每个字段的Excel导出配置。sql2java-generator在生成Java Bean代码时支持从SQL 表和字段注释COMMENT中根据读取预定义的标记,在Java Bean类代码中生成@ExcelSheet,@ExcelColumn注解。
要开启Excel注解生成特性,需要做如下两步设置
开启此特性生成的代码需要sql2java-excel库的支持
修改 sql2java.properties
将excel.annotation.bean
置为true
,即增加如下设置
# generate @ExcelSheet,@ExcelColumn annotation if true
excel.annotation.bean = true
在数据库建表语句的表和字段注释(COMMENT)上根据需要定义特殊的EXCEL 标记,示例如下:
下面的CREATE TABLE SQL语句示例中用到了很多X@....@X
标记,这些标记内容就是为sql2java-generator在生成JavaBean代码时用于识别生成@ExcelSheet,@ExcelColumn
注解的特殊标记(tag):
CREATE TABLE IF NOT EXISTS dc_device (
`id` int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT 'X@NAME:设备id@X',
`group_id` int(11) DEFAULT 1 COMMENT 'X@NAME:所属设备组id@X',
`features` int(11) DEFAULT 0 COMMENT 'X@NAME:设备组特性标志@X,应用层定义',
`name` varchar(32) DEFAULT NULL COMMENT 'X@NAME:设备名称@X,用户指定',
`physical_address` varchar(32) NOT NULL UNIQUE COMMENT '设备X@NAME:物理地址@X,MAC地址,IMEI或其他设备识别码',
`address_type`varchar(16) NOT NULL DEFAULT 'MAC' COMMENT '设备物理X@NAME:地址类型@X(MAC,IMEI...),默认6字节MAC地址(HEX)',
`iot_card` varchar(32) DEFAULT NULL UNIQUE COMMENT '设备X@NAME:物联网卡编号@X,例如联通叫iccid',
`status` varchar(32) NOT NULL DEFAULT 'ENABLE' COMMENT 'X@NAME:设备状态@X,X@VALUES:ENABLE:正常,DISABLE:禁用,MAINTAIN:维护,PENDING:挂起(待审核)@X',
`private_time` bigint DEFAULT 0 COMMENT '设备令牌创建的时间戳(毫秒),每次创建设备令牌都会修改此字段',
`screen_info` varchar(32) DEFAULT NULL COMMENT 'X@NAME:设备屏幕信息@X,格式示例:15H1080x960--15(英)寸横屏分辨率1080x960,21V960x1080--21(英)寸横屏分辨率960x1080',
`fixed_mode` varchar(8) DEFAULT 'FLOOR' COMMENT '设备X@NAME:安装方式@X,X@VALUES:HANG:悬挂,FLOOR:落地@X',
`os_arch` varchar(64) DEFAULT NULL COMMENT 'X@NAME:操作系统平台@X,操作系统名称及版本及硬件架构名称,例如:Windows-x86_64,Linux-x86_64,Android-arm...',
`network` varchar(32) DEFAULT NULL COMMENT 'X@NAME:网络连接类型@X:4G,WIFI,ETHERNET',
`version_info`varchar(32) DEFAULT NULL COMMENT '设备端应用程序的X@NAME:版本@X号,格式由应用层定义',
`model` varchar(32) DEFAULT NULL COMMENT 'X@NAME:设备型号@X',
`vendor` varchar(32) DEFAULT NULL COMMENT 'X@NAME:设备供应商@X',
`device_detail` varchar(512) DEFAULT NULL COMMENT '[JSON_STR,obj]X@NAME:设备产品详细信息@X,以JSON格式定义设备详细信息,JSON字段:X@NAMES:device_name:产品名称,manufacturer:制造商,made_date:生产日期@X,应用层可根据需要扩展',
`props` text DEFAULT NULL COMMENT '[JSON_STR,obj]JSON格式的扩展字段(最大64KB),用于定义扩展信息,X@NAMES:last_active_time:上次在线时间,disk_capacity:磁盘容量,status_comment:状态变更说明@X',
`plan_id` varchar(64) DEFAULT NULL COMMENT 'X@NAME:当前节目ID@X',
`target_id` varchar(64) DEFAULT NULL COMMENT 'X@NAME:目标节目ID@X',
`remark` varchar(256) DEFAULT NULL COMMENT 'X@NAME:备注@X',
`create_time` timestamp DEFAULT CURRENT_TIMESTAMP COMMENT 'X@NAME:记录创建时间@X',
`update_time` timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'X@NAME:记录修改时间@X'
) COMMENT 'X@NAME:前端设备记录@X,前端设备基本信息,X@SHEET:titleFillColor=YELLOW,hideColumns=private_time|props|device_detail@X' DEFAULT CHARSET=utf8;
有了这些标记,sql2java-generator就会为dc_device表生成如下的带有@ExcelSheet,@ExcelColumn
注解的Java Bean代码:
/**
* DeviceBean is a mapping of dc_device Table.
* <br>Meta Data Information (in progress):
* <ul>
* <li>comments: 前端设备记录,前端设备基本信息, </li>
* </ul>
* @author guyadong
*/
@ExcelSheet(sheetName="dc_device",title="前端设备记录",titleFillColor="YELLOW",hideColumns={"private_time","props","device_detail"})
public final class DeviceBean extends BaseRow
implements Serializable,Constant
{
private static final long serialVersionUID = -3495281739409382636L;
/** comments:设备id */
@ExcelColumn(sort=1,name="设备id")
private Integer id;
/** comments:所属设备组id */
@ExcelColumn(sort=2,name="所属设备组id")
private Integer groupId;
/** comments:设备组特性标志,应用层定义 */
@ExcelColumn(sort=3,name="设备组特性标志")
private Integer features;
/** comments:设备名称,用户指定 */
@ExcelColumn(sort=4,name="设备名称")
private String name;
/** comments:设备物理地址,MAC地址,IMEI或其他设备识别码 */
@ExcelColumn(sort=5,name="物理地址")
private String physicalAddress;
/** comments:设备物理地址类型(MAC,IMEI...),默认6字节MAC地址(HEX) */
@ExcelColumn(sort=6,name="地址类型")
private String addressType;
/** comments:设备物联网卡编号,例如联通叫iccid */
@ExcelColumn(sort=7,name="物联网卡编号")
private String iotCard;
/** comments:设备状态,ENABLE:正常,DISABLE:禁用,MAINTAIN:维护,PENDING:挂起(待审核) */
@ExcelColumn(sort=8,name="设备状态",readConverterExp="ENABLE=正常, DISABLE=禁用, MAINTAIN=维护, PENDING=挂起(待审核)")
private String status;
/** comments:设备令牌创建的时间戳(毫秒),每次创建设备令牌都会修改此字段 */
@ExcelColumn(sort=9)
private Long privateTime;
/** comments:设备屏幕信息,格式示例:15H1080x960--15(英)寸横屏分辨率1080x960,21V960x1080--21(英)寸横屏分辨率960x1080 */
@ExcelColumn(sort=10,name="设备屏幕信息")
private String screenInfo;
/** comments:设备安装方式,HANG:悬挂,FLOOR:落地 */
@ExcelColumn(sort=11,name="安装方式",readConverterExp="HANG=悬挂, FLOOR=落地")
private String fixedMode;
/** comments:操作系统平台,操作系统名称及版本及硬件架构名称,例如:Windows-x86_64,Linux-x86_64,Android-arm... */
@ExcelColumn(sort=12,name="操作系统平台")
private String osArch;
/** comments:网络连接类型:4G,WIFI,ETHERNET */
@ExcelColumn(sort=13,name="网络连接类型")
private String network;
/** comments:设备端应用程序的版本号,格式由应用层定义 */
@ExcelColumn(sort=14,name="版本")
private String versionInfo;
/** comments:设备型号 */
@ExcelColumn(sort=15,name="设备型号")
private String model;
/** comments:设备供应商 */
@ExcelColumn(sort=16,name="设备供应商")
private String vendor;
/** comments:设备产品详细信息,以JSON格式定义设备详细信息,JSON字段:device_name:产品名称,manufacturer:制造商,made_date:生产日期,应用层可根据需要扩展 */
@ExcelColumns({
@ExcelColumn(sort=17,name="设备产品详细信息"),
@ExcelColumn(sort=17,columnName="device_detail.device_name",name="产品名称"),
@ExcelColumn(sort=17,columnName="device_detail.manufacturer",name="制造商"),
@ExcelColumn(sort=17,columnName="device_detail.made_date",name="生产日期")
})
@com.fasterxml.jackson.annotation.JsonRawValue
@com.fasterxml.jackson.databind.annotation.JsonDeserialize(using = gu.sql2java.json.RawJsonDeserializer.class)
private com.alibaba.fastjson.JSONObject deviceDetail;
/** comments:JSON格式的扩展字段(最大64KB),用于定义扩展信息,last_active_time:上次在线时间,disk_capacity:磁盘容量,status_comment:状态变更说明 */
@ExcelColumns({
@ExcelColumn(sort=18),
@ExcelColumn(sort=18,columnName="props.last_active_time",name="上次在线时间"),
@ExcelColumn(sort=18,columnName="props.disk_capacity",name="磁盘容量"),
@ExcelColumn(sort=18,columnName="props.status_comment",name="状态变更说明")
})
@com.fasterxml.jackson.annotation.JsonRawValue
@com.fasterxml.jackson.databind.annotation.JsonDeserialize(using = gu.sql2java.json.RawJsonDeserializer.class)
private com.alibaba.fastjson.JSONObject props;
/** comments:当前节目ID */
@ExcelColumn(sort=19,name="当前节目ID")
private String planId;
/** comments:目标节目ID */
@ExcelColumn(sort=20,name="目标节目ID")
private String targetId;
/** comments:备注 */
@ExcelColumn(sort=21,name="备注")
private String remark;
/** comments:记录创建时间 */
@ExcelColumn(sort=22,name="记录创建时间")
private java.util.Date createTime;
/** comments:记录修改时间 */
@ExcelColumn(sort=23,name="记录修改时间")
private java.util.Date updateTime;
//////////////////////////////
///// 。。其他代码。。 ////
//////////////////////////////
}
本节说明说明EXCEL 标记X@...@X
的定义方式
X@NAME:xxxx@X
为表/字段名字定义标记,定义表或字段在输出EXCEL数据的标题或列名,当出现在表的注释语句(COMMENT)中时它对应生成@ExcelSheet
的title
,出现在字段的注释语句(COMMENT)中时它对应生成@ExcelColumn
的name
.
X@NAMES:a=b,c=d@X
为多符号定义标记,定义表或字段在在输出EXCEL数据时,子成员变量的列名.当出现在表的注释语句(COMMENT)中时它对应生成表成员或子成员字段的@ExceColumn
注解代码以定义表成员或子成员字段的列名.出现在字段的注释语句(COMMENT)中且该字段被标记为JSON object字段时它对应生成JSON子成员字段的@ExcelColumn
注解代码以定义JSON子成员字段的列名.
在上面的示例中,device_detail
字段被定义为JSON object字段,且COMMENT中定义了NAMES tag:X@NAMES:device_name:产品名称,manufacturer:制造商,made_date:生产日期@X
,相当就定义了该JSON成员中的device_name,device_name,manufacturer,made_date
子成员字段在输出到EXCEL时对应的列名.
如果实际该JSON 字段保存的字段不至这三个,还有
location
字段没有定义列名,输出该字段的列名是什么呢?没定义的情况默认就是locaiton
X@VALUES:a=b,c=d@X
为多值转换定义标记,用于定义在字段的值在输出到EXCEL时实际内容.对应于@ExcelColumn
的readConverterExp
.
如上示例中dc_device.status
字段定义了VALUES tag:X@VALUES:ENABLE:正常,CLOSED:关闭,MAINTAIN:维护,PENDING:挂起(待审核)@X
,即代表当月status
字段值为ENABLE
时,输出到Excel的值为正常
,以此类推.
X@COLUMN:a=b,c=d@X
为@ExcelColumn
注解全字段定义标记,@ExcelColumn
注解定义有数十个可配置的参数字段,name,readConverterExp
只是常用的字段,所以定义了专用的NAME tag,VALUES tag,对于其他参数,都可以通COLUMN tag来进行定义.
X@SHEET:a=b,c=d@X
为@ExcelSheet
注解全字段定义标记,@ExcelSheet
注解定义有数十个可配置的参数字段,name
只是常用的字段,所以定义了专用的NAME tag,对于其他参数,都可以通SHEET tag来进行定义.
上面的示例中dc_device表的注释(COMMENT)中使用了SHEET tag定义了:@ExcelSheet
的titleFillColor,hideColumns
:X@SHEET:titleFillColor=YELLOW,hideColumns=private_time|props|device_detail@X
注意在这里,
@ExcelSheet
的hideColumns
的类型是String数组,在SHEET tag中对于数组类型的字段定义多个元素时要用|
分割.
即专用标记优先于COLUMN tag,SHEET tag定义
对于一个字段如果使用COLUMN tag,定义了name
,同时也用NAME tag定义了列名,这种情况下优先使用NAME tag定义的值,对于SHEET tag也是一样的逻辑。
CREATE TABLE dc_spot (
`id` int(11) PRIMARY KEY AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL COMMENT '地点名称',
`spot` point DEFAULT NULL COMMENT '经纬度点'
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
从3.18.0版本开始,支持MySQL(above 5.7)的所有空间数据类型(Spatial Data Types)即几何类型(Geomerty)字段自动生成JTS 的 com.vividsolutions.jts.geom.Geometry
类型的成员.
如下为MySQL空间数据类型名与JTS 几何对象的对应表
MySQL空间数据类型名 | JTS类 |
---|---|
GEOMETRY | com.vividsolutions.jts.geom.Geometry |
POINT | com.vividsolutions.jts.geom.Point |
LINESTRING | com.vividsolutions.jts.geom.LineString |
POLYGON | com.vividsolutions.jts.geom.Polygon |
MULTIPOINT | com.vividsolutions.jts.geom.GeometryCollection |
MULTILINESTRING | com.vividsolutions.jts.geom.GeometryCollection |
MULTIPOLYGON | com.vividsolutions.jts.geom.GeometryCollection |
GEOMETRYCOLLECTION | com.vividsolutions.jts.geom.GeometryCollection |
为控制生成的代码中对于Geomerty类型字段的getter/setter方法的类型,增加了codewrite.bean.geometry.serial.type
参数
以下codewrite.bean.geometry.serial.type
参数的说明
【默认值】当codewrite.bean.geometry.serial.type=STRING
时,Geomerty类型字段的getter/setter方法的类型为String,即对外使用WKT字符串来表示几何对象
因为String是简单类型,这种方式可读性好,比较通用,符合常规场景下对Geometry类型的处理
生成代码示例:
private com.vividsolutions.jts.geom.Point spot;
/** 将spot转为WKT字符串返回 */
public String getSpot(){
return null == spot ? null : spot.toText();
}
/** 将WKT字符串转为Point保存到spot */
public void setSpot(String newVal){
spot = (null == newVal || newVal.isEmpty())? null : GeometryDataCodec.DEFAULT_INSTANCE.fromWKTUnchecked(newVal,Point.class);
}
/** 返回sport原始对象 */
public com.vividsolutions.jts.geom.Point readSpot(){
return spot;
}
/** 修改spot原始对象 */
public void writeSpot(com.vividsolutions.jts.geom.Point newVal){
spot = newVal;
}
当codewrite.bean.geometry.serial.type=JTS
时,JTS Geomertry 类型直接用于Geomerty类型字段的getter/setter方法的类型。
生成代码示例:
@com.fasterxml.jackson.databind.annotation.JsonDeserialize(using = gu.sql2java.geometry.jackson.GeometryDeserializer.class)
@com.fasterxml.jackson.databind.annotation.JsonSerialize(using = gu.sql2java.geometry.jackson.GeometrySerializer.class)
@com.alibaba.fastjson.annotation.JSONField(serializeUsing=gu.sql2java.geometry.fastjson.PointCodec.class,deserializeUsing=gu.sql2java.geometry.fastjson.PointCodec.class)
private com.vividsolutions.jts.geom.Point spot;
/** 返回sport原始对象 */
public com.vividsolutions.jts.geom.Point getSpot(){
return spot;
}
/** 修改spot原始对象 */
public void setSpot(com.vividsolutions.jts.geom.Point newVal){
spot = newVal;
}
不论codewrite.bean.geometry.serial.type
参数如何选择,Geomerty类型字段生成的Java Bean的对应成员类型都为 JTS Geomerty类型。
JTS Geometry对象不是标准的Java Bean不能自动被Jackson执行序列化和反序列化。所以需要为 Geometry对象实现自定义的序列化器和反序列化器。
JTS Geometry类序列化器实现 gu.sql2java.geometry.jackson.GeometryDeserializer
JTS Geometry类反序列化器实现 gu.sql2java.geometry.jackson.GeometrySerializer
如下可以在以使用@JsonDeserialize
和@JsonSerialize
注解定义类成员字段的自定义序列化和反序列化器:
@com.fasterxml.jackson.databind.annotation.JsonDeserialize(using = gu.sql2java.geometry.jackson.GeometryDeserializer.class)
@com.fasterxml.jackson.databind.annotation.JsonSerialize(using = gu.sql2java.geometry.jackson.GeometrySerializer.class)
private com.vividsolutions.jts.geom.Point spot;
直接引用自定义序列化和反序列化器示例参见:GeometryJacksonTest
JTS Geometry对象不是标准的Java Bean不能自动被fastjson执行序列化和反序列化。所以需要为 Geometry对象实现自定义的序列化器和反序列化器。
fastjson 为JTS Geometry类型自定义的序列化和反序列化实现的基类为gu.sql2java.geometry.fastjson.GeometryCodec
如下为详细的JTS Geometry类与fastjson自定义序列化反序列化类对应表
JTS Geometry类 | fastjson自定义序列化反序列化类 |
---|---|
com.vividsolutions.jts.geom.Geometry | gu.sql2java.geometry.fastjson.GeometryCodec |
com.vividsolutions.jts.geom.Point | gu.sql2java.geometry.fastjson.PointCodec |
com.vividsolutions.jts.geom.LineString | gu.sql2java.geometry.fastjson.LineStringCodec |
com.vividsolutions.jts.geom.Polygon | gu.sql2java.geometry.fastjson.PolygonCodec |
com.vividsolutions.jts.geom.GeometryCollection | gu.sql2java.geometry.fastjson.GeometryCollectionCodec |
如下可以在以使用@JSONField
注解定义类成员字段的自定义序列化和反序列化器:
@com.alibaba.fastjson.annotation.JSONField(
serializeUsing=gu.sql2java.geometry.fastjson.PointCodec.class,
deserializeUsing=gu.sql2java.geometry.fastjson.PointCodec.class)
private com.vividsolutions.jts.geom.Point spot;
直接引用自定义序列化和反序列化器示例参见:gu.sql2java.GeometryFastjsonTest
gu.sql2java.geometry.fastjson.GeometryInit 用于为fastjson指定JTS Geometry类型的全局序列化反序列器,即将上述的所有fastjson自定义序列化反序列化器实例设置为fastjson的全局序列化反序列化器
当需要单独对JTS Geometry进行序列化和反序列化时,可以使用此GeometryInit.init()
完成全局初始化,以确保fastjson能正确处理JTS Geometry对象
示例如下:
@Test
public void test2Fastjson() {
try {
GeometryInit.init();
String wkt = "POINT (1 -1)";
Point point = GeometryDataCodec.DEFAULT_INSTANCE.fromWKT(wkt,Point.class);
log("point {}",JSON.toJSONString(point));
assertTrue(wkt.equals(point.toText()));
} catch (ParseException e) {
e.printStackTrace();
assertTrue(false);
}
}
不论是Thrift RPC还是SpringWeb服务,服务方法的输入和输出参数都要通过网络在Server/Client之间传输。实现数据对象传输,发送端需要对数据对象进行序列化(JSON或二进制数据流),接收端需要对收到的数据反序列化还原为原始的数据对象。
从3.32.0版本开始,sql2java增加了静态字段过滤功能,是指在生成sql2java的数据库表记录对象类时,允许指定字段的可见度(ColumnVisibility)。
可见度是指字段对数据接收端是否可见,只要控制数据库表对象在序列化/反序列化时忽略不可见字段,数据接收端最终收到数据库对象中就不会包含该字段。
具体实现就是sql2java-generator会根据字段的可见度要求,对于不可见字段,在生成对应字段代码时增加Jackson,Fastjson,Thrift注解(Annotation)指定在表对象序列化/反序列化时忽略该字段。示例参见 **《SCOPE@@EPOSC》**章节
sql2java中字段可见度定义对应枚举类型gu.sql2java.ColumnVisibility
枚举变量 | JSON是否可见 | Thrift是否可见 | 说明 |
---|---|---|---|
DEFAULT | true | true | 默认:全可见 |
LOCAL | false | false | 仅本地可见,与远端(Spring WEB,Thrift RPC)交互时不可见 |
THRIFT | false | true | Thrift RPC 传输时可见,Thrft RPC 客户端与服务端交互时可见 |
JSON | true | false | JSON序列化时可见,Spring WEB 客户端与服务端 交互时可见(Spring WEB是基于jackson实现序列化和反序列化的),使用fastjson对数据库对象进行序列化和反序列化时同样有效。 |
定义字段可见度的方式有两种,一种是在建表语句的字段注释中通过字段注释标记SCOPE@@EPOSC
来定义,参见 **《SCOPE@@EPOSC》**章节
另一种是在sql2java参数配置文件(sql2java.properties)中定义,参见 **《参数说明》**章节(6/8)
段
从3.32.6版本开始新增加了@Sql2javaLocalConfig
注解,定义在服务方法或服务类上,用于定义Sql2java的运行时配置,目前只有一个字段resetModifiedIfEqual
,如果将指定的Java Bean类型定义在resetModifiedIfEqual
,则fastjson,jackson反序列化器在对JSON字段成功反序列化为JavaBean对象后,会调用BasesBean.resetModifiedIfEqual
对解析的对象进行归一化处理,确保只有与数据库已经存在记录不相等的字段对应的modified标记才被置1。
在spring环境定义在服务类或服务方法上的@Sql2javaLocalConfig
注解生效需要RuntimeConfigInterceptor
的配合。RuntimeConfigInterceptor
负责在HTTP请求解析之前为请求方法安装sql2java运行时配置对象( gu.sql2java.config.RuntimeConfig
),方法调用结束删除。
RuntimeConfig
中保存了由@Sql2javaLocalConfig
注解生成的配置。
如下在Spring服务启动注解(@SpringBootApplication
)上指定扫描RuntimeConfigInterceptor
拦截器FilterInterceptorConfig
所在包就可以启动服务方法拦截器,激活了服务方法上定义的beanfilter过滤器
import org.springframework.boot.autoconfigure.SpringBootApplication;
import gu.sql2java.config.spring.FilterInterceptorConfig;
/**
* 应用服务启动配置
*/
@SpringBootApplication(scanBasePackageClasses = {RuntimeConfigInterceptor.class})
public class ApplicationBoot{
//////..../////
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。
1. 开源生态
2. 协作、人、软件
3. 评估模型