使用mysql的XML Functions让mysql schema free

    xiaoxiao2025-11-09  18

    schema free 是mongodb里的一个重要的特性,很适合业务系统对某些非重点字段的维护,但是mongodb在运维上比mysql代价高,所以DBA也不会推荐使用。一般业务系统都默认使用成熟而又稳定的mysql。

    但是,如何在mysql上实现schema free呢?

    横纵表方案

    业务系统最常见的是横纵表方案横表存储主要字段(用于查询、排序的字段)纵表用 key-value的形式存储非主要字段

    而当业务需要获取一个实体时,需要在业务代码中这样处理

    1.查询主表select * from main_table where id=?

    2.查询纵表select key,value from vertical_table where obj_id=?

    3.然后将这个kv结果集合塞回到实体中,然后返回

    这样做当然可以满足要求,但是,逻辑的复杂度增加了,不但是查询,新建、更新、删除都需要操作2张表去完成。

    XML Functions方案

    当我看到了mysql的XML Functions后,突然感到世界打开了一扇新的窗,完全可以通过它来实现schema free。

    XML Functions 的两个函数

    NameDescriptionExtractValue()Extracts a value from an XML string using XPath notationUpdateXML()Return replaced XML fragment

    用法

    SELECT ExtractValue(memo, '/e') AS val1 FROM table1

    这样可以查询table1表中的memo字段里中间的内容

    update table1 set memo=UpdateXML(memo, '/e', '<e>fff</e>')

    可以更新table1 表中memo字段中的中间的内容为fff

    我们需要做的,只需要纵表的表中增加一个大字段(varchar(1000)?大小自己预估),然后在这个大字段存储非主要信息

    能再简单一点吗?

    事情到这里是不是完成了呢?写这样繁琐的sql是不是有点复杂啊?

    于是我写了一个myibatis的拦截器,封装的xml的操作,让使用方感觉是在操作横表一样去操作大字段

    比如:id,title 和横表字段,大字段是memo,author是xml节点

    Select

    查询时只要输入sql

    select id,title,_memo_author from tb

    就可以完成查询,当然,在拦截器中将它转换成了

    select id,title,ExtractValue(memo, '/author')from tb

    通过myibatis的orm可以将大字段中的节点直接映射到对象属性上

    Insert

    insert操作也一样

    insert into tb (id,title,_memo_author) values(1,'interstellar','buming.pl')

    Update

    update tb set id=1,title='interstellar',_memo_author='buming.pl'

    author节点如果不存在,会在xml中新加,如果存在,会修改

    下面这个是jar包

    <dependency> <groupId>com.taobao</groupId> <artifactId>interstellar</artifactId> <version>1.1.0</version> </dependency>

    只需要在myibatis拦截器列表中增加拦截器

    <property name="plugins"> <list> <bean class="com.taobao.interstellar.InterstellarInterceptor"> <property name="properties"> <!-- memo:纵表大字段,defaultPrefix:前缀,defaultSuffix:后缀 --> <value> defaultColumn=memo defaultPrefix=_ defaultSuffix=_ </value> </property> </bean> </list> </property>

    更新列表

    1.1.0

    1、拦截器不作用在prepare阶段,改到 Executor 接口2、sql解析在第一次注册为sqlmap,以后直接调用3、对象不在需要memo属性,通过cglib动态添加4、加入 处理特殊字符

    1.0.3

    修复了如果更新字段为空时,更新不成功bug 

    参考资料:

    XML Functions 的文档 http://dev.mysql.com/doc/refman/5.1/en/xml-functions.html

    最新回复(0)