MybatisPlus条件构造器Wrapper分页查询自定义SQLService层接口代码生成器

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MybatisPlus条件构造器Wrapper分页查询自定义SQLService层接口代码生成器相关的知识,希望对你有一定的参考价值。

MybatisPlus基础篇

(目录)


1.条件构造器Wrapper

1.1 概述

​ 我们在实际操作数据库的时候会涉及到很多的条件。所以MP为我们提供了一个功能强大的条件构造器 Wrapper 。使用它可以让我们非常方便的构造条件。

​ 其继承体系如下:

​ 完整的AbstractWrapper方法可以参照:https://baomidou.com/guide/wrapper.html#abstractwrapper

介绍是用来干什么的。它的实现类有哪些

QueryWrapper,UpdateWrapper,【LambdaQueryWrapper】


1.2 常用AbstractWrapper方法

示例一

SQL语句如下:

SELECT 
	id,user_name,PASSWORD,NAME,age,address 
FROM 
	USER 
WHERE 
	age > 18 AND address = 狐山

如果用Wrapper写法如下:

    @Test
    public void testWrapper01()
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.gt("age",18);
        wrapper.eq("address","狐山");
        List<User> users = userMapper.selectList(wrapper);
        System.out.println(users);
    

示例二

SQL语句如下:

SELECT 
	id,user_name,PASSWORD,NAME,age,address 
FROM 
	USER 
WHERE 
	id IN(1,2,3) AND 
	age BETWEEN 12 AND 29 AND 
	address LIKE %山%

如果用Wrapper写法如下:

    @Test
    public void testWrapper02()
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.in("id",1,2,3);
        wrapper.between("age",12,29);
        wrapper.like("address","山");
        List<User> users = userMapper.selectList(wrapper);
        System.out.println(users);
    

示例三

SQL语句如下:

SELECT 
	id,user_name,PASSWORD,NAME,age,address 
FROM 
	USER 
WHERE 
	id IN(1,2,3) AND 
	age > 10 
ORDER BY 
	age DESC

如果用Wrapper写法如下:

    @Test
    public void testWrapper03()
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("id",1,2,3);
        queryWrapper.gt("age",10);
        queryWrapper.orderByDesc("age");
        List<User> users = userMapper.selectList(queryWrapper);
        System.out.println(users);
    

1.3 常用QueryWrapper方法

QueryWrapper的 select 可以设置要查询的列。

示例一

SQL语句如下:

SELECT 
	id,user_name
FROM 
	USER 

MP写法如下:

    @Test
    public void testSelect01()
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("id","user_name");
        List<User> users = userMapper.selectList(queryWrapper);
        System.out.println(users);
    

示例二

方法的第一个参数为实体类的字节码对象,第二个参数为Predicate类型,可以使用lambda的写法,过滤要查询的字段 (主键除外) 。

SQL语句如下:

SELECT 
	id,user_name
FROM 
	USER 

MP写法如下:

    @Test
    public void testSelect02()
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.select(User.class, new Predicate<TableFieldInfo>() 
            @Override
            public boolean test(TableFieldInfo tableFieldInfo) 
                return "user_name".equals(tableFieldInfo.getColumn());
            
        );
        List<User> users = userMapper.selectList(queryWrapper);
        System.out.println(users);
    

示例三

方法第一个参数为Predicate类型,可以使用lambda的写法,过滤要查询的字段 (主键除外) 。

SQL语句如下:

SELECT 
	id,user_name,PASSWORD,NAME,age 
FROM 
	USER

就是不想查询address这列,其他列都查询了

MP写法如下:

    @Test
    public void testSelect03()
        QueryWrapper<User> queryWrapper = new QueryWrapper<>(new User());
        queryWrapper.select(new Predicate<TableFieldInfo>() 
            @Override
            public boolean test(TableFieldInfo tableFieldInfo) 
                return !"address".equals(tableFieldInfo.getColumn());
            
        );
        List<User> users = userMapper.selectList(queryWrapper);
        System.out.println(users);
    

1.4 常用UpdateWrapper方法

​ 我们前面在使用update方法时需要创建一个实体类对象传入,用来指定要更新的列及对应的值。但是如果需要更新的列比较少时,创建这么一个对象显的有点麻烦和复杂。

​ 我们可以使用UpdateWrapper的set方法来设置要更新的列及其值。同时这种方式也可以使用Wrapper去指定更复杂的更新条件。

示例

SQL语句如下:

UPDATE 
	USER
SET 
	age = 99
where 
	id > 1

​ 我们想把id大于1的用户的年龄修改为99,则可以使用如下写法:

    @Test
    public void testUpdateWrapper()
        UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
        updateWrapper.gt("id",1);
        updateWrapper.set("age",99);
        userMapper.update(null,updateWrapper);
    

1.5 Lambda条件构造器

​ 我们前面在使用条件构造器时列名都是用字符串的形式去指定。这种方式无法在编译期确定列名的合法性。

​ 所以MP提供了一个Lambda条件构造器可以让我们直接以实体类的方法引用的形式来指定列名。这样就可以弥补上述缺陷。

示例

要执行的查询对应的SQL如下

SELECT 
	id,user_name,PASSWORD,NAME,age,address 
FROM 
	USER 
WHERE 
	age > 18 AND address = 狐山

如果使用之前的条件构造器写法如下

    @Test
    public void testLambdaWrapper()
        QueryWrapper<User> queryWrapper = new QueryWrapper();
        queryWrapper.gt("age",18);
        queryWrapper.eq("address","狐山");
        List<User> users = userMapper.selectList(queryWrapper);
    

如果使用Lambda条件构造器写法如下

    @Test
    public void testLambdaWrapper2()
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.gt(User::getAge,18);
        queryWrapper.eq(User::getAddress,"狐山");
        List<User> users = userMapper.selectList(queryWrapper);
    

2.自定义SQL

​ 虽然MP为我们提供了很多常用的方法,并且也提供了条件构造器。但是如果真的遇到了复制的SQL时,我们还是需要自己去定义方法,自己去写对应的SQL,这样SQL也更有利于后期维护。

​ 因为MP是对mybatis做了增强,所以还是支持之前Mybatis的方式去自定义方法。

​ 同时也支持在使用Mybatis的自定义方法时使用MP的条件构造器帮助我们进行条件构造。

​ 接下去我们分别来讲讲。

2.0 准备工作

①准备数据

CREATE TABLE `orders` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `price` int(11) DEFAULT NULL COMMENT 价格,
  `remark` varchar(100) DEFAULT NULL COMMENT 备注,
  `user_id` int(11) DEFAULT NULL COMMENT 用户id,
  `update_time` timestamp NULL DEFAULT NULL COMMENT 更新时间,
  `create_time` timestamp NULL DEFAULT NULL COMMENT 创建时间,
  `version` int(11) DEFAULT 1 COMMENT 版本,
  `del_flag` int(1) DEFAULT 0 COMMENT 逻辑删除标识,0-未删除,1-已删除,
  `create_by` varchar(100) DEFAULT NULL COMMENT 创建人,
  `update_by` varchar(100) DEFAULT NULL COMMENT 更新人,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;

/*Data for the table `orders` */

insert  into `orders`(`id`,`price`,`remark`,`user_id`,`update_time`,`create_time`,`version`,`del_flag`,`create_by`,`update_by`) values (1,2000,无,2,2021-08-24 21:02:43,2021-08-24 21:02:46,1,0,NULL,NULL),(2,3000,无,3,2021-08-24 21:03:32,2021-08-24 21:03:35,1,0,NULL,NULL),(3,4000,无,2,2021-08-24 21:03:39,2021-08-24 21:03:41,1,0,NULL,NULL);

②创建实体类

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Orders  

    private Long id;

    /**
     * 价格
     */
    private Integer price;

    /**
     * 备注
     */
    private String remark;

    /**
     * 用户id
     */
    private Integer userId;

    /**
     * 更新时间
     */
    private LocalDateTime updateTime;

    /**
     * 创建时间
     */
    private LocalDateTime createTime;

    /**
     * 版本
     */
    private Integer version;

    /**
     * 逻辑删除标识,0-未删除,1-已删除
     */
    private Integer delFlag;



2.1 Mybatis方式

①定义方法

​ 在Mapper接口中定义方法

public interface UserMapper extends BaseMapper<User> 

    User findMyUser(Long id);


②创建xml

​ 先配置xml文件的存放目录

mybatis-plus:
  mapper-locations: classpath*:/mapper/**/*.xml

​ 创建对应的xml映射文件

③在xml映射文件中编写SQL

​ 创建对应的标签,编写对应的SQL语句

<?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.sangeng.mapper.UserMapper">

    <select id="findMyUser" resultType="com.sangeng.domian.User">
       select * from user where id = #id 
    </select>
</mapper>

2.2 Mybatis方式结合条件构造器

​ 我们在使用上述方式自定义方法时。如果也希望我们的自定义方法能像MP自带方法一样使用条件构造器来进行条件构造的话只需要使用如下方式即可。

①方法定义中添加Warpper类型的参数

添加Warpper类型的参数,并且要注意给其指定参数名。

public interface UserMapper extends BaseMapper<User> 

    User findMyUserByWrapper(@Param(Constants.WRAPPER) Wrapper<User> wrapper);

②在SQL语句中获取Warpper拼接的SQL片段进行拼接。

    <select id="findMyUserByWrapper" resultType="com.sangeng.domian.User">
        select * from user $ew.customSqlSegment
    </select>

注意:不能使用#应该用$


3.分页查询

3.1 基本分页查询

①配置分页查询拦截器

@Configuration
public class PageConfig 

    /**
     * 3.4.0之前的版本
     * @return
     */
   /* @Bean
    public PaginationInterceptor paginationInterceptor()
        return  new PaginationInterceptor();
    */

    /**
     * 3.4.0之后版本
     * @return
     */
   @Bean
   public MybatisPlusInterceptor mybatisPlusInterceptor()
       MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
       mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
       return mybatisPlusInterceptor;
   

②进行分页查询

    @Test
    public void testPage()
        IPage<User> page = new Page<>();
        //设置每页条数
        page.setSize(2);
        //设置查询第几页
        page.setCurrent(1);
        userMapper.selectPage(page, null);
        System.out.println(page.getRecords());//获取当前页的数据
        System.out.println(page.getTotal());//获取总记录数
        System.out.println(page.getCurrent());//当前页码
    

3.2 多表分页查询

​ 如果需要在多表查询时进行分页查询的话,就可以在mapper接口中自定义方法,然后让方法接收Page对象。

示例

需求

​ 我们需要去查询Orders表,并且要求查询的时候除了要获取到Orders表中的字段,还要获取到每个订单的下单用户的用户名。

准备工作
SQL准备
SELECT 
	o.*,u.`user_name`
FROM 
	USER u,orders o
WHERE 
	o.`user_id` = u.`id`
实体类修改

增加一个userName属性

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Orders  
	//省略无关代码
    private String userName;

实现

①定义接口,定义方法

方法第一个测试定义成Page类型

public interface OrdersMapper extends BaseMapper<Orders> 

    IPage<Orders> findAllOrders(Page<Orders> page);

在xml中不需要关心分页操作,MP会帮我们完成。

<?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.sangeng.mapper.OrdersMapper">
    <select id="findAllOrders" resultType="com.sangeng.domian.Orders">
        SELECT
            o.*,u.`user_name`
        FROM
            USER u,orders o
        WHERE
            o.`user_id` = u.`id`
    </select>
</mapper>

然后调用方法测试即可

    @Autowired
    private OrdersMapper ordersMapper;
    @Test
    public void testOrdersPage()
        Page<Orders> page = new Page<>();
        //设置每页大小
        page.setSize(2);
        //设置当前页码
        page.setCurrent(2);
        ordersMapper.findAllOrders(page);
        System.out.println(page.getRecords());
        System.out.println(page.getTotal());
    

4.Service 层接口

​ MP也为我们提供了Service层的实现。我们只需要编写一个接口,继承IService,并创建一个接口实现类继承ServiceImpl,即可使用。

​ 相比于Mapper接口,Service层主要是支持了更多批量操作的方法。

4.1 基本使用

4.1.1 改造前

定义接口

public interface UserService 
    List<User> list();


定义实现类

@Service
public class UserServiceImpl implements UserService 
    @Autowired
    private UserMapper userMapper;

    @Override
    public List<User> list() 
        return userMapper.selectList(null);
    


4.1.2 改造后

接口

public interface UserService extends IService<User> 


实现类

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper,User> implements UserService 
	


测试

    @Autowired
    private UserService userService;


    @Test
    public void testSeervice()
        List<User> list = userService.list();
        System.out.println(list);
    

4.2自定义方法

public interface UserService extends IService<User> 


    User test();


@Service
public class UserServiceImpl extends ServiceImpl<UserMapper,User> implements UserService 

    @Autowired
    private OrdersMapper ordersMapper;

    @Override
    public User test() 
        UserMapper userMapper = getBaseMapper();
        List<Orders> orders = ordersMapper.selectList(null);
        User user = userMapper.selectById(3);
        //查询用户对于的订单
        QueryWrapper<Orders> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id",3);
        List<Orders> ordersList = ordersMapper.selectList(wrapper);
        return user;
    


5.代码生成器

当有一个新的业务实现时,对接口的功能实现上,我们通常来说需要构建下面的信息:

​ 从上面的各类代码中可以放下,代码都是模板性的,如果用手工copy、修改的方式来实现,太烦人也没效率,而这时就是代码生成器小展身手的时候,使用代码生成器生成模板性的代码,减少手工操作的繁琐,集中精力在业务开发上,提升开发效率。


①添加依赖

        <!--mybatisplus代码生成器-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.4.1</version>
        </dependency>
        <!--模板引擎-->
        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
        </dependency>

②生成

​ 修改相应配置后执行以下代码即可


public class GeneratorTest 
	@Test
	public void generate() 
		AutoGenerator generator = new AutoGenerator();

		// 全局配置
		GlobalConfig config = new GlobalConfig();
		String projectPath = System.getProperty("user.dir");
		// 设置输出到的目录
		config.setOutputDir(projectPath + "/src/main/java");
		config.setAuthor("sangeng");
		// 生成结束后是否打开文件夹
		config.setOpen(false);

		// 全局配置添加到 generator 上
		generator.setGlobalConfig(config);

		// 数据源配置
		DataSourceConfig dataSourceConfig = new DataSourceConfig();
		dataSourceConfig.setUrl("jdbc:mysql://localhost:3306/mp_db?characterEncoding=utf-8&serverTimezone=UTC");
		dataSourceConfig.setDriverName("com.mysql.cj.jdbc.Driver");
		dataSourceConfig.setUsername("root");
		dataSourceConfig.setPassword("root");

		// 数据源配置添加到 generator
		generator.setDataSource(dataSourceConfig);

		// 包配置, 生成的代码放在哪个包下
		PackageConfig packageConfig = new PackageConfig();
		packageConfig.setParent("com.sangeng.mp.generator");

		// 包配置添加到 generator
		generator.setPackageInfo(packageConfig);

		// 策略配置
		StrategyConfig strategyConfig = new StrategyConfig();
		// 下划线驼峰命名转换
		strategyConfig.setNaming(NamingStrategy.underline_to_camel);
		strategyConfig.setColumnNaming(NamingStrategy.underline_to_camel);
		// 开启lombok
		strategyConfig.setEntityLombokModel(true);
		// 开启RestController
		strategyConfig.setRestControllerStyle(true);
		generator.setStrategy(strategyConfig);
		generator.setTemplateEngine(new FreemarkerTemplateEngine());

        // 开始生成
		generator.execute();
	


6.MybatisX 快速开发插件

MybatisX 是一款基于 IDEA 的快速开发插件,为效率而生。

安装方法:打开 IDEA,进入 File -> Settings -> Plugins -> Browse Repositories,输入 mybatisx 搜索并安装。

功能:

  • Java 与 XML 调回跳转
  • Mapper 方法自动生成 XML


以上是关于MybatisPlus条件构造器Wrapper分页查询自定义SQLService层接口代码生成器的主要内容,如果未能解决你的问题,请参考以下文章

MybatisPlus条件构造器wrapper方法的使用

MybatisPlus条件构造器wrapper方法的使用

MybatisPlus 学习条件构造器和常用接口

第121天学习打卡(MyBatisPlus CRUD扩展之查询操作 分页查询 删除操作 逻辑删除 条件构造器 自动生成器 )

MybatisPlus实现基本CURD&逻辑删除&代码生成(对标Django系列学习二)

MyBatis-Plus——使用查询构造器Wrapper & 简单分页操作