Mybatis-Plus

MyBatis-Plus

简介 | MyBatis-Plus (baomidou.com)

MyBatis-plus +MyBatis

简单的整合mybatis里操作数据库的方法

  • 将对应的Mapper对象继承BaseMapper(使其能调用BaseMpper里的操作方法)
  • 使用MyBatis-plus 的方式产生SqlSessionFactory
  • 最后调用BaseMpper的方法操作数据库
@Test
public void testUserList() throws Exception {
    String resource = "mybatis-config.xml";
    InputStream inputStream = Resources.getResourceAsStream(resource);
    SqlSessionFactory sqlSessionFactory = new
            //这里使用的是MP中的MybatisSqlSessionFactoryBuilder
            MybatisSqlSessionFactoryBuilder().build(inputStream);
    SqlSession sqlSession = sqlSessionFactory.openSession();
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    // 可以调用BaseMapper中定义的方法
    List<User> list = userMapper.selectList(null);
    for (User user : list) {
        System.out.println(user);
    }
}

子项目都继承了父项目来引用mybatis-plus

<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

<!--扫描配置源    -->
<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>
<!--这里使用MP提供的sqlSessionFactory,完成了Spring与MP的整合-->
<bean id="sqlSessionFactory"
      class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
</bean>
<!--扫描mapper接口,使用的依然是Mybatis原生的扫描器-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <property name="basePackage" value="cn.itcast.mp.simple.mapper"/>
</bean>

spring也是同样引用mybatis-plus

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

Springboot+Mybatis-plus

需要在application.yml的配置文件中配置数据源,而其他的映射或者扫描器springboot已经注解封装完成不需要自己重复写

# 配置数据源
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项目的启动对应的配置文件

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.6.7</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>

引用mybatis-plus需要引用springboot对应的mybatis-plus配置信息

<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、对象中的属性字段在表中不存在的问题

@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更新
//根据id更新
@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); //更新的字段
        //根据id更新,更新不为null的字段
        this.userMapper.updateById(user);
    }
}
根据条件更新
//根据条件更新
//QueryWrapper进行更新 封装成对象 匹配条件进行更新
@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);
}


//UpdateWrapper进行更新 可以设置set---更新内容的操作
@Test
public void testUpdate() {
    //更新的条件以及字段
    UpdateWrapper<User> wrapper = new UpdateWrapper<>();
    wrapper.eq("id", 6).set("age", 23);
    //set的字段是数据库表字段
    //执行更新操作
    int result = this.userMapper.update(null, wrapper);
    System.out.println("result = " + result);
}
删除操作
根据id删除deleteById
    @Test
    public void testDeleteById() {
        //执行删除操作
        int result = this.userMapper.deleteById(6L);
        System.out.println("result = " + result);
    }
根据条件删除deleteByMap
@Test
public void testDeleteByMap() {
    Map<String, Object> columnMap = new HashMap<>();
    columnMap.put("age",20);
    columnMap.put("name","张三");
    //将columnMap中的元素设置为删除的条件,多个之间为and关系
    int result = this.userMapper.deleteByMap(columnMap);
    System.out.println("result = " + result);
}
delete

更加情况分为两种不同参数的删除

@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

批量删除 传入的参数需要是一个数组类型

@Test
public void testDeleteByMap() {
    //根据id集合批量删除
    int result = this.userMapper.deleteBatchIds(Arrays.asList(1L,10L,20L));
    System.out.println("result = " + result);
}
查询操作
根据id查询selectById
@Test
public void testSelectById() {
    //根据id查询数据
    User user = this.userMapper.selectById(2L);
    System.out.println("result = " + user);
}
根据数组集合查询数据
@Test
public void testSelectBatchIds() {
    //根据id集合批量查询
    List<User> users = this.userMapper.selectBatchIds(Arrays.asList(2L, 3L, 10L));
    for (User user : users) {
        System.out.println(user);
    }
}
根据条件查询一条数据selectOne
@Test
public void testSelectOne() {
    QueryWrapper<User> wrapper = new QueryWrapper<User>();
    wrapper.eq("name", "李四");
    //根据条件查询一条数据,如果结果超过一条会报错
    User user = this.userMapper.selectOne(wrapper);
    System.out.println(user);
}
根据条件查询总记录数
@Test
public void testSelectCount() {
    QueryWrapper<User> wrapper = new QueryWrapper<User>();
    wrapper.gt("age", 23); //年龄大于23岁
    //根据条件查询数据条数
    Integer count = this.userMapper.selectCount(wrapper);
    System.out.println("count = " + count);
}
分页查询selectPage
/**
 * 根据 entity 条件,查询全部记录(并翻页)
 *
 * @param page 分页查询条件(可以为 RowBounds.DEFAULT)
 * @param queryWrapper 实体对象封装操作类(可以为 null)
 */
IPage<T> selectPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

需要进行分页必须写一个mybatis提供的分页插件

MybatisPlusInterceptor MybatisPlus的分页拦截器

MybatisPlus自带的分页插件

@Configuration //标记为配置类
public class MPConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        return interceptor;
    }
}
    @Test
    public void testSelectPage() {
        
        //分页条件
        QueryWrapper<User> wrapper = new QueryWrapper<User>();
        wrapper.gt("age", 20); //年龄大于20岁
        
        Page<User> page = new Page<>(1,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是它的实现类

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oELt6XI7-1656752352796)(C:\Users\29769\AppData\Roaming\Typora\typora-user-images\image-20220702163307785.png)]

在AbstractSqlInjector中,主要是由inspectInject()方法进行注入的,如下:

@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)); 是关键,循环遍历方法,进行注入。

/**
 * 注入自定义 MappedStatement
 *
 * @param mapperClass mapper 接口
 * @param modelClass mapper 泛型
 * @param tableInfo 数据库表反射信息
 * @return MappedStatement
 */
public abstract MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?
        > modelClass, TableInfo tableInfo);

后置内容再添加

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

02XD

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

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

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

打赏作者

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

抵扣说明:

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

余额充值