Mybatis Plus使用,条件拼装、自定义分页、多数据源

MyBatis-Plus(简称 MP)是一个MyBatis的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。文档地址:https://mybatis.plus/guide/

一、spring-boot整合mybatis-plus (配置文档地址:https://mybatis.plus/guide/config.html,包含spring中的配置)

创建springboot项目,引入mybatis-plus的starter

<!-- https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-boot-starter -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.4.2</version>
</dependency>

<!--mysql数据库驱动-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.16</version>
</dependency>

springboot配置文件配置数据源

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
    driverClassName: com.mysql.cj.jdbc.Driver
    username: root
    password: root

sql建表语句

CREATE TABLE `user` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  `name` varchar(30) DEFAULT NULL COMMENT '姓名',
  `age` int(11) DEFAULT NULL COMMENT '年龄',
  `u_email` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '邮箱',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1364106346254659587 DEFAULT CHARSET=utf8;

INSERT INTO `user` (`id`, `name`, `age`, `u_email`) VALUES ('1', 'name2', '13', '[email protected]');
INSERT INTO `user` (`id`, `name`, `age`, `u_email`) VALUES ('2', 'Jack', '28', '[email protected]');
INSERT INTO `user` (`id`, `name`, `age`, `u_email`) VALUES ('3', 'Tom', '18', '[email protected]');
INSERT INTO `user` (`id`, `name`, `age`, `u_email`) VALUES ('4', 'Sandy', '31', '[email protected]');
INSERT INTO `user` (`id`, `name`, `age`, `u_email`) VALUES ('5', 'Billie', '24', '[email protected]');
INSERT INTO `user` (`id`, `name`, `age`, `u_email`) VALUES ('6', 'plus', '19', '[email protected]');

创建Mapper继承BaseMapper

/**
 * BaseMapper里mybatis-plus封装了增删改方法
 */
public interface UserMapper extends BaseMapper<User> {
    
    
}

创建配置类,添加扫包注解,扫描mapper包

@Configuration
@MapperScan("com.example.demo.mapper")
public class MyBatisPlusConfig {
    
    
}

编写测试类,测试查询:

@RunWith(SpringRunner.class)
@SpringBootTest
class DemoApplicationTests {
    
    

    @Resource
    private UserMapper userMapper;

    @Test
    public void list() {
    
    
        List<User> list = userMapper.selectList(null);
        list.forEach(user -> System.out.println(user.toString()));
    }

}

二、条件构造器AbstractWrapper

AbstractWrapper(抽象类)是QueryWrapper(查询)和UpdateWrapper(修改)的父类。QueryWrapper和UpdateWrapper条件拼接的方法一致。

QueryWrapper

@Test
public void query(){
    
    
    QueryWrapper<User> queryWrapper = new QueryWrapper<User>();
    Map<String,String> map = new HashMap<>();
    map.put("name","plus");
    map.put("age","18");
    map.put("u_email","[email protected]");
    //allEq全部相等 传入map,key为数据库字段,val为对应的值 sql : name = 'plus' and age = '18' and u_email = '[email protected]'
    //queryWrapper.allEq(map);
    //eq单独字段相等,可以用eq一直拼接字段条件 sql : name = 'Tom' and age  = 18
    //queryWrapper.eq("name","Tom").eq("age","18");
    //ne不等于,无限ne sql : name != 'Tom'
    //queryWrapper.ne("name","Tom");
    //gt大于 sql : age > 18
    //queryWrapper.gt("age",18);
    //大于等于 sql : age >= 18
    //queryWrapper.ge("age",18);
    //lt小于 sql : age < 18
    //queryWrapper.lt("age",18);
    //le小于等于sql :age <= 18
    //queryWrapper.le("age",18);
    //between在18到28之间  18 <= age <= 28
    //queryWrapper.between("age",18,28);
    //notBetween (age < 18 or age > 28)
    //queryWrapper.notBetween("age",18,28);
    //模糊匹配 sql: name like '%lus%'
    //queryWrapper.like("name","lus");
    // name not like '%lus%'
    //queryWrapper.notLike("name","lus");
    //左匹配 sql : name like '%lus'
    //queryWrapper.likeLeft("name","lus");
    //右匹配 sql name like 'plu%'
    //queryWrapper.likeRight("name","plu");
    //sql : name is null
    //queryWrapper.isNull("name");
    //sql : name is not null
    //queryWrapper.isNotNull("name");
    //in 查询 : id in (1,2,3)
    //queryWrapper.in("id", Arrays.asList(1,2,3));
    //not in查询 sql: id not in (1,2,3)
    //queryWrapper.notIn("id", Arrays.asList(1,2,3));
    //条件在查询的数据中,id in (select id from user where id < 3)
    //queryWrapper.inSql("id","select id from user where id < 3");
    // id not in (select id from user where id < 3)
    //queryWrapper.notInSql("id","select id from user where id < 3");
    //group by age
    //queryWrapper.groupBy("age");
    // order by age asc
    //queryWrapper.orderByAsc("age");
    // order by age desc
    //queryWrapper.orderByDesc("age");
    //select 指定查询字段,having sum(age) > 18
    //queryWrapper.select("name").groupBy("name").having("sum(age) > 18");
    //func支持传入方法
   /* queryWrapper.func(w -> {
        if(false){
            w.eq("name","plus");
        }else {
            w.eq("name","Tom");
        }
    });*/
    // 相当于 name = 'plus' or (name = 'Tom' and age = '18')(默认都为and)
    //queryWrapper.eq("name","plus").or().eq("name","Tom").eq("age","18");
    //相当于 age = 18 or (name = 'plus' or name = 'Tom')
 /*   queryWrapper.eq("age",18).or(i -> {
        i.eq("name","plus").or().eq("name","Tom");
    });*/
    //相当于 id = 3 and (name = 'Tom' and age = '18') , and方法相当于里面小括号外加and
    /*queryWrapper.eq("id",3).and(i->{
        i.eq("name","Tom").eq("age",18);
    });*/
  /*  //正常嵌套 (name = 'plus' and age = '19')
    queryWrapper.nested(i->{
        i.eq("name","plus").eq("age",19);
    });*/
   //用于数据库函数 sql : where LEFT(name,2) = 'To'
    //queryWrapper.apply("LEFT(name,2) = 'To'");
    //直接拼接sql后面
    queryWrapper.last("limit 1");
    List<User> list = userMapper.selectList(queryWrapper);
    list.forEach(System.out::println);
}

UpdateWrapper

@Test
public void update(){
    
    
    //修改,不仅会修改实体的内容,也会修改set方法里的内容,字段值设为null,set("u_email",null)
    User user = new User();
    user.setName("name");
    user.setAge(13);
    UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
    updateWrapper.set("u_email","[email protected]");
    updateWrapper.setSql("name = 'name2'");
    updateWrapper.eq("id",1);
    //userMapper.update(user,updateWrapper);
    userMapper.update(null,updateWrapper);
}

三、自定义sql

注解方式,直接定义方法,注解方式查询:

public interface UserMapper extends BaseMapper<User> {
    
    

    @Select("select * from user where id = #{id}")
    User findById(@Param("id")String id);
    
    /**
     * 映射xml文件方法
     * @param name
     * @return
     */
    User findUserByName(String name);

}

xml文件方式:

定义xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.mapper.UserMapper">

    <resultMap id="BaseResultMap" type="com.example.demo.core.User">
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <result property="age" column="age"/>
        <result property="uEmail" column="u_email"/>
    </resultMap>

    <select id="findUserByName" parameterType="java.lang.String" resultMap="BaseResultMap">
        select * from user where `name` = #{name}
    </select>

</mapper>

mybatis-plus配置:

# 如果xml文件在classpath下mapper文件夹下不配置也可以,如果不是就需要配上xml文件路径
mybatis-plus:
  mapper-locations: classpath*:mapper/*Mapper.xml

查询测试:

@Test
public void findById(){
    
    
    //注解方式
    User user = userMapper.findById("1");
    System.out.println(user.toString());
}

@Test
public void findByName(){
    
    
    //xml文件方式
    User user = userMapper.findUserByName("plus");
    System.out.println(user.toString());
}

三、分页

添加分页插件,注册成bean

@Configuration
@MapperScan("com.example.demo.mapper")
public class MyBatisPlusConfig {
    
    

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

}

mapper接口和xml定义分页查询方法(普通的查询,mybatis-plus自动添加分页,按分页规则写查询方法)

//UserMapper的分页方法
IPage<User> findUserPage(Page<User> userPage);
 <!--UserMapper.xml中的分页方法-->
<select id="findUserPage" resultMap="BaseResultMap">
    select * from `user`
</select>

分页测试代码

@Test
public void findPage(){
    
    
    int pageNo = 2; //页码
    int pageSize = 2; //每页数据条数
    Page<User> page = new Page<>(pageNo,pageSize);
    IPage<User> iPage = userMapper.findUserPage(page);
    System.out.println("数据总条数:" + iPage.getTotal());
    System.out.println("总页数:" + iPage.getPages());
    iPage.getRecords().forEach(System.out::println);
}

自定义分页类,带入对象信息查询:

/**
 * 创建Pager类,继承Page类,自定义condition字段接收查询条件对象
 */
public class Pager<T> extends Page<T> {
    
    

    /**
     * 条件参数
     */
    private T condition;

    public T getCondition() {
    
    
        return condition;
    }

    public void setCondition(T condition) {
    
    
        this.condition = condition;
    }

    public Pager(int pageNo, int pageSize){
    
    
        super(pageNo,pageSize);
    }

}

UserMapper和UserMapper.xml

/**
 * 自定义Pager,传入查询条件(实体)
 * @param pager
 * @return
 */
IPage<User> findPageByCondition(Pager<User> pager);
<select id="findPageByCondition" resultMap="BaseResultMap" parameterType="com.example.demo.page.Pager">
    select * from `user`
    <where>
        <if test="condition != null">
          <if test="condition.name != null and condition.name != ''">
              and `name` = #{condition.name}
          </if>
          <if test="condition.age != null">
              and age = #{condition.age}
          </if>
        </if>
    </where>
</select>

查询测试:

@Test
public void findPageByCondition(){
    
    
    //查询条件对象
    User user = new User();
    //user.setName("plus");
    user.setAge(19);
    int pageNo = 1; //页码
    int pageSize = 2; //每页数据条数
    Pager<User> pager = new Pager<>(pageNo,pageSize);
    pager.setCondition(user);
    IPage<User> iPage = userMapper.findPageByCondition(pager);
    System.out.println("数据总条数:" + iPage.getTotal());
    System.out.println("总页数:" + iPage.getPages());
    iPage.getRecords().forEach(System.out::println);
}

四、多数据源

1、引入dynamic-datasource-spring-boot-starter

dynamic-datasource-spring-boot-starter 是一个基于springboot的快速集成多数据源的启动器。

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
    <version>3.3.1</version>
</dependency>

2、配置文件

spring:
  datasource:
    dynamic:
      primary: master #默认数据源或数据组,默认为master
      strict: false #设置严格模式,默认false。启动未匹配到默认数据源会报错不会使用默认数据源
      datasource:
        master:
          url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
          username: root
          password: root
          driverClassName: com.mysql.cj.jdbc.Driver
        master_1:
          url: jdbc:mysql://190.168.65.1:3306/test?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
          username: root
          password: root
          driverClassName: com.mysql.cj.jdbc.Driver

3、使用 @DS注解切换数据源。方法上的注解优先于类上的注解

//可用在类、接口和方法上
@Target({
    
    ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DS {
    
    
    String value();
}
@Service
@DS("master_1")
public class UserServiceImpl implements UserService {
    
    

    @Resource
    private UserMapper userMapper;

    @DS("master") //就近原则,方法上的注解优先于类上的注解
    @Override
    public void insertUser(User user) {
    
    
        userMapper.insert(user);
    }
}

4、添加测试,修改数据源

@Test
public void insert(){
    
    
    User user = new User();
    user.setName("数据源");
    user.setAge(20);
    user.setUEmail("[email protected]");
    userService.insertUser(user);
}

猜你喜欢

转载自blog.csdn.net/zhaoqingquanajax/article/details/114107471