栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

尚融宝项目之Mybatis-plus入门

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

尚融宝项目之Mybatis-plus入门

尚融宝


欢迎关注微信公众号,需要完整项目在公众号回复MP即可

MyBatis-Plus 入门 一、简介 1、官网

http://mp.baomidou.com

2、特点

MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。

3、支持数据库

mysql 、mariadb 、oracle 、db2 、h2 、hsql 、sqlite 、postgresql 、sqlserver 、presto 、Gauss 、Firebird

Phoenix 、clickhouse 、Sybase ASE 、 Oceanbase 、达梦数据库 、虚谷数据库 、人大金仓数据库 、南大通用数据库

4、框架结构

二、快速入门 1、创建数据库

创建数据库:mybatis_plus

CREATE TABLE user
(
	id BIGINT(20) NOT NULL COMMENT '主键ID',
	name VARCHAr(30) NULL DEFAULT NULL COMMENT '姓名',
	age INT(11) NULL DEFAULT NULL COMMENT '年龄',
	email VARCHAr(50) NULL DEFAULT NULL COMMENT '邮箱',
	PRIMARY KEY (id)
);
INSERT INTO user (id, name, age, email) VALUES
(1, 'Jone', 18, 'test1@baomidou.com'),
(2, 'Jack', 20, 'test2@baomidou.com'),
(3, 'Tom', 28, 'test3@baomidou.com'),
(4, 'Sandy', 21, 'test4@baomidou.com'),
(5, 'Billie', 24, 'test5@baomidou.com');
2、创建spring boot工程

3、引入依赖

    
        org.springframework.boot
        spring-boot-starter
    

    
        com.baomidou
        mybatis-plus-boot-starter
        3.4.1
    

    
        mysql
        mysql-connector-java
        runtime
    

    
        org.projectlombok
        lombok
        true
    

    
        org.springframework.boot
        spring-boot-starter-test
        test
        
            
                org.junit.vintage
                junit-vintage-engine
            
        
    

4、修改配置文件

在 application.properties 配置文件中添加 MySQL 数据库的相关配置 :

#mysql数据库连接
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus?serverTimezone=GMT%2B8&characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=123456

#mybatis日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

**注意:**如果定义了mysql驱动的依赖的版本为5,例如

5.1.47

则数据库连接配置为

#mysql数据库连接
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus?characterEncoding=utf-8&useSSL=true
spring.datasource.username=root
spring.datasource.password=123456

#mybatis日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
5、创建实体类

创建包 entity,编写实体类 User.java,并使用 lombok 简化实体类的编写

package com.atguigu.mybatisplus.entity;

@Data
public class User {
    private Long id;
    private String name;
    private Integer age;
    private String email;
}

编译结果

6、创建mapper接口

创建包 mapper ,编写Mapper接口:UserMapper.java

package com.atguigu.mybatisplus.mapper;

public interface UserMapper extends baseMapper {
    
}
7、启动类添加注解

在spring boot启动类中添加@MapperScan注解,扫描Mapper文件夹,只会扫描包中的接口,不会扫描类。

package com.atguigu.mybatisplus;

@SpringBootApplication
@MapperScan("com.atguigu.mybatisplus.mapper")
public class MybatisPlusApplication {
    ......
}
8、测试

使用测试类,进行功能测试

package com.atguigu.mybatisplus;

@SpringBootTest
class MybatisPlusApplicationTests {
    
    

	//@Autowired //默认按类型装配。是spring的注解
	@Resource //默认按名称装配,找不到与名称匹配的bean,则按照类型装配。是J2EE的注解
	private UserMapper userMapper;

	@Test
	void testSelectList() {
		//selectList()方法的参数:封装了查询条件
		//null:无任何查询条件
		List users = userMapper.selectList(null);
		users.forEach(System.out::println);
	}
}
sql日志输出
#mybatis日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
三、通用Mapper

MP中的基本CRUD在内置的baseMapper中都已得到了实现
使用已经创建好的测试类

//@Autowired //spring
@SpringBootTest//J2EE
class MybatisPlusApplicationTests {
    @Resource
	private UserMapper userMapper;
    
    @Test
	void testInsert(){
		User user = new User();
		user.setName("aojiaoge");
		user.setAge(18);
		user.setEmail("222226@qq.com");

		int result= userMapper.insert(user);
		System.out.println("结果:"+result);
		System.out.println(user.getId());
	}

	@Test
	void testSelect(){
		//id查询
		

		//id列表查询
		

		//条件查询
		Map map = new HashMap<>();
		map.put("name","Tom");
		List users = userMapper.selectByMap(map);
		users.forEach(System.out::println);
	}

	@Test
	void testUpdate(){
		User user = new User();
		user.setId(1l);
		user.setAge(100);
		
        //注意:update时生成的sql是动态的
		int i = userMapper.updateById(user);
		System.out.println("结果:"+i);
		User user1 = userMapper.selectById(1);
		System.out.println(user1);
	}

	@Test
	void testDelete(){
		Map objectObjectHashMap = new HashMap<>();
		objectObjectHashMap.put("name","aojiaoge");

		int i = userMapper.deleteByMap(objectObjectHashMap);
		System.out.println("结果:"+i);
	}
}
四、通用Service

MP中有一个接口IService和其实现类ServiceImpl,封装了常见的业务逻辑

1、创建Service接口

创建service包,创建UserService,继承IService

package com.atguigu.mybatisplus.service;

public interface UserService extends IService {
    
}
2、创建Service实现类

创建impl包,创建UserServiceImpl,继承ServiceImpl,实现UserService

package com.atguigu.mybatisplus.service.impl;

@Service
public class UserServiceImpl extends ServiceImpl implements UserService {

}
3、测试类
@SpringBootTest//J2EE
class MybatisPlusApplicationTests {
    @Resource
	private UserService userService;

	@Test
	void testCount(){
		int count = userService.count();
		System.out.println(count);
	}

	@Test
	void testSaveBach(){
		
		ArrayList users = new ArrayList<>();
		for (int i = 0; i < 6; i++) {
			User user = new User();
			user.setName("aojiaoge"+i);
			user.setAge(18+i);
			users.add(user);
		}
		userService.saveBatch(users);
	}
}
五、自定义Mapper

当通用Mapper无法满足我们的需求时,我们可以自定义基于Mapper接口的xml文件,并在xml文件中配置SQL语句

1、接口方法定义

在UserMapper接口中定义如下方法:

List selectAllByName(String name);
2、创建XML文件

在resources目录中创建mapper目录,创建UserMapper.xml






    
        uid as id,
        username as name,
        age,email,
        is_deleted as deleted,
        create_time as updateTime,
        update_time as updateTime
    

    
    
    SELECT  FROM user WHERe age > #{age}

(3)、测试

@Test
public void testSelectPageVo(){
    Page pageParam = new Page<>(1,5);
    userMapper.selectPageByPage(pageParam, 18);
    List users = pageParam.getRecords();
    users.forEach(System.out::println);
}
3、乐观锁 (1)、场景

一件商品,成本价是80元,售价是100元。老板先是通知小李,说你去把商品价格增加50元。小李正在玩游戏,耽搁了一个小时。正好一个小时后,老板觉得商品价格增加到150元,价格太高,可能会影响销量。又通知小王,你把商品价格降低30元。
此时,小李和小王同时操作商品后台系统。小李操作的时候,系统先取出商品价格100元;小王也在操作,取出的商品价格也是100元。小李将价格加了50元,并将100+50=150元存入了数据库;小王将商品减了30元,并将100-30=70元存入了数据库。是的,如果没有锁,小李的操作就完全被小王的覆盖了。
现在商品价格是70元,比成本价低10元。几分钟后,这个商品很快出售了1千多件商品,老板亏1万多。
接下来将我们演示这一过程:
*step1:*数据库中增加商品表

CREATE TABLE product
(
    id BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
    name VARCHAR(30) NULL DEFAULT NULL COMMENT '商品名称',
    price INT(11) DEFAULT 0 COMMENT '价格',
    version INT(11) DEFAULT 0 COMMENT '乐观锁版本号',
    PRIMARY KEY (id)
);

INSERT INTO product (id, NAME, price) VALUES (1, '笔记本', 100);

*step2:*创建实体类

package com.atguigu.mybatisplus.entity;
@Data
public class Product {
    private Long id;
    private String name;
    private Integer price;
    private Integer version;
}

step3:创建Mapper及对应的xml

public interface ProductMapper extends baseMapper {}



    

*step4:*测试

@Test
public void testConcurrentUpdate() {

    //1、小李
    Product p1 = productMapper.selectById(1L);

    //2、小王
    Product p2 = productMapper.selectById(1L);

    //3、小李将价格加了50元,存入了数据库
    p1.setPrice(p1.getPrice() + 50);
    int result1 = productMapper.updateById(p1);
    System.out.println("小李修改结果:" + result1);

    //4、小王将商品减了30元,存入了数据库
    p2.setPrice(p2.getPrice() - 30);
    int result2 = productMapper.updateById(p2);
    System.out.println("小王修改结果:" + result2);

    //最后的结果
    Product p3 = productMapper.selectById(1L);
    System.out.println("最后的结果:" + p3.getPrice());
}
(2)、乐观锁方案

数据库中添加version字段:取出记录时,获取当前version

SELECT id,`name`,price,`version` FROM product WHERe id=1

更新时,version + 1,如果where语句中的version版本不对,则更新失败

UPDATe product SET price=price+50, `version`=`version` + 1 WHERe id=1 AND `version`=1
(3)、乐观锁实现流程

*step1:*修改实体类
添加@version注解

@Version
private Integer version;

*step2:*添加乐观锁插件

@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
    MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
    //分页插件
    interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));//这里更换为我们使用的MySQL数据库
    //乐观锁插件
    interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());//乐观锁
    return interceptor;
}
(4)、优化流程

失败后重试

@SpringBootTest//J2EE
public class TestProduct {
    @Resource
    private ProductMapper productMapper;

    
    @Test
    void testMP(){
        //取数据
        Product xiaoli = productMapper.selectById(1l);

        Product xiaowang = productMapper.selectById(1l);

        //修改数据
        xiaoli.setPrice(xiaoli.getPrice() + 50);
        int i = productMapper.updateById(xiaoli);
        System.out.println("小李 "+i);
        if (i==0){
            //错误重试
            System.out.println("小李重新修改");
            //取数据
            Product xiaoli1 = productMapper.selectById(1l);
            xiaoli1.setPrice(xiaoli.getPrice() + 50);
            int i1 = productMapper.updateById(xiaoli);
            System.out.println("小李 "+i1);
        }

        xiaowang.setPrice(xiaowang.getPrice() - 30);
        int i1 = productMapper.updateById(xiaowang);
        System.out.println("小王 "+i1);
        if (i1==0){
            //错误重试
            System.out.println("小王重新修改");
            //取数据
            Product xiaowang1 = productMapper.selectById(1l);
            xiaowang1.setPrice(xiaowang1.getPrice() - 30);
            int i2 = productMapper.updateById(xiaowang1);
            System.out.println("小王 "+i2);
        }

        Product product = productMapper.selectById(1l);
        System.out.println(product);
    }
}
九、条件结构器 1、Wapper介绍 (1)、wapper家族

在MP中我们可以使用通用Mapper(baseMapper)实现基本查询,也可以使用自定义Mapper(自定义XML)来实现更高级的查询。当然你也可以结合条件构造器来方便的实现更多的高级查询。

Wrapper : 条件构造抽象类,最顶端父类
AbstractWrapper : 用于查询条件封装,生成 sql 的 where 条件
QueryWrapper : 查询条件封装
UpdateWrapper : Update 条件封装
AbstractLambdaWrapper : 使用Lambda 语法
LambdaQueryWrapper :用于Lambda语法使用的查询Wrapper
LambdaUpdateWrapper : Lambda 更新封装Wrapper

(2)、创建测试类
@SpringBootTest
public class TestWrapper {
    @Resource
    private UserMapper userMapper;

    private QueryWrapper userQueryWrapper = new QueryWrapper<>();
}
2、QueryWrapper (1)、例1:组装查询条件
@Test
void test1(){
     

     userQueryWrapper
           .like("username","a")
            .between("age",10,20)
             .isNotNull("email");

     List users = userMapper.selectList(userQueryWrapper);
     users.forEach(System.out::println);
}
(2)、例2:组装排序条件
@Test
    void test2(){
        

        userQueryWrapper
                .orderByDesc("age").orderByAsc("id");
        List users = userMapper.selectList(userQueryWrapper);
        users.forEach(System.out::println);

    }
(3)、例3:组装删除条件
@Test
void test3(){
     
     userQueryWrapper.isNull("email");
     int delete = userMapper.delete(userQueryWrapper);
     System.out.println(delete);
}
(4)、例4:条件的优先级
    @Test
    void test4(){
        
        userQueryWrapper
                .like("username","a")
                .and(i -> i.lt("age",18).or().isNull("email"));
        List users = userMapper.selectList(userQueryWrapper);
        users.forEach(System.out::println);

        User user = new User();
        user.setAge(18);
        user.setEmail("user@atguigu.com");
        int update = userMapper.update(user, userQueryWrapper);
        System.out.println(update);
    }
(5)、例5:组装select子句
    @Test
    void test5(){
        
        userQueryWrapper.select("username","age");
        List> maps = userMapper.selectMaps(userQueryWrapper);
        maps.forEach(System.out::println);
        
    }
(6)、例6:实现子查询
@Test
public void test6() {

    QueryWrapper queryWrapper = new QueryWrapper<>();
    queryWrapper.inSql("id", "select id from user where id <= 3");

    //selectObjs的使用场景:只返回一列
    List objects = userMapper.selectObjs(queryWrapper);//返回值是Object列表
    objects.forEach(System.out::println);
}
 

但是上面方式容易发生sql注入

@Test
void test6(){
    
    userQueryWrapper.in("uid",1,2,3);
    List objects = userMapper.selectObjs(userQueryWrapper);
    objects.forEach(System.out::println);
}
 
3、UpdateWrapper 
(1)、例7:需求同例4 
    @Test
    void test7(){
        
        UpdateWrapper userUpdateWrapper = new UpdateWrapper<>();
        

        userUpdateWrapper
                .set("age",18)
                .set("email","user@atguigu.com")
                .like("username","n")
                .and(i -> i.lt("age",18).or().isNull("email"));
        User user = new User();
        //这里必须要创建User对象,否则无法应用自动填充。如果没有自动填充,可以设置为null
        int update = userMapper.update(user, userUpdateWrapper);
        System.out.println(update);
    }
4、condition (1)、例8:动态组装查询条件
@Test
void test8(){
    
    //模拟用户输入
    String name = null;
    Integer ageStart = 10;
    Integer ageEnd = 20;

    
    userQueryWrapper
         .like(StringUtils.isNotBlank(name),"username",name)
         .ge(ageStart != null,"age",ageStart)
         .le(ageEnd != null,"age",ageEnd);
    List users = userMapper.selectList(userQueryWrapper);
    users.forEach(System.out::println);
}
5、LambdaXxxWrapper

(1)、例9:Query - 需求同例8

    @Test
    void test9(){
        

        LambdaQueryWrapper userLambdaQueryWrapper = new LambdaQueryWrapper<>();


        String name = null;
        Integer ageStart = 10;
        Integer ageEnd = 20;

        userLambdaQueryWrapper
                .like(StringUtils.isNotBlank(name),User::getName,name)
                .ge(ageStart != null,User::getAge,ageStart)
                .le(ageEnd != null,User::getAge,ageEnd);
        List users = userMapper.selectList(userLambdaQueryWrapper);
        users.forEach(System.out::println);
    }

(2)、例10:Update - 需求同例4

    @Test
    void test10(){
        

        LambdaQueryWrapper userLambdaQueryWrapper = new LambdaQueryWrapper<>();

        userLambdaQueryWrapper
                .like(User::getName,"a")
                .and(i -> i.lt(User::getAge,18).or().isNull(User::getEmail));
        List users = userMapper.selectList(userLambdaQueryWrapper);
        users.forEach(System.out::println);

        User user = new User();
        user.setAge(18);
        user.setEmail("user@atguigu.com");
        int update = userMapper.update(user, userLambdaQueryWrapper);
        System.out.println(update);
    }

userLambdaQueryWrapper = new LambdaQueryWrapper<>();

    String name = null;
    Integer ageStart = 10;
    Integer ageEnd = 20;

    userLambdaQueryWrapper
            .like(StringUtils.isNotBlank(name),User::getName,name)
            .ge(ageStart != null,User::getAge,ageStart)
            .le(ageEnd != null,User::getAge,ageEnd);
    List users = userMapper.selectList(userLambdaQueryWrapper);
    users.forEach(System.out::println);
}
(2)、例10:Update - 需求同例4

```java
    @Test
    void test10(){
        

        LambdaQueryWrapper userLambdaQueryWrapper = new LambdaQueryWrapper<>();

        userLambdaQueryWrapper
                .like(User::getName,"a")
                .and(i -> i.lt(User::getAge,18).or().isNull(User::getEmail));
        List users = userMapper.selectList(userLambdaQueryWrapper);
        users.forEach(System.out::println);

        User user = new User();
        user.setAge(18);
        user.setEmail("user@atguigu.com");
        int update = userMapper.update(user, userLambdaQueryWrapper);
        System.out.println(update);
    }

项目完整结构

转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号