您的位置 首页 > 娱乐休闲

Mybatis深度整合Mysql的Json字段 extcol

以前当业务数据结构变化时,往往需要采用的方案是:

  1. 修改表结构增加字段
  2. 遇到数据结构有list结构时,新建1对多的关联子表
  3. 用字典表表示字段的增加

以上方案对代码侵入性很强,同时与旧业务数据结构不兼容。导致代码从实体类

、Dao、Service、Controller层都要修改。


随着NOSQL数据库的广泛应用,可扩展的存储方式在关系型数据库中也有了很好的支持,最新的My中就新增加了一个数据类型Json,使用mysql的json类型字段做扩展字段,可以以json串形式动态的存储任意结构的数据,包括list结构的数据也不必再创建子表。代码的实体类和Dao层不必修改,其他层代码修改量也能够减少。


Mysql常见json字段操作

My开始支持json字段

创建带有json字段的表micro_test,其中extcol为json类型字段

CREATE TABLE `micro_test` ( `id` int(11) NOT NULL AUTO_INCREMENT, `meta_name` VARCHAR(100) DEFAULT NULL COMMENT '元数据名称', `create_time` datetime DEFAULT NULL COMMENT '创建时间', `update_time` datetime DEFAULT NULL COMMENT '更新时间', `extcol` json DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB CHARSET=utf8;

插入json字段

可按照json字符串插入json字段

Insert into micro_test (extcol,meta_name,create_time) values('{"name":"tomcat","age":15}',’123’,now());

查询json字段

可以根据path查询json字段中全部或部分数据

Select meta_name,extcol->>'$.name' as name,extcol->>'$.age' as age from micro_test;

修改json字段

可以根据path局部更新json字段中数据

Update micro_test set extcol=json_set(extcol,'$.name','jeffrey') where meta_name='123'

My.22版本以后支持JSON_MERGE_PATCH

可以省略path参数,全面更新json字段中数据

Update micro_test set extcol=json_set(extcol,'{“name”:”n1”,”age”:30}') where meta_name='123'

Mybatis使用Json字段

按照mybatis常规方式把json函数写入到xml文件中的sql中,即可支持json字段增删改查。但查询出的json字段为字符串类型,需要手工转成bean,插入时需手工把bean转成json字符串,这样做不利于面向对象编程。


Mybatis深度整合Json字段

实现bean与json串在mybatis内部转换,这样做的优点是dao层代码和sql不变,service层可以增删改查不同的动态Entity对象。更符合面向对象编程习惯提高开发效率。


Extcol开源项目实现Mybatis与mysql的json字段深度整合

项目地址为:

pom引用extcol的jar

<dependency> <groupId>com.gi;/groupId> <artifactId>extcol</artifactId> <version>0.0.1-RELEASE</version> </dependency>

Extcol包中TypeHandler子类TagToJsonTypeHandler 实现mybatis在数据库操作过程中的参数输入和结果转换的拦截。拦截父类为ExtBeanWrapper的对象。

使TagToJsonTypeHandler生效需要配置

mybatis-plus: typeHandlersPackage: com.nh.micro.ext.th

Extcol包中ExtBeanWrapper类,作为json对象转换的目标对象,内有map成员变量保存实际数据,getobj和setobj方法是使用fastjson做对象与map的转换。

使用Extcol的Demo

引入和配置好extcol后,在demo业务系统工程中编写对应micro_test表的实体类TestDto,其中json字段的成员变量类型是ExtBeanWrapper。

public class TestDto { private Integer id; private String metaKey; private String metaName; private String metaType; private Date createTime; private ExtBeanWrapper extcol; public ExtBeanWrapper getExtcol() { return extcol; } public void setExtcol(ExtBeanWrapper extcol) { }

扩展字段业务bean

例如扩展bean为ExtEntity有两个在数据库中json字段动态存储的字段t1和t2

public class ExtEntity { private String t1; private String t2; public String getT1() { return t1; } public void setT1(String t1) { = t1; } public String getT2() { return t2; } public void setT2(String t2) { = t2; } }

在以TestDto为更新和插入时的参数操作时,mybatis将负责将bean转为json串

<update id="insertInfo4JsonXml" parameterType="com.;> insert into micro_test(meta_name,extcol,create_time) values (#{metaName},#{extcol},now()) </update>

当执行查询语句时,返回的结果映射到ExtBeanWrapper 类型的字段时,mybatis将负责将json串转为ExtBeanWrapper ,且这个ExtBeanWrapper 可以按照不同的业务bean自适应转化。

<resultMap id="TestDto" type="com.; > <id column="id" property="id" jdbcType="INTEGER" /> <result column="meta_name" property="metaName" jdbcType="VARCHAR" /> <result column="create_time" property="createTime" jdbcType="TIMESTAMP" /> <result column="extcol" property="extcol" jdbcType="VARCHAR" /> </resultMap> <select id="getInfo4JsonXml" resultMap="TestDto" parameterType="java.lang.String"> SELECT * from micro_test where meta_name=#{name} </select>

取查询结果中JSON字段中存储的业务类ExtEntity 的代码

public List<TestDto> testQuery4JsonXml(String name){ List<TestDto> retList=(name); if(retList!=null){ for(TestDto testDto:retList){ ExtBeanWrapper extBeanWrapper=(); ExtEntity extEntity=(ExtEntity) ex); Sy()); } } return retList; }

Mybatisplus的bean更新时使用JSON_MERGE_PATCH

修改mybatisplus的AutoSqlInjector

private String getPlaceTag(String row){ int start=row.indexOf("#{"); int end=row.indexOf("}")+1; String temp=row.substring(start,end); Sy(temp); return temp; } private String getColTag(String row){ int end=row.indexOf("=#{"); int start=0; i("<if")){ start=row.indexOf(">")+1; } String temp=row.substring(start,end); Sy(temp); return temp; } private String createNewPlace(String colTag,String placeTag){ String temp="json_merge_patch("+colTag+","+placeTag+")"; return temp; } protected void injectUpdateByIdSql(boolean selective, Class<?> mapperClass, Class<?> modelClass, TableInfo table) { SqlMethod sqlMethod = selective ? SqlMe : SqlMe; String temp=sqlSet(selective, table, "et."); String osql=temp; if(selective){ String[] tempArray=("\n\t"); StringBuilder sb=new StringBuilder(""); for(String row:tempArray){ i("typeHandler")){ Sy(getPlaceTag(row)); String placeTag=getPlaceTag(row); Sy(getColTag(row)); String colTag=getColTag(row); String nPlaceTag=createNewPlace(colTag, placeTag); Sy(nPlaceTag); row=row.replace(placeTag, nPlaceTag); (row).append("\n\t"); }else{ (row).append("\n\t"); } } osql=(); } String sql = S(), (), osql, (), "et." + (), "<if test=\"et instanceof java.u\">" + "<if test=\"et.MP_OPTLOCK_VERSION_ORIGINAL!=null\">" + "and ${et.MP_OPTLOCK_VERSION_COLUMN}=#{et.MP_OPTLOCK_VERSION_ORIGINAL}" + "</if>" + "</if>" ); Sy(sql); SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass); (mapperClass, modelClass, (), sqlSource); }

责任编辑: 鲁达

1.内容基于多重复合算法人工智能语言模型创作,旨在以深度学习研究为目的传播信息知识,内容观点与本网站无关,反馈举报请
2.仅供读者参考,本网站未对该内容进行证实,对其原创性、真实性、完整性、及时性不作任何保证;
3.本站属于非营利性站点无毒无广告,请读者放心使用!

“实体类如何扩展字段,实体类字段默认值,实体类忽略字段,实体类忽略字段注解”边界阅读