关于系统持久层实现方案


placeholder image
admin 发布于:2015-06-03 11:34:17
阅读:loading

从开始工作到现在的这一路上走来,持久层这块自然是经历了一系列的技术,原始JDBC简单封装、Hibernate、DbUtils、JdbcTemplate、本系统Dao实现、MyBatis,也就是从去年年底开始接触到MyBatis,使用这一段时间过来,发现个人最喜欢的持久层技术就是它了,虽然最晚了解它,但是发现真的是似曾相识,因为最开始工作的单位对持久层的封装也跟它的实现粘了一点点的关系,本文章重点说的本系统实现方案,更是粘了一点点点的关系。至于什么时候使用哪个实现,就看项目的使用了。

根据对以上相关持久层的技术的实践,我专门写了一套自己用来比较方便的技术实现,对于个人来讲有一个适合自己的快速开发平台,利用自己掌握的技术来做点什么事情不是很好嘛?这一路走来也是对各种持久层的封装,其中对于Apache的DbUtils组件也进行过封装,本系统中能找到的。现将通过代码分析,来谈谈一下我对它的理解:

优点:

将sql文件存储于xml配置文件中,易于管理维护;

提供测试、开发参数配置,开发环境则每次读取sql文件;

基于jdbcTemplate的基础,提供更强大的函数支持;

根据特殊表达式实现对动态sql的支持(简单处理);

支持传统jdbc直接传递sql语句;完美使用?的传值的处理方式(拒绝拼sql的方式);

改进:

在了解了MyBatis技术之后发现那对于处理动态sql才叫真的强大;

在了解了FreeMarker技术之后发现用它来处理动态sql貌似是可以实现的很“优美的”;

持久层函数在项目使用时基本上是写的最多的,那么提供一系列强大的函数来满足平时的使用岂不是个很好的事情?就拿一个查询返回Map对象的函数来说,本系统的实现方法至少为6个,传递sql和sqlKey的各有3个,如下:

   //查询参数为数组查询,适用于查询条件固定的情况

   public Map queryForMapSqlKey(String sqlKey , Object...params);

   //查询参数为map,可用于处理动态查询条件

   public Map queryForMapSqlKey(String sqlKey , Map paramsMap);

   //查询条件为对象,可用于处理动态查询条件

   public Map queryForMapSqlKey(String sqlKey , Entity entity);

   public Map queryForMap(String sql , Object...params);//同上,直接传递sql语句

   public Map queryForMap(String sql , Map paramsMap);//同上,直接传递sql语句

   public Map queryForMap(String sql , Entity entity);//同上,直接传递sql语句

        所谓的sqlKey是指将sql语句存储于xml配置文件中,调用时传递一个唯一标识的ID即达到调用sql的目的,如下为一个最基本的sql语句,

    SELECT

        id,

        type,

        status,

        editorContent,

        url,

        title,

        createTime

    FROM

        information a

    WHERE

        a.id = ?

        基于这种静态的查询(参数)条件,我们调用时可以使用传递Object...params的方式,如下:

    xxxDao.queryXById("xxxDao.queryXById" , new Object[]{ id });

    //当然参数只有一个,所以调用Object...params的方式必须显示的指定使用数组

    xxxDao.queryXById("xxxDao.queryXById" , id);//当只存在一个参数时不能直接这么调用的,具体原因不在此处解释

      此时你会不会有些疑问呢,比如说,如果我现在是列表查询呢,我的查询参数可以有也可以没有,那这个是怎么实现呢?

    SELECT

        *

    FROM

        information a

    WHERE

        1=1

        and a.type = [{type}] --表达式1,普通参数

        [%{ and a.title like result(title) }%] --表达式2,动态sql,根据参数值

        [{and a.status = result(status) }] --表达式3

        order by [{replace(createTime)}] desc --表达式4,参数动态替换

         到这里我将引入一个我认为的“表达式”的概念,上述有一个类似于[{XXX}]的表达式,结合上述sql写法它的解析原理是:

        1)、type是一个必定会出现的查询条件;

        2)、status是一个可能会出现的查询条件,换句话说如果传递的参数集合或对象中,status作为hashMap的key或者对象的属性,它的值不为null时会出现这个表达式中的语句,result将被完整的替换成?的方          式,  否则会忽略掉此表达式中的所有字符串;

        3)、如果某些查询条件需要使用like查询,需要对获取的属性进行%的追加,则可以看一下title属性查询的方式,原理是一样的,当然此处不限制于%字符,理论上是任意字符;

        4)、如果一些动态排序的功能只能使用替换的方式,则使用表达式4的方式实现;

        5)、如果一些类似mybatis的if、for之类的判断、循环写法采用编程式的方式解决;

    再回过头来,看看以下添加的两种方式,使用动态解析sql和固定参数的方式,参考如下:

    --方式1

    INSERT

    INTO

        information

        (

            createTime,

            type,

            status,

            editorContent,

            url,

            title,

            simpleContent

        )

        VALUES

        (

            [{createTime}],

            [{type}],

            [{status}],

            [{editorContent}],

            [{url}],

            [{title}],

            [{simpleContent}]

        )

    --方式2        

    INSERT

    INTO

        information

        (

            createTime,

            type,

            status,

            editorContent,

            url,

            title,

            simpleContent

        )

        VALUES

        (

            ?,

            ?,

            ?,

            ?,

            ?,

            ?,

            ?

        )

系统持久层继承结构图

 怎么样看着上面的2种方式,是不是可以任意写呢,现在熟悉了MyBatis后,单说它处理动态sql部分,支持判定,循环,肯定它属于更强大的,不过在不理解MyBatis和FreeMarker的基础上能实现以上,是不是也略叼呢,本Dao模块的核心代码也就百十来行(本系统中提供了一个文件在线编辑的功能,所有的源码都会公开的),原理就是使用正则表达式的特殊字符匹配和String的replace。另外对于喜欢写sql的朋友们如果还不了解MyBatis,或许是可以试着看看相关视频,那万一真要是喜欢上了呢?呵呵。


 点赞


 发表评论

当前回复:作者

 评论列表


留言区