springcloud里有关mybatis踩过的坑前言 java是进行应用开发非常好的一门语言,有很多成熟的开发框架。 springcloud是java语言实现微服务的最好的框架和微服务化的实践,很多中小厂都是使用springcloud来实现微服务的体系,而mybatis作为这个解决方案中objectmapping组件也是非常成熟的一种选择,今天这个文章就来拆一拆,在mybatis和springcloudspringboot集成中遇到过的一些坑。 依赖包的引用 要做到autoconfiguration,自动去扫描ObjecMap的classes文件和xml文件;必须引用mybatisspringbootstarter,否则不能扫描生效。可以用mybatisplus的mybatisplusbootstarter替代。(当然如果不是通过autoconfiguration的方式,自己去写starter或者通过显示API调用的方式的话除外。) dependencygroupIdcom。baomidougroupIdmybatisplusbootstarterartifactIddependency MapperScan的原罪 有关MapperScan支持多个包的问题,网上大部分说是通过basePackage指定扫描多个包,本身没问题,但不是一个完美的方案。原因如下: (1)如果扫描的包名是一个较顶级的,那么,一些不是mapper的interface也会被处理成mapper而被创建成一个springbean,造成系统无法启动。 (2)缩小包的范围,最好是只配置mapper对应包,但如果把所有包含mapper的包罗列出来,列表变得比较长,列表虽然可以用通配符解决一部分问题,但需要包包满足一些统一的规则。同时,对于层级不同的情况,根本还是不能处理。 (3)mapscan写在了SpringBootApplication这个入口主main类上,降低了扩展性,每增加或调整mapper包,都要到MapperScan中去注册。业务代码的变更影响了框架性的代码。尤其是对于多模块的情况,这个问题更加的不好控制。违背依赖的原则,本来框架不依赖业务,现在变成了框架反过来要因业务变化而调整代码。 如何来解决这个问题,我在写dbspringbootstarter这个微服务的底层子框架的时候,选择的方式是: 在MapperScan中,使用basePackageannotationClass组件解决问题。所有的mapper上加上Mapper注解。这是合理的,因为本身mapper属于一类特殊的接口,理应该要通过特殊注册进行区分。有了第1条,basePackage就可以指定一个较顶级的包名了 通过上面两条,一方面解决了mapper包动态变化的问题, 因为业务上的代码一般会有一个统一的包前缀,典型的如com。companyname,那么就可以把它作为basePackage,只需要配置一次,后面的变化都不受影响。 importorg。apache。ibatis。annotations。MMapperpublicinterfaceCityDaoextendsBaseMapperCity{} mybatisplus配置字段策略IGNORED:忽略判断,NOTNULL:非NULL判断),NOTEMPTY:非空判断mybatisplus。globalconfig。dbconfig。fieldstrategyNOTNULL逻辑删除配置mybatisplus。globalconfig。dbconfig。logicdeletevalue1mybatisplus。globalconfig。dbconfig。logicnotdeletevalue0原生配置mybatisplus。configuration。mapunderscoretocamelcasetruemybatisplus。configuration。cacheenabledfalsemybatisplus。mapperlocationsclasspath:mapperMapper。xmlmybatisplus。typeAliasesPackage{mapper。entity。path:com。joinsunsoft。。model。entity} 分页的问题 关于mybatis的分页,目前有两个主流派系,一个是使用mybatis的pagehelper,pagehelper实现了一个mybatis的拦截器,在执行mybatis的query时,会使用拦截器的方式来加入分页的代码和处理。另一个派系,是使用mybatisplus的PaginationInnerInterceptor来实现。不论用两种方式里的哪一个方式,都必须,1。要使用starter才能生效,或者写自己的starter,2。只使用一个,要么使用pagehelper,要么就是用mybatisPlus里的PaginationInnerInterceptor。每种方式都必须对应自己的调用方式,不能错用。 使用PageHelper 依赖包 dependencygroupIdcom。github。pagehelpergroupIdpagehelperspringbootstarterartifactIddependency 配置参数 pagehelper。helperdialect:mysql分页合理化参数,默认值为false。当该参数设置为true时,pageNum0时会查询第一页,pageNumpages(超过总数时),会查询最后一页pagehelper。reasonable:true支持通过Mapper接口参数来传递分页参数pagehelper。supportmethodsarguments:true PageHelper。startPage(pageNum,pageSize);设定当前页码,以及当前页显示的条数ListCitylistcityDao。selectByPage(); 使用PaginationInnerInterceptor 依赖包 dependencygroupIdcom。baomidougroupIdmybatisplusextensionartifactIddependency starter加载 org。springframework。boot。autoconfigure。EnableAutoConfigurationcom。joinsun。central。。db。config。DBAutoConfiguration,com。joinsun。central。。db。config。JdbcSessionConfiguration 新的分页插件,一缓和二缓遵循mybatis的规则,需要设置MybatisConfigurationuseDeprecatedExecutorfalse避免缓存出现问题BeanpublicMybatisPlusInterceptormybatisPlusInterceptor(){MybatisPlusInterceptorinterceptornewMybatisPlusInterceptor();interceptor。addInnerInterceptor(newPaginationInnerInterceptor(DbType。MYSQL));} OverridepublicPageCitylistCity(PagemyPage){PageCitypagePageHelper。startPage(myPage。getPage(),myPage。getLinage());PageCitycityListcityDao。selectPage(myPage,null);returncityL} 结束语 通过springcloudspringboot架构,java实现微服务的实施案例目前成功的非常多,目前有很多基于springcloud和springcloudalibaba的框架衍生出来的springcloud的微服务框架都是把类似很多的各种类似mybatis,redis,es,oauth,jwt等组件而糅合在一起的开发框架,使我们开发微服务起来非常的方便,但是由于封装了这些细节的地方,出现问题,如果对本身这些基础的组件不熟悉的情况下,就很难去定位,导致这样的一些架构仅仅只是在学习springcloud框架有意义,真正的公司的微服务框架更多的是自研究的框架,例如我们公司的微服务框架都是自行去研发的,这样也就有了很多踩坑的体验,有这样的踩坑的经历千万别害怕,也许这就是让我们对技术更深入研究的机会。 以后还会有更多的文章和大家一起来解析拆坑体会的经历。欢迎大家持续关注。