最近在用mybatis作项目,有一些感触想记录下,主要是mybatis(以及它的一些插件)相比较于Spring data(或者jpa,hibernate等)的优点地方.html
我以为mybatis相比于Spring data的最大的几个优点的地方在于:spring
不论是在以前的公司仍是如今的公司都有不少这样的业务..好比进来先是一个查询界面,有N多条件,而后下面是个根据条件分页查询的数据,查出数据之后你能够进行一些修改呀查看呀等等操做.sql
这样的业务若是是Spring data来作的话比较麻烦.数据库
由于上面的条件用户是能够输入也能够不输入的.在本来的公司我看到有几种解决方法:json
1.本身动态的拼接hql.因此service的代码里会出现不少if(StringUtils.isEmpty(xxxx查询条件)){hql += "and xxx条件 = :XXX参数"}相似于这样的代码.这样首先是hql拼接,可读性是比较差的,另外SQL是在service层拼接的.可能代码复用的几率会小一点.session
2.公司有本身的封装(http://www.cnblogs.com/abcwt112/p/5874401.html).简单来讲就是指定一下这个查询是对应哪一个entity.而后根据传过来的request里的paramter找到entity对应的field而后仍是拼接sql....只不过本身在service里不用拼接了...能够稍微简化一些代码...可是不是很灵活..有些功能还没封装.好比or的条件链接就不行.只能拼接and...而后不能嵌套查询..因此能够说是1方法的简化版可是相比于本身拼接SQL有些经常使用的功能作不到.mybatis
3.虽然公司我一直没看到有人用过.可是我知道.Spring data是在jpa外包装了一层,jpa是有criteria的查询方式的.spring data也有相应的Specifications的那种查询方式.这种方法能够帮助咱们动态拼接查询条件..(这种查询方式我用的不多.可能说的不必定对).我以为这种查询方式有个最不方便的地方在于若是要多表关联查询,你的entity里没有@onetomany或者@manytomany或者@onetoone这样的关键的话你是取不到另外关联的那张表的..这样的话你就不可能拼接那个where条件..这样的状况仍是蛮常见的,由于表的关联太多了.不是全部的关联都写成了成员域..因此这种查询方法也是有缺陷的..架构
总结下的话就是Spring data动态查询拼接SQL比较麻烦..主要是在service里常常要判断XXX参数用户有没有输入..有输入就hql+=....看起来SQL不直观.都不知道完整的SQL结构,也很容易拼错.框架
这样的业务若是mybatis来作:eclipse
1.按照我如今公司的套路,大概是最简单粗暴的.咱们mybatis没用任何插件,也没有自动生成任何XML.纯手写.
那么我要作的也就是在XML里写个查询SQL对应的select语句.而后再拼接条件的时候能够用<if>标签去过滤就好了.
这样的好处就是SQL比较直观,到底查什么表一目了然,而后由于拼接SQL至关因而在dao层,因此复用几率会大一些.好比其余业务也要查这张表的数据,能够复用.
这个问题主要是entity与dto之间数据拷贝的问题,还有一些建表问题,没用过hibernate或者用hibernate自动生成表的朋友可能不会有这样的感受.
Spring data:
由于spring data数据库映射到实体用的是entity,而前台显示用的是dto.因此数据确定须要拷贝. 另一个比较坑爹的地方是entity若是和spring data的session关联了的话,若是修改了字段,即便不显示的调用dao.update,在出了事务之后也会自动更新数据库的(由于是受管实体).因此拷贝是必须的.这样的话会须要一些时间,另外对象拷贝也蛮麻烦的.特别是还有集合的状况更是麻烦.(以前公司用cglib的bean copier http://www.cnblogs.com/abcwt112/p/6073103.html)
还有个小坑就是若是查出来的对象有懒加载的集合属性,那么固然先后台交互的时候,好比用jackson将entity转化成json的时候会自动调用entity的get方法,致使懒加载被触发,而后hibernate自动调用SQL去查询数据,然而那个时候事务早已关闭,会报错,这也是一个坑,之前公司基本上是一个业务域的相关联对象一次性查出来(也不是不少数据).
另外当建表不是很规范的时候(好比多表关联没有使用外键关联,而是共享主键,又是单向关联的时候)spring data jpa的级联操做可能会产生问题.(http://www.cnblogs.com/abcwt112/p/4849416.html)
mybatis:
很简单..查出什么数据直接用....
公司仍然有entity和dto.其实我以为只须要留下dto就足够了.有2套对象的话若是dao里的方法的参数不一样也是须要转化的.mybatis只是把数据库查询的结果映射到了dto上.我以为没那么复杂...不须要2套对象.只有一套dto就足够了..还简单些.
表的主键在不少时候都是ID自增或者uuid,可是用户并不会知道,他们知道的多是业务上面的主键,好比超市商品的条形码等等.这种时候咱们操做数据库可能不是根据id而是根据这种业务上面的惟一标示去操做数据库.
spring data:
我一直以为这是Spring data相比于hibernate和jpa最引觉得傲的功能,能够根据dao的方法名自动映射成sql.
好比findByName会被自动翻译成select * from xxx where name = :name
updateNameByStateAndLevelIsNotNull会被自动翻译成update xxx set name = :name where state = :state and level is not null
能够说Spring data能够在绝大部分状况下避免写SQL.因此操做数据库比较方便.美中不足的就是若是SQL比较长参数比较多..那么方法名也会比较长....有时候看起来比较累.
mybatis:
让我从首选spring data变成首选mybatis做为持久层框架的一个缘由就在这里.(虽然spring data已经作的很好了)
按照公司的作法咱们须要手写SQL...那是很坑爹的.绝对没有Spring data好用.可是eclipse有个mybatis的generator插件.......
他能够自动帮咱们生成XML..这里生成的几个方法很是很是有用....
1 List<TmTransportAddressDto> selectByExample(TmTransportAddressExample example); 2 3 int updateByExampleSelective(@Param("record") TmTransportAddressDto record, @Param("example") TmTransportAddressExample example); 4 5 int updateByExample(@Param("record") TmTransportAddressDto record, @Param("example") TmTransportAddressExample example); 6 7 int countByExample(TmTransportAddressExample example); 8 9 int deleteByExample(TmTransportAddressExample example);
就是这几个example方法.
看一个使用example的小例子:
1 TmTransportAddressDto tmTransportAddressDto = new TmTransportAddressDto(); 2 tmTransportAddressDto.setExecutePerson(tmTransportChangeRecord.getDriverNameAfter()); 3 tmTransportAddressDto.setExecuteDeviceNo(tmTransportChangeRecord.getPlateNumberAfter()); 4 tmTransportAddressDto.setExecuteTelephone(tmTransportChangeRecord.getDriverPhoneAfter()); 5 TmTransportAddressExample tmTransportAddressExample = new TmTransportAddressExample(); 6 tmTransportAddressExample.createCriteria() 7 .andExecuteTelephoneEqualTo(tmTransportChangeRecord.getDriverPhoneBefore()).andSnEqualTo(sn); 8 countUpdate += tmTransportAddressDao.updateByExampleSelective(tmTransportAddressDto, 9 tmTransportAddressExample);
上面这9行代码至关因而更新tmTransportAddress表的executePerson,executeDeviceNo等4个字段 where 条件是executeTelphone = XXX and sn = xxx.
这种用法比Spring data还要简单,连dao的方法名都不用写了(其实仍是要写的.只是写在了example里...generator自动生成了通用的XML SQL片断)...很是很是好用!
再不少状况下只要自动生成了xml文件之后基本SQL和额外的dao方法都不须要写了..由于example至关因而动态拼接SQL的方法.能够拼接出任意的SQL.
不过我以为这种用法仍是不太适合页面上那种动态条件分页查询,由于也须要在service里拼接条件..只是简化了一些.并无本身在XML里写完整的SQL直观.
以上即是我最近2个月学习mybatis的一些感触.mybatis在不少状况下确实是比spring data简单好用(其实就是拼SQL的功能很强大).
后面会再分享一些若是我是架构师会怎么在项目里使用mybatis的一些想法