MyBatisPuls学习总结

目录

一、前言

二、配置

依赖文件

yml文件

扫描mapper

三、入门案例

查询全部数据(selectList)

四、具体用法

插入

插入数据,并且获取自增主键(insert)

删除

通过id删除数据(deleteById)

map条件删除(deleteByMap)

根据id批量删除(deleteBatchIds)

修改

根据实体类的id修改数据(updateById)

查询

根据id查询(selectById)

根据id批量查询(selectBatchIds)

根据map条件查询(selectByMap)

查询全部(selectList)

五、自定义SQL(XML)

六、通用Service接口

定义接口

方法

七、注解

映射表@TableName("数据库表名")

映射主键@TableId

字段映射@TableField

逻辑删除@TableLogic

八、条件构造器wapper

查询(QueryWrapper)

条件查询

查询结果排序

删除

条件删除

修改

条件修改

条件优先级括号

UpdateWrapper 直接设置修改值

组装select

自定义返回表的字段

子查询

组装状态条件

动态组装

防止字段写错

九、插件

分页插件

常用分页属性

配置类

使用

自定义分页

乐观锁

使用@Version注解

十、通用枚举

十一、多数据源

十一:总结


一、前言

mybatis-puls在mybatis的前提下只做增强不做修改,对于单表查询更加灵活,在有mybatis的基础下最多需要三天就能游刃有余。

二、配置

依赖文件

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

<dependency>    
     <groupId>com.mysql</groupId>    
     <artifactId>mysql-connector-j</artifactId>   
     <scope>runtime</scope>
 </dependency>

yml文件

#Mysql  
datasource:
  spring:
    url: jdbc:mysql://localhost:3306/ipiw?characterEncoding=utf-8&userSSL=false
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver
    
mybatis-plus:
  configuration:  
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl  #设置打印日志

扫描mapper

@SpringBootApplication
//扫描mapper接口所在的包
@MapperScan("com.example.demo2.mapper")
public class Demo2Application {

    public static void main(String[] args) {
        SpringApplication.run(Demo2Application.class, args);    
     }

}

三、入门案例

查询全部数据(selectList)

//继承 BaseMappe 接口,需要指定表查询映射对应的Bean
@Repository //标识为持久层主键 ,使@Autowired不会报错
public interface UserMapper extends BaseMapper<User2> {
}

@Autowired
private  UserMapper userMapper;
@Testpublic void  test01(){
    //通过条件构造器插叙一个List集合,如果没有条件,则可以设置null为参数   
    List<User2> list=userMapper.selectList(null);   
    list.forEach(System.out::println);
  }

四、具体用法

插入

插入数据,并且获取自增主键(insert)

user类

public class User2 {
    @TableId(value = "id",type = IdType.AUTO) //绑定自增主键的类属性
    private int id; //自动自增主键    
    private String name;    
    private Integer mima;
 }
 
 @Test
 public void testInset(){
    User2 user2=new User2();    
    user2.setMima(1234);    
    user2.setName("王五");  
    int rest=  userMapper.insert(user2);    //插入    
    log.info("插入成功:{},自增加主键:{}",rest,user2.getId());
 }

删除

通过id删除数据(deleteById)

@Test
public void  test02(){
    int result = userMapper.deleteById(8);    
    log.info("删除条数:{}",result);
}

map条件删除(deleteByMap)

@Test
public void  test03(){
    //设置map条件
    Map<String,Object>map =new HashMap<>();    
    map.put("name","王五");    
    map.put("mima",12);    
    //根据map执行条件删除(map为且条件)    
    int result=userMapper.deleteByMap(map);  
   // int result=userMapper.deleteByMap(null); 删除全部数据
        
    log.info("删除条数:{}",result);
 }

根据id批量删除(deleteBatchIds)

@Test
public void  test04(){
  //根据id执行批量删除  
  List<Integer>list=  Arrays.asList(1,2,3);  
  int result =userMapper.deleteBatchIds(list);    //根据id执行批量删除
  log.info("删除条数:{}",result);
 }

修改

根据实体类的id修改数据(updateById)

//修改数据
@Test
public void  test05(){
    //根据实体类的对象的id修改数据   
    User2 user2=new User2();   
    user2.setId(9); //设置id,会根据这个id修改数据   
    user2.setName("小红");    
    user2.setMima(0);    
    int result=userMapper.updateById(user2); // 修改数据,会根据实体类id匹配id字段  
    log.info("删除条数:{}",result);
}

查询

根据id查询(selectById)

@Test
public void  test06(){
 User2 user2=userMapper.selectById(14);    
 log.info("查询数据:{}",user2);
}

根据id批量查询(selectBatchIds)

@Test
public void  test07(){
 List<Integer>user2Ids=   Arrays.asList(11,13,15);  //创建id集合   
 List<User2> user2s=userMapper.selectBatchIds(user2Ids);//根据id集合批量查询    
 log.info("查询数据:{}",user2s);
}

根据map条件查询(selectByMap)

//根据map条件查询
@Test
public void  test08(){
 Map<String,Object> map=new HashMap<>(); 
 map.put("name","老大"); 
 map.put("mima",676); //map条件为且条件( name=‘老大’  AND mima=676)   
 List<User2> user2s=userMapper.selectByMap(map);    //根据map条件查询
 //List<User2> user2s=userMapper.selectByMap(null); //为null时候代表查询全部
 log.info("查询数据:{}",user2s);
}

查询全部(selectList)

@Test
public void  test09(){
    //查询全部数据    
    List<User2> user2s=userMapper.selectList(null);    
    log.info("查询数据:{}",user2s);
}

五、自定义SQL(XML)

mybatis-puls默认扫描 resources/**/*.xml文件

自定义查询,直接写自定义方法

@Repository //标识为持久层主键
public interface UserMapper extends BaseMapper<User2> {
    //查询结果封装成map    
    Map<String,Object> selectMapById(@Param("id")Integer id);    
    //查询结果封装成User2,puls插件有这个方法  
    User2 selectUser2ById(@Param("id")Integer id);
}

xml



<select id="selectMapById" resultType="map">
    select id,name,mima from user2 where id=#{id}
</select>
    
<select id="selectUser2ById" resultType="com.example.demo2.pojo.User2">
    select * from user2 where id=#{id}
 </select>

六、通用Service接口

Mybatis-Plus提供了一个IService接口以及ServiceImpl实现类,封装了常见的业务逻辑

定义接口

//自定义接口(UserService) 继承IService<User2>  User2为当前查询结果表映射的bean
public interface UserService extends IService<User2> {
}

 //自定义实现(UserServiceImpl)   继承 ServiceImpl类  和 UserService接口                                   
 @Service                              //UserMapper为对应的dao接口    //   User2为当前查询结果表映射的bean
public class UserServiceImpl extends ServiceImpl<UserMapper, User2> implements UserService {
}

方法

统计

@Test
public void test01(){
    //查询总记录数目 
    long count=   userService.count(); 
    log.info("数据条数:{}",count);
}

批量添加

本质是多次循环调用添加,

效率不如直接写xml

//批量添加
@Test
public void test02(){
    List<User2> list= new ArrayList<>();    
    for (int i = 0; i < 10; i++) {
        User2 user=new User2();        
        user.setName("张三"+i);        
        user.setMima(23+i);        
        list.add(user);    
        }
   boolean b= userService.saveBatch(list); 
   //批量添加传入个集合    
   log.info("批量插入是否成功:{},插入条数:{}",b,list.size());
 }

七、注解

映射表@TableName("数据库表名")

设置bean对应的数据库表

@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName("user2") //对应表名
public class User2 {
    @TableId(value = "id",type = IdType.AUTO)
    private int id; //自动自增主键    
    private String name;    
    private Integer mima;
}

全局映射表前缀yml

mybatis-plus:
    global-config:
      db-config:
        table-prefix: t-  # user名的bean映射对应数据库表t-user (对全部表生效,不仅仅是user)

映射主键@TableId

将bean属性映射数据库表中主键(当前属性名字需要和字段名字相同)

@TableId //什么也不加只是设置主键
private int name; //  数据库表中name为主键,当前属性名字需要和字段名字相同

bean主键和数据库主键名字不一致时候

@TableId(value = "uid") //@TableId("uid")
private int id;         //映射主键,id--uid

设置映射自增主键,不使用默认的雪花算法

@TableId(value = "id",type = IdType.AUTO)
private int id; //自动自增主键 ,且数据库需要设置主键自动递增

统一设置IdType

global-config:
  db-config:
    table-prefix: t-
    id-type: auto #主统一键生成策略

雪花算法:能够保证不同的主键的不重复性

字段映射@TableField

在mybaits-plus中 userName---user_name (驼峰名字自动转换成数字库名中的_),而mybatis需要配置才行

自定义映射字段

@TableField("user_name") //自定义字段 name--user_name
private String name;

逻辑删除@TableLogic

1、物理删除:

  真实删除,将对应数据从数据库中删除,之后查询不到此条被删除的数据

2、逻辑删除:

  假删除,将对应数据中代表是否被删除字段的状态改为“被删除状态”,之后在数据库中仍然可见

使用场景:可以进行数据恢复

使用:

@TableLogic //逻辑删除
private Integer isDeleted;  //在数据库中is_deleted字段的默认值是0,执行删除操作时候之后把当前is_deleted修改成0
                            //同时is_deleted为1的数据也不会被查询到

八、条件构造器wapper

修改:UpdateWrapper、LambdaUpdatewrapper

查询/删除:QueryWrapper、LambdaQueryWrapper

查询(QueryWrapper)

条件查询

@Testpublic void test01(){
    //查询条件    
    //查询id在[9,16]之间,且名字不为老王,且mima包含4    
    QueryWrapper<User2> queryWrapper=new QueryWrapper<>();   //查询条件
                    //数据库字段--value
    queryWrapper.between("id",9,16) //id在[9,16]之间                
                .notIn("name","老王") //名字不能为老王                
                .like("mima",4); //密码有 4, 模糊查询 %4%    
    List<User2> user2s = userMapper.selectList(queryWrapper);    
    log.info("查询结果:{}",user2s);
 }

查询结果排序

@Testpublic void test02(){
    //查询条件    
    //按mima大小排序,如果mima相同就按id大小排序    
    QueryWrapper<User2> queryWrapper=new QueryWrapper<>();    
    queryWrapper.orderByAsc("mima") //先按照mima升序排序                
                .orderByAsc("id"); //再按照id 升序排序    
    List<User2> user2s = userMapper.selectList(queryWrapper);    
    user2s.forEach(System.out::println);  
   
}

删除

条件删除

@Testpublic void test03(){
      //删除mima有3的数据    
      QueryWrapper<User2> queryWrapper=new QueryWrapper<>();    
      queryWrapper.like("mima",3);    
      int result=userMapper.delete(queryWrapper);    
      log.info("删除数据条数:{}",result);
}

修改

条件修改

queryWrapper.gt() // gt表示>, ge表示>=, lt表示

or 上下默认AND连接,使用or连接上下(一句)

(A) or (B) A表示上条件,B表示下条件即当前or内部条件

.or(queryWrapper2->queryWrapper2.isNull("name").isNull("id"))

//条件修改
@Testpublic void test04(){
    //将mima>24或者name名字有包含“三”的数据修改成 mima=11,name=猫猫    
    UpdateWrapper<User2> updateWrapper=new UpdateWrapper<>();     
    //   queryWrapper.gt() // gt表示>, ge表示>=,  lt表示<,lr表示<=,  between 表示区间[]    
    updateWrapper.gt("mima",23)
                .like("name","三")
                .or()                   //上下默认AND连接,使用or连接上下(一句)                
                .isNull("id");                                 
                User2 user2=new User2();    
                user2.setMima(11);    //修改密码
                user2.setName("猫猫");    //修改名字
                int update = userMapper.update(user2,updateWrapper);//修改结果--修改条件    
                log.info("修改成功条数:{}",update);
}

条件优先级括号

在sql中括号具有最高优先级

.and(i->i.XX.XX)

         表示 (A)AND (B) ;A表示上层所有,B表示下层所有

.or(i->i.XX.XX)

        表示 (A)OR (B) ;A表示上层所有,B表示下层所有

//条件优先级
@Test
public void test05(){
    //将 name包含猫 且 (mima>=12 且 id!=null)    
    //修改成  name=狗    
    UpdateWrapper<User2> updateWrapper=new UpdateWrapper<>();    
    updateWrapper.like("name","猫")
                .and(user2UpdateWrapper2 ->user2UpdateWrapper2.ge("mima",12).isNotNull("id"));   //表示   A and B  (A表示上层所有,B表示下层所有) 
                //.or(user2UpdateWrapper2 ->user2UpdateWrapper2.ge("mima",12).isNotNull("id"));  //表示   A or B  (A表示上层所有,B表示下层所有) 
                User2 user2=new User2();    
                user2.setName("狗"); //只修改名字    
                int update = userMapper.update(user2,updateWrapper);
                //修改结果--修改条件    
                log.info("修改成功条数:{}",update);
}

 

上面UpdateWrapper都可以替换成QueryWrapper

UpdateWrapper 直接设置修改值

推荐使用这个

//修改
@Test
public void test08(){
   // 将name中包含狗且(id<30 or mima<100) 的修改成 猫    
   UpdateWrapper<User2> updateWrapper=new UpdateWrapper<>();    
   updateWrapper.like("name","狗")
                 .and(que2->que2.lt("id",30).or().lt("mima",100));    
                 updateWrapper.set("name","猫"); //可以直接设置修改的字段       
                 int result = userMapper.update(null, updateWrapper);    
                 log.info("修改数据条数:{}",result);
}

组装select

自定义返回表的字段

//自定义返回的数据字段
@Testpublic void test06(){
  //只返回表的id、name字段信息    
  QueryWrapper<User2> queryWrapper=new QueryWrapper<>();    
  queryWrapper.select("id","name"); //只返会 id,name字段    
  List<Map<String, Object>> maps = userMapper.selectMaps(queryWrapper);   //返回多个map 
  maps.forEach(System.out::println);
}

子查询

//子查询
@Test
public void test07(){
    // 查询id小于等于100的用户信息    
    QueryWrapper<User2> queryWrapper=new QueryWrapper<>();    
    // **** id in (sql)    
    queryWrapper.inSql("id","select id from user2 where id<=100");    
    List<User2> user2s = userMapper.selectList(queryWrapper);    
    user2s.forEach(System.out::println);
}

组装状态条件

动态组装

如果第一个参数为false,那么当前条件失效,不会组装成sql条件

@Test
public void test10(){
    String name="";    
    Integer mimaBegin=20;    
    Integer mimaEnd=30;    
    QueryWrapper<User2> queryWrapper=new QueryWrapper<>();    
    queryWrapper.like(StringUtils.isNotBlank(name),"name","a") // 为空时候不组装当前条件            
                .ge(mimaBegin!=null,"mima",20) // 为空时候不组装当前条件            
                .le(mimaEnd!=null,"mima",30); // 为空时候不组装当前条件    
    List<User2> user2s = userMapper.selectList(queryWrapper);    
    user2s.forEach(System.out::println);
}

防止字段写错

防止数据库字段,可以使用LambdaUpdateWrapper、LambdaQueryWrapper

直接使用表映射的类数据成员充当字段名字

@Test
public void test11(){
    String name="";    
    Integer mimaBegin=20;    
    Integer mimaEnd=30;    
    LambdaQueryWrapper<User2> lambdaQueryWrapper=new LambdaQueryWrapper<>();    
    lambdaQueryWrapper.like(StringUtils.isNotBlank(name),User2::getName,name)  //User2::getName --name                        
    .ge(mimaBegin!=null,User2::getMima,20)  //User2::getMima--mima                      
    .le(mimaEnd!=null,User2::getMima,30);  //User2::getMima--mima    
    List<User2> user2s = userMapper.selectList(lambdaQueryWrapper);    
    user2s.forEach(System.out::println);
}
//修改
@Test
public void test12(){
    // 将name中包含狗且(id<30 or mima<100) 的修改成 猫    
    LambdaUpdateWrapper<User2> updateWrapper=new LambdaUpdateWrapper<>();    
    updateWrapper.like(User2::getName,"狗")
                 .and(que2->que2.lt(User2::getId,30).or().lt(User2::getId,100));   
             
            updateWrapper.set(User2::getName,"猫"); //可以直接设置修改    
            int result = userMapper.update(null, updateWrapper);    
            log.info("修改数据条数:{}",result);
   }

九、插件

分页插件

常用分页属性

page.hasNext()         是否有下一页
page.hasPrevious()     是否有上一页
page.getRecords()      当前页面数据
page.getCurrent()      当前页码
page.getPages()        总页数
page.getTotal()        总数据条数
,page.getSize()        每页最大数据条数

配置类

@Configuration
//扫描mapper接口所在的包
@MapperScan("com.example.demo2.mapper")
public class MybaitsPlusConfig {
    @Bean    
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        MybatisPlusInterceptor interceptor=new MybatisPlusInterceptor(); //创建配置        
        //添加分页插件        
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));              
         
        return interceptor;    
        }
}

使用

@Test
public void test01(){
    Page<User2> page=new Page<>(5,3); //第五页 ,每页3条数据    
    //查询数据封装到page中    
    // 第一个参数 分页数据,第二个参数 查询条件
    userMapper.selectPage(page,null);  //把结果存储到page,当前是第五页的的结果   
    log.info("page数据:{}",page);    
    log.info("有没有下一页数据:{}",page.hasNext());    
    log.info("有没有上一页:{}",page.hasPrevious());    
    log.info("当前页面数据:{}",page.getRecords());    
    log.info("当前页码:{}",page.getCurrent());    
    log.info("总页数:{}",page.getPages());    
    log.info("总数据条数:{}",page.getTotal());    
    log.info("每页最大数据条数:{}",page.getSize()); //每页最大数据条数  
 }

自定义分页

sql是自己写的xml时候,分页需要进行自定义

接口

 //通过id进行查询 并且分页,注意返回值和第一个参数需要是Page
 Page<User2> selectPageVo(@Param("page")  Page<User2> page,@Param("id") Integer id);

sql

<select id="selectPageVo" resultType="com.example.demo2.pojo.User2">
    select id,name,mima from user2 where id>#{id}
 </select>
 //返回值的类型是映射的类类型
 //结果会自动映射成page

使用

@Test
public void test02(){
    Page<User2> page=new Page<>(1,3); //当前页,每页条数    
    userMapper.selectPageVo(page,20); //结果会映射到page ,当前是第一页的数据   
    log.info("page数据:{}",page);    
    log.info("有没有下一页数据:{}",page.hasNext());    
    log.info("有没有上一页:{}",page.hasPrevious());    
    log.info("当前页面数据:{}",page.getRecords());    
    log.info("当前页码:{}",page.getCurrent());    
    log.info("总页数:{}",page.getPages());    
    log.info("总数据条数:{}",page.getTotal());    
    log.info("每页最大数据条数:{}",page.getSize()); //每页最大数据条数
}

乐观锁

悲观锁:

        每次只能一个人操作,此人操作完成后才释放锁

乐观锁:

        每个人操作时候都会有一个版本号,如果一个人在未完成操作时候版本号发生改变(被另一个人操作修改了)那么此人的操作失败,数据库设置一个字段version用来表示版本号

使用@Version注解

设置当前数据字段为版本号,与数据库版本号字段绑定,字段可以设置int类型,默认值为0

映射类

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Product {
    @TableId(value = "id",type = IdType.AUTO) //自动递增主键    
    private Integer id;    
    private String name;    
    private Double price;    
    @Version //标识乐观锁版本号字段    
    private Integer version;
}

配置类:添加乐观锁插件

@Configuration
//扫描mapper接口所在的包
@MapperScan("com.example.demo2.mapper")
public class MybaitsPlusConfig {
    @Bean    
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        MybatisPlusInterceptor interceptor=new MybatisPlusInterceptor(); //创建配置        
        //添加分页插件        
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));              
        // 添加乐观锁插件        
        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());        
        return interceptor;    
        }
}

操作失败的解决办法:

如果当前人因为版本号不同而操作失败,那么进行重试即可解决

十、通用枚举

在枚举中加入@EnumValue注解 ,把枚举的值存储到数据库中,而不是枚举名字,但该注解需要在yml里配置扫描才能生效

扫描@EnumValue注解

mybatis-plus:
    type-enums-package:com.at.mybaits.enums  #扫描枚举所在的包,新版本不用配置
    

枚举:

@Getter
public enum MyIp {
    WIN("192.168.1","win"),    
    LIU("192.168.2","lux"); //每一个相当于对象    
    
    private String ip;      // 成员属性    
    
    @EnumValue //当成员是枚举时候需要写入数据库的属性    
    private String name;    // 成员属性     
        
    MyIp(String ip,String name){ 
    //私有构造方法        
    this.ip=ip;        
    this.name=name;    
   }

    
}

映射表

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
    private MyIp name; //当前表映射是枚举,会把@EnumValue  注解的属性写入数据库    
    private Integer mima;
 }

测试方法

@Autowired
MyUserMapper mapper;

@Test
public void test01(){
    User user=new User();    
    user.setName(MyIp.WIN);  //设置枚举  
    user.setMima(1111);    
    int result= mapper.insert(user);    
    log.info("插入数据:{}",result);
 }

十一、多数据源

依赖

<!--       多数据源-->        
<dependency>            
    <groupId>com.baomidou</groupId>            
    <artifactId>dynamic-datasource-spring-boot-starter</artifactId>            
    <version>3.3.2</version>        
</dependency>

配置文件

spring:
 datasource:
      dynamic:
        primary: master  #设置默认的数据源或者数据源组    
        strict: false # 严格匹配数据源 ,默认false,true未匹配到指定数据源时候抛出异常    
        datasource:
          master: # 数据源 1        
            url: jdbc:mysql://localhost:3306/ipiw?serTimezone=UTC&character=utf8
            username: root
            password: 123456
            driver-class-name: com.mysql.cj.jdbc.Driver
          slaver_1: # 数据源 2        
            url: jdbc:mysql://localhost:3306/text?serTimezone=UTC&character=utf8
            username: root
            password: 123456
            driver-class-name: com.mysql.cj.jdbc.Driver

对应mapper接口

需要使用@DS(“数据源”) ;来表名操作的数据源,也可以标识在方法上

@DS("master") //指定dao操作的数据源,也可以标识在Service层
@Repository //标识为持久层主键
public interface UserMapper extends BaseMapper<User2> {
}

另一个数据源

@DS("slaver_1") //当前接口操作的都是 slaver_1 数据库中的表
@Repositorypublic interface DateMapper extends BaseMapper<Date> {

}

测试

@Autowired
UserMapper userMapper;
@Autowired
DateMapper dateMapper;

@Test
public void test01(){
    List<User2> user2s = userMapper.selectList(null);    
    user2s.forEach(System.out::println);    
    List<Date> dates = dateMapper.selectList(null);    
    dates.forEach(System.out::println);
 }

十一:总结

一下子不知道怎么办就直接写SQL,对比MyBatis来说确实更好用了,如果单人开发选择它可以更加舒服,多人一起开发还是写sql吧。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值