MyBatis-Plus
简介 | MyBatis-Plus (baomidou.com)
MyBatis-plus +MyBatis
简单的整合mybatis里操作数据库的方法
- 将对应的Mapper对象继承BaseMapper(使其能调用BaseMpper里的操作方法)
- 使用MyBatis-plus 的方式产生SqlSessionFactory
- 最后调用BaseMapper的方法操作数据库
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| @Test public void testUserList() throws Exception { String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new MybatisSqlSessionFactoryBuilder().build(inputStream); SqlSession sqlSession = sqlSessionFactory.openSession(); UserMapper userMapper = sqlSession.getMapper(UserMapper.class); List<User> list = userMapper.selectList(null); for (User user : list) { System.out.println(user); } }
|
子项目都继承了父项目来引用mybatis-plus
1 2 3 4 5
| <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus</artifactId> <version>3.1.1</version> </dependency>
|
MyBatis-plus +Spring
整合Spring+MyBatis-plus主要是解析数据源,将配置信息写在spring的配置文件中
pom文件中需要导入spring的mybatis-plus的配置
itcast-mybatis-plus-spring
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| <context:property-placeholder location="classpath:*.properties"/>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close"> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> <property name="driverClassName" value="${jdbc.driver}"/> <property name="maxActive" value="10"/> <property name="minIdle" value="5"/> </bean>
<bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> </bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="cn.itcast.mp.simple.mapper"/> </bean>
|
spring也是同样引用mybatis-plus
1 2 3 4 5
| <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus</artifactId> <version>3.1.1</version> </dependency>
|
Springboot+Mybatis-plus
需要在application.yml的配置文件中配置数据源,而其他的映射或者扫描器springboot已经注解封装完成不需要自己重复写
1 2 3 4 5 6 7
| spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/test username: root password: nian0209
|
pom文件里springboot项目需要引用父类文件
spring-boot-starter-parent 里面封装了springboot项目的启动对应的配置文件
1 2 3 4 5 6
| <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.6.7</version> <relativePath/> </parent>
|
引用mybatis-plus需要引用springboot对应的mybatis-plus配置信息
1 2 3 4 5
| <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.1</version> </dependency>
|
BaseMapper提供的CRUD
@TableField
在MP中通过@TableField注解可以指定字段的一些属性,常常解决的问题有2个:
1、对象中的属性名和字段名不一致的问题(非驼峰)
2、对象中的属性字段在表中不存在的问题
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| @TableName("tb_user") public class User { @TableId(type = IdType.AUTO) private Long id; private String userName; @TableField(select = false) private String password; private String name; private Integer age; @TableField(value = "email") private String email; @TableField(exist = false) private String address; }
|
更新操作
在MP中,更新操作有2种,一种是根据id更新,另一种是根据条件更新
根据id更新
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| @RunWith(SpringRunner.class) @SpringBootTest public class UserMapperTest { @Autowired private UserMapper userMapper;
@Test public void testUpdateById() { User user = new User(); user.setId(6L); user.setAge(21); this.userMapper.updateById(user); } }
|
根据条件更新
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
|
@Test public void testUpdate() { User user = new User(); user.setAge(22); QueryWrapper<User> wrapper = new QueryWrapper<>(); wrapper.eq("id", 6); int result = this.userMapper.update(user, wrapper); System.out.println("result = " + result); }
@Test public void testUpdate() { UpdateWrapper<User> wrapper = new UpdateWrapper<>(); wrapper.eq("id", 6).set("age", 23); int result = this.userMapper.update(null, wrapper); System.out.println("result = " + result); }
|
删除操作
根据id删除deleteById
1 2 3 4 5 6
| @Test public void testDeleteById() { int result = this.userMapper.deleteById(6L); System.out.println("result = " + result); }
|
根据条件删除deleteByMap
1 2 3 4 5 6 7 8 9
| @Test public void testDeleteByMap() { Map<String, Object> columnMap = new HashMap<>(); columnMap.put("age",20); columnMap.put("name","张三"); int result = this.userMapper.deleteByMap(columnMap); System.out.println("result = " + result); }
|
delete
更加情况分为两种不同参数的删除
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| @Test public void testDeleteByMap() { QueryWrapper<User> wrapper = new QueryWrapper<User>(); wrapper.eq("user_name","caocao").eq("password","123"); User user = new User(); user.setUserName("caocao"); user,setPassword("123"); int result = this.userMapper.delete(wrapper); System.out.println("result = " + result); }
|
deleyeBetchIds
批量删除 传入的参数需要是一个数组类型
1 2 3 4 5 6
| @Test public void testDeleteByMap() { int result = this.userMapper.deleteBatchIds(Arrays.asList(1L,10L,20L)); System.out.println("result = " + result); }
|
查询操作
根据id查询selectById
1 2 3 4 5 6
| @Test public void testSelectById() { User user = this.userMapper.selectById(2L); System.out.println("result = " + user); }
|
根据数组集合查询数据
1 2 3 4 5 6 7 8
| @Test public void testSelectBatchIds() { List<User> users = this.userMapper.selectBatchIds(Arrays.asList(2L, 3L, 10L)); for (User user : users) { System.out.println(user); } }
|
根据条件查询一条数据selectOne
1 2 3 4 5 6 7 8
| @Test public void testSelectOne() { QueryWrapper<User> wrapper = new QueryWrapper<User>(); wrapper.eq("name", "李四"); User user = this.userMapper.selectOne(wrapper); System.out.println(user); }
|
根据条件查询总记录数
1 2 3 4 5 6 7 8
| @Test public void testSelectCount() { QueryWrapper<User> wrapper = new QueryWrapper<User>(); wrapper.gt("age", 23); Integer count = this.userMapper.selectCount(wrapper); System.out.println("count = " + count); }
|
分页查询selectPage
1 2 3 4 5 6 7
|
IPage<T> selectPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
|
需要进行分页必须写一个mybatis提供的分页插件
MybatisPlusInterceptor MybatisPlus的分页拦截器
MybatisPlus自带的分页插件
1 2 3 4 5 6 7 8 9
| @Configuration public class MPConfig { @Bean public MybatisPlusInterceptor mybatisPlusInterceptor(){ MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor()); return interceptor; } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| @Test public void testSelectPage() { QueryWrapper<User> wrapper = new QueryWrapper<User>(); wrapper.gt("age", 20); Page<User> page = new Page<>(1,1);
IPage<User> iPage = this.userMapper.selectPage(page, wrapper); System.out.println("数据总条数:" + iPage.getTotal()); System.out.println("总页数:" + iPage.getPages()); List<User> users = iPage.getRecords(); for (User user : users) { System.out.println("user = " + user); } }
|
QueryWrapper各参数
SQL注入原理
MP在启动后会将BaseMapper中的一系列的方法注册到meppedStatements中
在MP中,ISqlInjector负责SQL的注入工作,它是一个接口,AbstractSqlInjector是它的实现类
在AbstractSqlInjector中,主要是由inspectInject()方法进行注入的,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| @Override public void inspectInject(MapperBuilderAssistant builderAssistant, Class<?> mapperClass) { Class<?> modelClass = extractModelClass(mapperClass); if (modelClass != null) { String className = mapperClass.toString(); Set<String> mapperRegistryCache = GlobalConfigUtils.getMapperRegistryCache(builderAssistant.getConfiguration()); if (!mapperRegistryCache.contains(className)) { List<AbstractMethod> methodList = this.getMethodList(); if (CollectionUtils.isNotEmpty(methodList)) { TableInfo tableInfo = TableInfoHelper.initTableInfo(builderAssistant, modelClass); methodList.forEach(m -> m.inject(builderAssistant, mapperClass, modelClass, tableInfo)); } else { logger.debug(mapperClass.toString() + ", No effective injection method was found."); } mapperRegistryCache.add(className); } } }
|
在实现方法中, methodList.forEach(m -> m.inject(builderAssistant, mapperClass, modelClass,
tableInfo)); 是关键,循环遍历方法,进行注入。
1 2 3 4 5 6 7 8 9 10
|
public abstract MappedStatement injectMappedStatement(Class<?> mapperClass, Class<? > modelClass, TableInfo tableInfo);
|
后置内容再添加