springcloud mybatis踩过的坑

18 篇文章 0 订阅
9 篇文章 0 订阅

springcloud里有关mybatis踩过的坑

前言

java是进行应用开发非常好的一门语言,springcloud是java语言实现微服务的最好的框架和微服务化的实践,很多中小厂都是使用springcloud来实现微服务的体系, 而mybatis作为这个解决方案中object mapping组件也是非常成熟的一种选择, 今天这个文章就来拆一拆,在mybatis和springcloud/springboot集成中遇到过的一些坑。

 

依赖包的引用

要做到autoconfiguration,自动去扫描Objec Map的classes文件和xml文件;必需引用 mybatis-spring-boot-starter, 否则不能扫描生效。可以用 mybatis-plus 的 mybatis-plus-boot-starter 替代。 (当然如果不是通过autoconfiguration的方式,自己去写starter或者通过显示API调用的方式的话除外。)

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
        </dependency>

 @MapperScan 的原罪

有关MapperScan支持多个包的问题,网上大部分说是通过 basePackage 指定扫描多个包,本身没问题,但不是一个完美的方案。原因如下:

(1)如果扫描的包名是一个较顶级的,那么,一些不是 mapper 的 interface 也会被处理成 mapper 而被创建成一个 spring bean,造成系统无法启动。

(2)缩小包的范围,最好是只配置 mapper 对应包,但如果把所有包含 mapper 的包罗列出来, 列表变得比较长,列表虽然可以用通配符解决一部分问题,但需要包包满足一些统一的规则。  同时,对于层级不同的情况,根本还是不能处理。 

(3)mapscan写在了@SpringBootApplication这个入口主main类上,降低了扩展性,每增加或调整 mapper 包,都要到 @MapperScan 中去注册。业务代码的变更影响了框架性的代码。尤其是对于多模块的情况,这个问题更加的不好控制。 违背依赖的原则,本来框架不依赖业务,现在变成了框架反过来要因业务变化而调整代码。

如何来解决这个问题, 我在写db-spring-boot-starter这个微服务的底层子框架的时候,选择的方式是:

在 @MapperScan 中,使用 basePackage + annotationClass 组件解决问题。 所有的 mapper 上加上 @Mapper 注解。这是合理的,因为本身 mapper 属于一类特殊的接口,理应该要通过特殊注册进行区分。有了第1条,basePackage 就可以指定一个较顶级的包名了 

通过上面两条,一方面解决了 mapper 包动态变化的问题,

因为业务上的代码一般会有一个统一的包前缀,典型的如 com.companyname, 那么就可以把它作为 basePackage,只需要配置一次,后面的变化都不受影响。

import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface CityDao extends BaseMapper<City> {

}
##### mybatis-plus配置
#字段策略 IGNORED:"忽略判断",NOT_NULL:"非 NULL 判断"),NOT_EMPTY:"非空判断"
mybatis-plus.global-config.db-config.field-strategy=NOT_NULL
#逻辑删除配置
mybatis-plus.global-config.db-config.logic-delete-value=1
mybatis-plus.global-config.db-config.logic-not-delete-value=0
# 原生配置
mybatis-plus.configuration.map-underscore-to-camel-case=true
mybatis-plus.configuration.cache-enabled=false
mybatis-plus.mapper-locations=classpath:/mapper/*Mapper.xml
mybatis-plus.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

依赖包

        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
        </dependency>
配置参数
pagehelper.helper-dialect: mysql
# 分页合理化参数,默认值为false。当该参数设置为 true 时,pageNum<=0 时会查询第一页, pageNum>pages(超过总数时),会查询最后一页
pagehelper.reasonable: true
# 支持通过 Mapper 接口参数来传递分页参数
pagehelper.support-methods-arguments: true

调用

PageHelper.startPage(pageNum, pageSize); // 设定当前页码,以及当前页显示的条数
List<City> list = cityDao.selectByPage();       
return list;

使用PaginationInnerInterceptor

依赖包

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-extension</artifactId>
        </dependency>

starter加载

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.joinsun.central..db.config.DBAutoConfiguration,\
com.joinsun.central..db.config.JdbcSessionConfiguration
    /**
     * 新的分页插件,一缓和二缓遵循mybatis的规则,需要设置 MybatisConfiguration#useDeprecatedExecutor = false 避免缓存出现问题
     */

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }

调用


	@Override
	public Page<City> listCity(Page myPage) {
		//Page<City> page = PageHelper.startPage(myPage.getPage(), myPage.getLinage());
		Page<City> cityList = cityDao.selectPage(myPage, null);


		return cityList;
	}

结束语

通过springcloud/springboot架构,java实现微服务的实施案例目前成功的非常多,目前有很多基于springcloud和spring cloud alibaba的框架衍生出来的springcloud的微服务框架都是把类似很多的各种类似mybatis,redis,es, oauth, jwt等组件而糅合在一起的开发框架,是我们开发微服务起来非常的方便,但是由于封装了这些细节的地方,出现问题,如果对本身这些基础的组件不熟悉的情况下,就很难去定位,导致这样的一些架构仅仅只是在学习springcloud框架有意义,真正的公司的微服务框架更多的是自研究的框架, 例如我们公司的微服务框架都是自行去研发的,这样也就有了很多踩坑的体验,有这样的踩坑的经历千万别害怕,也许这就是让我们对技术更深入研究的机会。 

以后还会有更多的文章和大家一起来解析“拆坑”体会的经历。  欢迎大家持续关注。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Spring CloudMyBatis 升级为 MyBatis Plus,步骤如下: 1. 引入 MyBatis Plus 的依赖:在 pom.xml 文件中添加以下依赖。 ```xml <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.0</version> </dependency> ``` 2. 修改 Mapper 接口:使用 MyBatis Plus 提供的 BaseMapper 接口替换原有的 Mapper 接口。例如: ```java public interface UserMapper extends BaseMapper<User> { } ``` 3. 修改实体类:使用 MyBatis Plus 提供的注解替换原有的注解。例如: ```java @Data public class User { @TableId(type = IdType.AUTO) private Long id; private String name; private Integer age; private String email; } ``` 4. 修改配置文件:在 application.yaml 或 application.properties 文件中添加以下配置。 ```yaml mybatis-plus: mapper-locations: classpath*:mapper/**/*.xml configuration: map-underscore-to-camel-case: true ``` 5. 使用 MyBatis Plus 提供的 API:例如,使用 BaseMapper 提供的方法进行 CRUD 操作。 ```java @Service public class UserService { @Autowired private UserMapper userMapper; public void saveOrUpdate(User user) { if (user.getId() == null) { userMapper.insert(user); } else { userMapper.updateById(user); } } public void deleteById(Long id) { userMapper.deleteById(id); } public User getById(Long id) { return userMapper.selectById(id); } public List<User> list() { return userMapper.selectList(null); } } ``` 注意:在升级过程中,如果你使用了 MyBatis 原生的注解和 API,需要进行相应的修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

inthirties

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值