SpringBoot项目中借助Mybatis来操作数据库,对大部分java技术栈的小伙伴来说,并不会陌生;我们知道,使用mybatis,一般会有下面几个
Entity: 数据库实体类
Mapper: db操作接口
Service: 服务类
本片博文中的注解,放在Mapper上,你知道注册Mapper有几种方式么(这个问题像不像”茴”字有几个写法😬)
I. 环境准备 1. 数据库准备 使用mysql作为本文的实例数据库,新增一张表
1 2 3 4 5 6 7 8 9 10 CREATE TABLE `money` ( `id` int (11 ) unsigned NOT NULL AUTO_INCREMENT, `name` varchar (20 ) NOT NULL DEFAULT '' COMMENT '用户名' , `money` int (26 ) NOT NULL DEFAULT '0' COMMENT '钱' , `is_deleted` tinyint(1 ) NOT NULL DEFAULT '0' , `create_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间' , `update_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间' , PRIMARY KEY (`id` ), KEY `name` (`name` ) ) ENGINE =InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET =utf8mb4;
2. 项目环境 本文借助 SpringBoot 2.2.1.RELEASE + maven 3.5.3 + IDEA进行开发
pom依赖如下
1 2 3 4 5 6 7 8 9 10 11 <dependencies > <dependency > <groupId > org.mybatis.spring.boot</groupId > <artifactId > mybatis-spring-boot-starter</artifactId > <version > 2.2.0</version > </dependency > <dependency > <groupId > mysql</groupId > <artifactId > mysql-connector-java</artifactId > </dependency > </dependencies >
db配置信息 application.yml
1 2 3 4 5 spring: datasource: url: jdbc:mysql://127.0.0.1:3306/story?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai username: root password:
II. 实例演示 前面基础环境搭建完成,接下来准备下Mybatis的Entity,Mapper等基础类
1. 实体类,Mapper类 数据库实体类MoneyPo
1 2 3 4 5 6 7 8 9 10 11 12 13 14 @Data public class MoneyPo { private Integer id; private String name; private Long money; private Integer isDeleted; private Timestamp createAt; private Timestamp updateAt; }
对应的Mapper接口(这里直接使用注解的方式来实现CURD)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 public interface MoneyMapper { @Options (useGeneratedKeys = true , keyProperty = "po.id" , keyColumn = "id" ) @Insert ("insert into money (name, money, is_deleted) values (#{po.name}, #{po.money}, #{po.isDeleted})" ) int save (@Param("po" ) MoneyPo po) ; @Update ("update money set `money`=#{money} where id = #{id}" ) int update (@Param("id" ) int id, @Param ("money" ) long money) ; @Delete ("delete from money where id = #{id}" ) int delete (@Param("id" ) int id) ; @Select ("select * from money where id = #{id}" ) @Results (id = "moneyResultMap" , value = { @Result (property = "id" , column = "id" , id = true , jdbcType = JdbcType.INTEGER), @Result (property = "name" , column = "name" , jdbcType = JdbcType.VARCHAR), @Result (property = "money" , column = "money" , jdbcType = JdbcType.INTEGER), @Result (property = "isDeleted" , column = "is_deleted" , jdbcType = JdbcType.TINYINT), @Result (property = "createAt" , column = "create_at" , jdbcType = JdbcType.TIMESTAMP), @Result (property = "updateAt" , column = "update_at" , jdbcType = JdbcType.TIMESTAMP)}) MoneyPo getById (@Param("id" ) int id) ; }
对应的Service类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 @Slf 4j@Service public class MoneyService { @Autowired private MoneyMapper moneyMapper; public void basicTest () { int id = save(); log.info("save {}" , getById(id)); boolean update = update(id, 202L ); log.info("update {}, {}" , update, getById(id)); boolean delete = delete(id); log.info("delete {}, {}" , delete, getById(id)); } private int save () { MoneyPo po = new MoneyPo(); po.setName("一灰灰blog" ); po.setMoney(101L ); po.setIsDeleted(0 ); moneyMapper.save(po); return po.getId(); } private boolean update (int id, long newMoney) { int ans = moneyMapper.update(id, newMoney); return ans > 0 ; } private boolean delete (int id) { return moneyMapper.delete(id) > 0 ; } private MoneyPo getById (int id) { return moneyMapper.getById(id); } }
2. 注册方式 注意,上面写完之后,若不通过下面的几种方式注册Mapper接口,项目启动会失败,提示找不到MoneyMapper对应的bean
1 Field moneyMapper in com.git.hui.boot.mybatis.service.MoneyService required a bean of type 'com.git.hui.boot.mybatis.mapper.MoneyMapper' that could not be found.
2.1 @MapperScan注册方式 在配置类or启动类上,添加@MapperScan注解来指定Mapper接口的包路径,从而实现Mapper接口的注册
1 2 3 4 5 6 7 8 9 10 11 12 @MapperScan (basePackages = "com.git.hui.boot.mybatis.mapper" )@SpringBootApplication public class Application { public Application (MoneyService moneyService) { moneyService.basicTest(); } public static void main (String[] args) { SpringApplication.run(Application.class); } }
执行之后输出结果如下
1 2 3 2021-07-06 19:12:57.984 INFO 1876 --- [ main] c.g.h.boot.mybatis.service.MoneyService : save MoneyPo(id=557, name=一灰灰blog, money=101, isDeleted=0, createAt=2021-07-06 19:12:57.0, updateAt=2021-07-06 19:12:57.0) 2021-07-06 19:12:58.011 INFO 1876 --- [ main] c.g.h.boot.mybatis.service.MoneyService : update true, MoneyPo(id=557, name=一灰灰blog, money=202, isDeleted=0, createAt=2021-07-06 19:12:57.0, updateAt=2021-07-06 19:12:57.0) 2021-07-06 19:12:58.039 INFO 1876 --- [ main] c.g.h.boot.mybatis.service.MoneyService : delete true, null
注意:
basePackages: 传入Mapper的包路径,数组,可以传入多个
包路径支持正则,如com.git.hui.boot.*.mapper
上面这种方式,可以避免让我们所有的mapper都放在一个包路径下,从而导致阅读不友好
2.2 @Mapper 注册方式 前面的@MapperScan指定mapper的包路径,这个注解则直接放在Mapper接口上
1 2 3 4 @Mapper public interface MoneyMapper {... }
测试输出省略…
使用MapperScannerConfigurer来实现mapper接口注册,在很久以前,还是使用Spring的xml进行bean的声明的时候,mybatis的mapper就是这么玩的
1 2 3 4 <bean class ="org.mybatis.spring.mapper.MapperScannerConfigurer" > <property name ="basePackage" value ="xxx" /> <property name ="sqlSessionFactoryBeanName" value ="sqlSessionFactory" /> </bean >
对应的java代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 @Configuration public class AutoConfig { @Bean (name = "sqlSessionFactory" ) public SqlSessionFactory sqlSessionFactory (DataSource dataSource) throws Exception { SqlSessionFactoryBean bean = new SqlSessionFactoryBean(); bean.setDataSource(dataSource); bean.setMapperLocations( new PathMatchingResourcePatternResolver().getResources("classpath*:mapping/*.xml" )); return bean.getObject(); } @Bean ("sqlSessionTemplate" ) public SqlSessionTemplate sqlSessionTemplate (SqlSessionFactory storySqlSessionFactory) { return new SqlSessionTemplate(storySqlSessionFactory); } @Bean public MapperScannerConfigurer mapperScannerConfigurer () { MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer(); mapperScannerConfigurer.setBasePackage("com.git.hui.boot.mybatis.mapper" ); mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactory" ); mapperScannerConfigurer.setSqlSessionTemplateBeanName("sqlSessionTemplate" ); return mapperScannerConfigurer; } }
测试输出省略
3. 小结 本文主要介绍Mybatis中Mapper接口的三种注册方式,其中常见的两种注解方式
@MapperScan: 指定Mapper接口的包路径
@Mapper: 放在mapper接口上
MapperScannerConfigurer: 编程方式注册
那么疑问来了,为啥要介绍这三种方式,我们实际的业务开发中,前面两个基本上就满足了;什么场景会用到第三种方式?
如写通用的Mapper(类似Mybatis-Plus中的BaseMapper)
如一个Mapper,多数据源的场景(如主从库,冷热库,db的操作mapper一致,但是底层的数据源不同)
本文到此结束,关于上面两个场景的实例case,后面有空再补上,我是一灰灰,有缘再见(欢迎关注长草的公众号一灰灰blog)
III. 不能错过的源码和相关知识点 0. 项目
1. 一灰灰Blog 尽信书则不如,以上内容,纯属一家之言,因个人能力有限,难免有疏漏和错误之处,如发现bug或者有更好的建议,欢迎批评指正,不吝感激
下面一灰灰的个人博客,记录所有学习和工作中的博文,欢迎大家前去逛逛
打赏
如果觉得我的文章对您有帮助,请随意打赏。
微信打赏
支付宝打赏