Resumo MyBatisPlus

Índice

MeuBatisPlus

Recursos do MP

Estrutura do quadro MP

Preparação para uso de MP

dependências de importação

springboot integra arquivos de configuração mybatisplus

Edite a interface do mapeador após definir a classe de entidade Usuário

A diferença entre @Mapper e @MapperScan("nome do pacote")

Operação básica do MP

Adicionar operação

operação de exclusão

excluir usuário por id

Excluir por mapa como condição

Excluir por ID múltiplo

atualizar usuário

Atualização de usuário por id

Consultar usuários 

Consultar usuários por ID

Consultar usuários com base em vários IDs

Consultar usuários com base na coleção de mapas como condição

Interface de serviço comum

algumas operações 

Consultar o número total de registros

Adicione dados em lotes

Anotações comuns para MP

algoritmo de floco de neve

prefácio

mesa vertical

tabela de nível

construtor condicional

estrutura de herança

Use o construtor condicional para implementar operações de consulta

consultar todos os usuários

Consulte a coleção de campos de chave primária de acordo com o construtor

Consulte vários usuários de acordo com o construtor de condição

Sobre consulta difusa

 em consulta

Consultar e classificar por caractere de escape

O construtor condicional implementa a operação de exclusão

Implementando operações de modificação usando construtores condicionais

Prioridade das condições

Montando a instrução select

Montando uma subconsulta

consulta SQL dinâmica

Use updateWrapper para implementar a função de modificação

LambdaQueryWrapper

LambdaUpdateWrapper

Plugin de paginação para MP

Classe de configuração de configuração (necessária)

MP implementa paginação 

Função de paginação personalizada

Bloqueio otimista de MP

Adicione uma anotação de versão à classe de entidade que precisa ser alterada

Adicionar plugin de bloqueio otimista 

teste 

Enumeração genérica

Função de preenchimento automático de MP

Adicionar classe de configuração

Adicionar anotações a classes de entidades 

teste 

MeuBatisPlus

Significado: mybatis-plus é uma ferramenta de aprimoramento para mybatis. Com base no mybatis, apenas melhorias são feitas sem alterações. Ele nasceu para simplificar o desenvolvimento e melhorar a eficiência

Nota: Podemos integrar diretamente o mybatisplus com base no mybatis, o que não afetará as funções do mybatis, e também podemos usar as funções fornecidas por ele.

Recursos do MP

  • Apenas melhorias e nenhuma alteração são feitas no mybatis, e a introdução do mesmo não afetará os projetos existentes
  • Necessita apenas de uma configuração simples para executar rapidamente operações CRUD de tabela única, economizando muito tempo
  • Geração de código, paginação automática, exclusão lógica, funções de preenchimento automático, etc. estão disponíveis

Estrutura do quadro MP

entender:

  • MP é composto por MP starter, parte de anotação, parte de extensão, parte central e parte de geração de código; esses conteúdos juntos suportam o processo de MP para realizar a função
  • Função de implementação MP: primeiro, verifique a classe de entidade e, em seguida, extraia os atributos na classe de instância por meio da tecnologia de reflexão após a digitalização e analise o relacionamento entre a tabela e a classe de entidade após a extração; e os atributos na classe de entidade extraídos por meio de reflexão e O relacionamento entre nossos campos atuais; em seguida, gere a instrução sql correspondente de acordo com o método que estamos chamando no momento e, em seguida, injete a instrução sql de adição, exclusão, modificação e consulta no contêiner mybatis para atingir a função final

Preparação para uso de MP

dependências de importação

<dependencies>
        <!--springboot启动器-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <!--springboot测试-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!--lombok依赖-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <!--MP启动器-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.1</version>
        </dependency>
        <!--mysql驱动包--><!--测试功能的启动器-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
    </dependencies>

springboot integra arquivos de configuração mybatisplus

spring:
  #设置数据源信息
  datasource:
    #配置数据源类型
    type: com.zaxxer.hikari.HikariDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql:///mybatis_plus?characterEncoding=utf-8&userSSL=false&serverTimezone=GMT%2B8
    username: root
    password: root
mybatis-plus:
  configuration:
    #MP提供了日志功能
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    #驼峰映射(默认就是开启的)
    map-underscore-to-camel-case: true
  #设置MP的全局配置
  global-config:
    db-config:
      #这样设置的话,那么实体类所有的表都会加上t_前缀
      table-prefix: t_
      #设置统一主键生成策略
      id-type: auto
  #映射文件路径
  mapper-locations: classpath:/mapper/UserMapper.xml
  #配置类型别名所对应的包
  type-aliases-package: cn.tedu.mybatisplus.pojo
  #扫描通用枚举的包
  type-enums-package: cn.tedu.mybatisplus.enums

Edite a interface do mapeador após definir a classe de entidade Usuário

//使用MP提供的通用mapper——BaseMapper
//BaseMapper里的泛型表示实体类的类型
@Mapper
public interface UserMapper  extends BaseMapper<User> {
}

Perceber:

  • O MP encapsula muitos métodos CRUD comumente usados, e os usuários só precisam herdar a interface de negócios pública BaseMapper quando necessário, melhorando assim a eficiência
  • Os genéricos devem ser adicionados à interface BaseMapper, pois ela precisa obter a anotação especificada (e obter o valor da anotação), nome da tabela e seus atributos de acordo com o objeto genérico

A diferença entre @Mapper e @MapperScan("nome do pacote")

  • @MapperScan("nome do pacote"): verifica a interface do mapeador no pacote especificado e entrega a classe proxy da interface ao contêiner Spring para armazenamento
  • @Mapper: Entregue a classe proxy da interface para o contêiner Spring para armazenamento
  • @Mapper é usado na interface especificada, @MapperScan("o nome do pacote da interface correspondente") é usado na classe de inicialização ou arquivo de configuração 

Operação básica do MP

Nota: injete userMapper antes de usar 

Adicionar operação

        User user = new User();
        user.setName("lili").setAge(23).setEmail("[email protected]");
        int insert = userMapper.insert(user);
        System.out.println(insert);
        //mybatis-plus会自动获取id
        System.out.println(user.getId());

operação de exclusão

excluir usuário por id

        int i = userMapper.deleteById(7);
        System.out.println(i);

Excluir por mapa como condição

        Map<String,Object> map=new HashMap<>();
        map.put("name", "张三");
        map.put("age", 23);
        //删除name为张三,age为23的人
        int i = userMapper.deleteByMap(map);
        System.out.println(i);

Excluir por ID múltiplo

        List<Long> list = Arrays.asList(1L, 2L, 3L);
        int i = userMapper.deleteBatchIds(list);
        System.out.println(i);

atualizar usuário

Atualização de usuário por id

        User user = new User();
        user.setId(3L).setName("lan").setEmail("[email protected]");
        //根据id修改元素
        int i = userMapper.updateById(user);
        System.out.println(i);

Consultar usuários 

Consultar usuários por ID

        User user = userMapper.selectById(1L);
        System.out.println(user);

Consultar usuários com base em vários IDs

        List<Long> list = Arrays.asList(1L, 2L, 3L);
        List<User> users = userMapper.selectBatchIds(list);
        users.forEach(System.out::println);

Consultar usuários com base na coleção de mapas como condição

        HashMap<String, Object> map = new HashMap<>();
        map.put("name", "lan");
        map.put("age", 28);
        List<User> users = userMapper.selectByMap(map);
        //list会直接打印对象数组
        System.out.println(users);

Interface de serviço comum

Descrição: o General Service encapsula a interface IService e encapsula ainda mais o CRUD usando get query single line, remove delete, list query collection, page pagination e outros métodos de nomenclatura de prefixo para distinguir a camada Mapper e evitar confusão

//service接口
public interface UserService extends IService<User> {
}
//service实现类
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
}

Perceber:

  • ServiceImpl<UserMapper, User> implementa a interface IService<User>
  • UserService deve ser injetado primeiro ao usar

algumas operações 

Consultar o número total de registros

        //查询总记录数
        long count = userService.count();
        System.out.println(count);

Adicione dados em lotes

        ArrayList<User> list = new ArrayList<>();
        for (int i = 1; i <=10 ; i++) {
            User user = new User();
            user.setName("cjc"+i).setAge(10+i);
            list.add(user);
        }
        //批量添加数据
        boolean b = userService.saveBatch(list);
        //操作成功或失败
        System.out.println(b);

Anotações comuns para MP

//设置实体类所对应的表名,若对象与表名一致,则表名中()可以省略
@TableName("t_user")
public class User {
    //将当前属性对应的字段指定为主键(将该属性与数据库中的id字段进行映射),并通过雪花算法生成主键id
    //type标识主键的生成策略为自动递增,要求数据库的主键为自增策略(默认为雪花算法——IdType.ASSIGN.ID)
    @TableId(value = "id")
    private Long id;
    //将该注解标识的属性与数据库中的name字段一一映射,若属性名与字段名相同,则注解可省略
    @TableField(value = "name")
    private String name;
    private Integer age;
    private String email;
    //逻辑删除0标识未删除,1标识已删除
    //被逻辑删除的数据用户查不到,但是可以在数据库中看到,只是该属性变为1;(为修改操作)
    @TableLogic
    private Integer isDeleted;
}

Nota: A anotação @TableField(exit=false) é geralmente usada no atributo injetado, e o atributo atual do nome da tabela identificado por esta anotação não participa da operação do MP 

algoritmo de floco de neve

prefácio

Contexto: São necessárias soluções adequadas para lidar com o crescimento da escala de dados, a fim de fazer face à crescente pressão de acesso e ao volume de dados

Métodos de expansão de tabelas de banco de dados: subbanco de dados de negócios, replicação mestre-escravo, subtabela de banco de dados

Duas formas de divisão de tabelas de banco de dados

  • mesa vertical
  • tabela de nível

mesa vertical

Coloque dados importantes em uma tabela e separe aqueles que não são usados ​​em consultas de negócios em outra tabela para melhorar determinado desempenho

tabela de nível

Incremento automático de chave primária: por exemplo, divida a tabela de acordo com o intervalo (1-9999 é colocado na tabela 1 e 10000-20000 é colocado na tabela 2)

Módulo: chave primária% número de bancos de dados e colocar o mesmo restante em uma tabela

Algoritmo de floco de neve:

O Algoritmo Snowflake é um algoritmo de geração de chave primária distribuída pelo Twitter, que garante a não repetição das chaves primárias de tabelas diferentes e a ordenação das chaves primárias da mesma tabela

idéia principal:

  1. O comprimento é de 64 bits
  2. O primeiro é o bit de sinal, identificação de 1 bit, porque o tipo básico de long é assinado em java, o bit mais alto é o bit de sinal, o número positivo é 0 e o número negativo é 1, então id é geralmente um número positivo, o bit mais alto é 0
  3. 4 bits é o carimbo de data e hora (nível ms), que armazena a diferença do carimbo de data e hora (carimbo de data e hora atual - carimbo de data e hora de início), e o resultado é cerca de 69,73 anos
  4. 10 bits como o ID da máquina (5 bits é o data center, 5 bits é o ID da máquina, que pode ser implantado em 1.024 nós)
  5. 12 bits como o número de série em ms (o que significa que cada nó pode gerar 4.096 ids por milissegundo)

Vantagens: classificação geral de acordo com o incremento de tempo e não haverá colisão de ID em todo o sistema distribuído

construtor condicional

Função: Encapsular a condição atual

estrutura de herança

AbstractWrapper: Usado para encapsulamento de consulta condicional, onde as condições para gerar sql

  1. QueryWrapper: encapsulamento de condição de consulta
  2. UpdateWrapper: Atualizar empacotamento condicional
  3. AbstractLambdaWrapper: use sintaxe lambda

ResumoLambdaWrapper

  1. LambdaQueryWrapper: Query Wrapper para uso de sintaxe lambda
  2. LambdaUpdateWrapper: Wrapper do pacote de atualização lambda

Use o construtor condicional para implementar operações de consulta

consultar todos os usuários

        //通过条件构造器查询一个list集合,若没有条件则可以设置null(相当于查询所有)
        List<User> users = userMapper.selectList(null);
        users.forEach(System.out::println);

Consulte a coleção de campos de chave primária de acordo com o construtor

        //查询name为lei的主键字段
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("name", "lei");
        List<Object> list = userMapper.selectObjs(queryWrapper);
        System.out.println(list);

Consulte vários usuários de acordo com o construtor de condição

        //查询用户名包含a,年龄在20-30之间,邮箱信息不为null的用户信息
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        //queryWrapper可以实现链式加载
        queryWrapper.like("name", "a").between("age", 20, 30).isNotNull("email");
        List<User> users = userMapper.selectList(queryWrapper);
        System.out.println(users);
        //对象形式
        User user = new User();
        user.setAge(28);
        QueryWrapper<User> queryWrapper = new QueryWrapper<>(user);
        List<User> users = userMapper.selectList(queryWrapper);
        System.out.println(users);
        //user内的属性最终会以and形式拼接

Sobre consulta difusa

  • como: Indica que há% em ambos os lados de um
  • likeleft: Indica que há % à esquerda de um
  • likeright: Indica que existe uma % à direita de um

 em consulta

        //in查询,查询id为1,2,3的数据
        Integer[] ids={1,2,3};
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("id",ids);
        List<User> users = userMapper.selectList(queryWrapper);
        System.out.println(users);

Consultar e classificar por caractere de escape

        //查询id>2的用户,按照年龄降序排序,若年两相同则按照id升序排序
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.gt("id", 2).orderByDesc("age").orderByAsc("id");
        List<User> users = userMapper.selectList(queryWrapper);
        System.out.println(users);

personagem de fuga

  • >:gt
  • <:lt
  • =:eq
  • >=:ge
  • <=:o
  • != : é

O construtor condicional implementa a operação de exclusão

        //删除邮箱地址为null的用户信息
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.isNull("email");
        int i = userMapper.delete(queryWrapper);
        System.out.println(i);

Implementando operações de modificação usando construtores condicionais

        //将年龄>20并且用户名中包含a或邮箱为null的用户进行修改(默认情况下就是and连接)
        //修改条件
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.gt("age", 20).like("name", "a").or().isNull("email");
        User user = new User();
        user.setName("lei").setEmail("[email protected]");
        int i = userMapper.update(user, queryWrapper);
        System.out.println(i);

Prioridade das condições

        //将用户名中包含a并且(年龄大于20或邮箱为null)的用户信息进行修改
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        //lambda中的条件优先执行(i就表示条件构造器)
        queryWrapper.like("name", "a").and(i-> i.gt("age", 20).or().isNull("email"));
        User user = new User();
        user.setName("red").setEmail("[email protected]");
        int i = userMapper.update(user, queryWrapper);
        System.out.println(i);

Montando a instrução select

        //查询出来一个以map为泛型的list集合
        //查询用户名、年龄、邮箱信息
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("name","age","email");
        List<Map<String, Object>> maps = userMapper.selectMaps(queryWrapper);
        System.out.println(maps);

Montando uma subconsulta

        //select * from t_user where id in(select id from t_user where id<=100)
        //查询id<=100的用户信息
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.inSql("id", "select id from t_user where id<=100");
        List<User> users = userMapper.selectList(queryWrapper);
        System.out.println(users);

consulta SQL dinâmica

        String name=null;
        String  age="21";
        //判断字符串是否为null或空串若为返回false,不为返回true
        boolean pn = StringUtils.hasLength(name);
        boolean pa = StringUtils.hasLength(age);
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        //判断属性是否为true,为true则执行该条件,不为则忽略该条件
        queryWrapper.eq(pn,"name",name).eq(pa, "age", age);
        List<User> users = userMapper.selectList(queryWrapper);
        System.out.println(users);

Nota: queryWrapper.clear(); Para limpar condições redundantes, queryWrapper pode continuar a ser usado após a limpeza 

Use updateWrapper para implementar a função de modificação

        //查询用户名中包含a(年龄>20或邮箱为null)的员工信息
        UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
        //修改条件
        updateWrapper.like("name", "a").and(i->i.gt("age", 20).isNull("email"));
        //修改内容
        updateWrapper.set("name", "lala").set("email", "[email protected]");
        int i = userMapper.update(null, updateWrapper);
        System.out.println(i);

LambdaQueryWrapper

Função: evitar que sejamos muito estúpidos e escrever o nome do campo errado e fornecer uma interface funcional para acessar um determinado atributo em nossa classe de entidade.Quando acessamos o atributo, ele pode obter automaticamente o campo correspondente do atributo Nome, que campo a ser usado como condição

        String name="a";
        Integer ageBegin=null;
        Integer ageEnd=30;
        //主要避免了名称写错进而提供了直接访问表达式::
        LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.like(StringUtils.isNotBlank(name), User::getName,name)
                          .ge(ageBegin!=null, User::getAge,ageBegin)
                          .le(ageEnd!=null, User::getAge,ageEnd);
        List<User> users = userMapper.selectList(lambdaQueryWrapper);
        System.out.println(users);

LambdaUpdateWrapper

        //查询用户名中包含a(年龄>20或邮箱为null)的员工信息
        LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
        //修改条件
        updateWrapper.like(User::getName, "a").and(i->i.gt(User::getAge, 20).isNull(User::getEmail));
        //修改内容
        updateWrapper.set(User::getName, "lala").set(User::getEmail, "[email protected]");
        int i = userMapper.update(null, updateWrapper);
        System.out.println(i);

Plugin de paginação para MP

Classe de configuração de configuração (necessária)

@Configuration
public class MPConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        //创建mybatisplus拦截器
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        //向拦截器中添加分页插件
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
}

MP implementa paginação 

//测试类内
        //两个参数——当前页页码,每页信息条数
        Page<User> page = new Page<>(2,3);
        //两个参数——分页对象,条件构造器
        userMapper.selectPage(page, null);//因为我对所有的查询所以条件构造器为null——返回值还为page
        //获取当前页数据
        List<User> records = page.getRecords();
        System.out.println(records);
        //获取总记录数
        long total = page.getTotal();
        System.out.println(total);
        //获取总页数
        long pages = page.getPages();
        System.out.println(pages);
        //是否有下一页
        System.out.println(page.hasNext());
        //是否有上一页
        System.out.println(page.hasPrevious());

Função de paginação personalizada

//自定义接口:
//mybatisplus提供的分页对象,必须为于第一个参数的位置
Page<User> selectPageVo(@Param("page") Page<User> page,@Param("age") Integer age);

//自定义配置文件sql
    <select id="selectPageVo" resultType="User">
        select id,name,age,email from t_user where age>#{age}
    </select>
        //测试类
        Page<User> page = new Page<>(2, 2);
        userMapper.selectPageVo(page,20);
        //获取当前页数据
        List<User> records = page.getRecords();
        System.out.println(records);
        //获取总记录数
        long total = page.getTotal();
        System.out.println(total);
        //获取总页数
        long pages = page.getPages();
        System.out.println(pages);
        //是否有下一页
        System.out.println(page.hasNext());
        //是否有上一页
        System.out.println(page.hasPrevious());

Bloqueio otimista de MP

Adicione uma anotação de versão à classe de entidade que precisa ser alterada

@Data
public class Product {
    private Long id;
    private String name;
    private Integer price;
    @Version//用来标识乐观锁版本号字段
    private Integer version;
}

Adicionar plugin de bloqueio otimista 

@Configuration
public class MPConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        //创建mybatisplus拦截器
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        //向拦截器中添加乐观锁插件
        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return interceptor;
    }
}

teste 

Nota: Xiao Wang e Xiao Li abaixo usam os mesmos dados

        //小李查询商品价格
        Product productLi = productMapper.selectById(1);
        System.out.println("小李"+productLi.getPrice());
        //小王查询商品价格
        Product productWang = productMapper.selectById(1);
        System.out.println("小王"+productWang.getPrice());
        //小李将商品价格+50
        productLi.setPrice(productLi.getPrice()+50);
        productMapper.updateById(productLi);
        //小王将商品价格-30
        productWang.setPrice(productWang.getPrice()-30);
        int result = productMapper.updateById(productWang);
        if (result==0){
            //操作失败后重试
            Product productNew = productMapper.selectById(1);
            productNew.setPrice(productNew.getPrice()-30);
            productMapper.updateById(productNew);
        }

Enumeração genérica

Há um tipo de enumeração na classe de entidade, então como armazenar o tipo de enumeração no banco de dados

//为该枚举添加注解
@Getter
public enum SexEnum {
    MALE(1,"男"),
    FEMALE(2,"女");
    @EnumValue//将注解所标识的属性的值存储到数据库中(因为数据库中存放的是数字)
    private Integer sex;
    private String sexName;
    SexEnum(Integer sex, String sexName) {
        this.sex = sex;
        this.sexName = sexName;
    }
}

Configurar pacote de verificação de enumeração geral

mybatis-plus.type-enums-package=cn.tedu.mybatisplus.enums

Insira um objeto enumerado no banco de dados

Função de preenchimento automático de MP

Adicionar classe de configuração

@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
    @Override
    public void insertFill(MetaObject metaObject) {
        this.setFieldValByName("created", new Date(), metaObject);
        this.setFieldValByName("updated", new Date(), metaObject);
    }
    @Override
    public void updateFill(MetaObject metaObject) {
        this.setFieldValByName("updated", new Date(), metaObject);
    }
}

Adicionar anotações a classes de entidades 

@Data
@Accessors(chain = true)
public class Product {
    private Long id;
    private String name;
    private Integer price;
    //在插入数据时自动填充
    @TableField(fill = FieldFill.INSERT)
    private Date created;
    //在插入和更新操作时自动填充
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Date updated;
    @Version//用来标识乐观锁版本号字段
    private Integer version;
}

teste 

        //测试
        Product product = new Product();
        product.setName("cake").setId(3L).setPrice(66);
        int insert = productMapper.insert(product);
        System.out.println(insert);

Acho que você gosta

Origin blog.csdn.net/m0_60027772/article/details/126570742
Recomendado
Clasificación