加入收藏 | 设为首页 |

周克华-Mybatis深度整合Mysql的Json字段 extcol

海外新闻 时间: 浏览:635 次

曾经当事务数据结构变化时,往往需求选用的计划是:

  1. 修正表结构添加字段
  2. 遇到数据结构有list结构时,新建1对多的相关子表
  3. 用字典表表明字段的添加

以上计划对代码侵入性很强,一起与旧事务数据结构不兼容。导致代码从实体类

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


跟着NOSQL数据库的广泛应用,可扩展的存储办法在联系型数据库中也有了很好的支撑,最新的MySQL5.7中就新添加了一个数据类型JSON,运用mysql的json类型字段做扩展字段,能够以json串办法动态的存储恣意结构的数据,包含list结构的数据也不用再创立子表。代码的实体类和Dao层不用修正,其他层代码修正量也能够削减。


Mysql常见json字段操作

Mysql5.7开端支撑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') wh周克华-Mybatis深度整合Mysql的Json字段 extcolere meta_name='123'

Mysql5.7.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字段 extcol目完成Mybatis与mysql的json字段深度整合

项目地址为:

https://github.com/jeffreyning/extcol.git

pom引证extcol的jar


com.github.jeffreyning
extcol
0.0.1-RELEASE

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_tes周克华-Mybatis深度整合Mysql的Json字段 extcolt表的实体类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) {
this.t1 = t1;
}
public String getT2() {
return t2;
}
public void setT2(String t2) {
this.t2 = t2;
}
}

在以TestDto为更新和刺进时的参数操作时,mybatis将担任将bean转为json串


insert into micro_test(meta_name,extcol,create_time) values (#{metaName},#{extcol},now())

当履行查询句子时,回来的成果映射到ExtBeanWrapper 类型的字段时,mybatis将担任将json串转为ExtBeanWrapper ,且这个ExtBeanWrapper 能够依照不同的事务bean自适应转化。

 







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

public List testQuery4JsonXml(String name){
List retList=testDao.getInfo4JsonXml(name);
if(retList!=null){
for(TestDto testDto:retList){
ExtBeanWrapper extBeanWrapper=testDto.getExtcol();
ExtEntity extEntity=(ExtEntity) extBeanWrapper.getObj(ExtEntity.class);
System.out.println(extEntity.getT1());
}
}
return retList;
}

Mybatisplus的bean更新时运用JSON_MERGE_PATCH

修正mybatisplus的AutoSqlInjector

 private String getPlaceTag(Strin周克华-Mybatis深度整合Mysql的Json字段 extcolg row){
int start=row.indexOf("#{");
int end=row.indexOf("}")+1;
String temp=row.substring(start,end);
System.out.println(temp);
return temp;
}
private String getColTag(String row){
int end=row.indexOf("=#{");
int start=0;
if(row.contains("
start=row.indexOf(">")+1;
}
String temp=row.substring(start,end);
System.out.println(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
SqlMethod sqlMethod = selective ? SqlMethod.UPDATE_BY_ID : SqlMethod.UPDATE_ALL_COLUMN_BY_ID;
String temp=sqlSet(selective, table, "et.");
String osql=temp;
if(selective){
String[] tempArray=temp.split("\n\t");
StringBuilder sb=new StringBuilder("");
for(String row:tempArray){
if(row.contains("typeHandler")){
System.out.println(getPlaceTag(row));
String placeTag=getPlaceTag(row);
System.out.println(getColTag(row));
String colTag=getColTag(row);
String nPlaceTag=createNewPlace(colTag, placeTag);
System.out.println(nPlaceTag);
row=row.replace(placeTag, nPlaceTag);
sb.append(row).append("\n\t");
}else{
sb.append(row).append("\n\t");
}
}
osql=sb.toString();
}
String sql = String.format(sqlMethod.getSql(), table.getTableName(), osql, table.getKeyColumn(),
"et." + table.getKeyProperty(),
""
+ ""
+ "and ${et.MP_OPTLOCK_VERSION_COLUMN}=#{et.MP_OPTLOCK_VERSION_ORIGINAL}"
+ "
"
+ "
"
);
System.out.println(sql);

SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
this.addUpdateMappedStatement(mapperClass, modelClass, sqlMethod.getMethod(), sqlSource);
}