不同查询构建器的使用方式(Mybatis、Mybatis-Plus、Mybatis-Flex、Spring Data JPA、QueryDsl)

目录

    • 一、SQL查询需求
    • 二、【Mybaits】xml方式
    • 三、【Mybatis-Plus】QueryWrapper方式
    • 四、【Mybatis-Flex】QueryWrapper方式
    • 五、【Mybatis-Flex】QueryWrapper & APT方式
    • 六、【Spring Data JPA】Specification方式
    • 七、【Spring Data JPA】Specification & MetaModel方式
    • 八、【Spring Data JPA】QueryDsl方式

一、SQL查询需求

实现如下3个查询:

-- 查询1
SELECT 
* 
FROM SAMPLE 
WHERE
id = 1 
AND name LIKE '%ha%' 
AND create_time BETWEEN '2014-11-24' AND '2024-11-24'  

-- 查询2
SELECT 
* 
FROM SAMPLE 
WHERE
id = 1 
OR name LIKE '%ha%' 
OR create_time BETWEEN '2014-11-24' AND '2024-11-24'  

-- 查询3
SELECT 
* 
FROM SAMPLE 
WHERE
( id = 1 OR name LIKE '%ha%')
AND create_time BETWEEN '2014-11-24' AND '2024-11-24' 

查询参数:

package com.luo.query;

class SampleQuery {
	private Long id;
	private String name;
	private LocalDateTime startDate;
	private LocalDateTime endDate;
	//省略getter/setter...
}

Sample数据对象:

package com.luo.po;

class Sample {
	private Long id;
	private String name;
	private LocalDateTime createTime;
	//省略getter/setter...
}

二、【Mybaits】xml方式

定义dao接口:

package com.luo.dao;

class SamplerMapper {
	List<Sample> select1(SampleQuery query);
	List<Sample> select2(SampleQuery query);
	List<Sample> select3(SampleQuery query);
}

定义mapper.xml,使用xml编写动态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.luo.dao.SampleMapper">   
    <select id="select1" resultType="com.luo.po.Sample">
        SELECT *
        FROM SAMPLE
        <where>
            <if test="id != null">
                AND id = #{id}
            </if>
            <if test="name != null">
                AND name LIKE CONCAT('%',#{name},'%')
            </if>
            <if test="startDate != null and endDate != null">
                AND create_time BETWEEN #{startDate} AND #{endDate}
            </if>
        </where>
    </select>
	<select id="select2" resultType="com.luo.po.Sample">
        SELECT *
        FROM SAMPLE
        <where>
            <if test="id != null">
                OR id = #{id}
            </if>
            <if test="name != null">
                OR name LIKE CONCAT('%',#{name},'%')
            </if>
            <if test="startDate != null and endDate != null">
                OR create_time BETWEEN #{startDate} AND #{endDate}
            </if>
        </where>
    </select>
    <select id="select3" resultType="com.luo.po.Sample">
        SELECT *
        FROM SAMPLE
        <where>
        	<if test="id != null or name != null">
        	(
	        	<if test="id != null">
	                id = #{id} OR 
	            </if>
	            <if test="name != null">
	                name LIKE CONCAT('%',#{name},'%')
	            </if>
	        )
        	</if>            
            <if test="startDate != null and endDate != null">
                AND create_time BETWEEN #{startDate} AND #{endDate}
            </if>
        </where>
    </select>
</mapper>

三、【Mybatis-Plus】QueryWrapper方式

定义dao接口,使用Mybatis-Plus QueryWrapper 动态构建查询条件:

import com.baomidou.mybatisplus.core.mapper.BaseMapper
import com.baomidou.mybatisplus.core.toolkit.Wrappers;

public interface SampleMapper extends BaseMapper<Sample> {

    default List<Sample> select1(SampleQueryDto query) {
        return this.selectList(Wrappers.<Sample>lambdaQuery()
                .eq(Objects.nonNull(query.getId()), Sample::getId, query.getId())
                .like(Objects.nonNull(query.getName()), Sample::getName, query.getName())
                .between(Objects.nonNull(query.getStartDate()) && Objects.nonNull(query.getEndDate()), Sample::getCreateTime, query.getStartDate(), query.getEndDate())
        );
    }

    default List<Sample> select2(SampleQueryDto query) {
        return this.selectList(Wrappers.<Sample>lambdaQuery()
                .or().eq(Objects.nonNull(query.getId()), Sample::getId, query.getId())
                .or().like(Objects.nonNull(query.getName()), Sample::getName, query.getName())
                .or().between(Objects.nonNull(query.getStartDate()) && Objects.nonNull(query.getEndDate()), Sample::getCreateTime, query.getStartDate(), query.getEndDate())
        );
    }

    default List<Sample> select3(SampleQueryDto query) {
        return this.selectList(Wrappers.<Sample>lambdaQuery()
                .between(Objects.nonNull(query.getStartDate()) && Objects.nonNull(query.getEndDate()), Sample::getCreateTime, query.getStartDate(), query.getEndDate())
                .and(Objects.nonNull(query.getId()) || Objects.nonNull(query.getName()),
                        wrapper -> wrapper.eq(Objects.nonNull(query.getId()), Sample::getId, query.getId())
                                .or().like(Objects.nonNull(query.getName()), Sample::getName, query.getName())
                )
        );
    }
}

四、【Mybatis-Flex】QueryWrapper方式

定义dao接口,使用Mybatis-Flex QueryWrapper 动态构建查询条件:

import com.mybatisflex.core.BaseMapper;
import com.mybatisflex.core.query.QueryWrapper

public interface SampleMapper extends BaseMapper<Sample> {


    default List<Sample> select1(SampleQueryDto query) {
        return this.selectListByQuery(QueryWrapper.create()
                .eq(Sample::getId, query.getId(), Objects.nonNull(query.getId()))
                .like(Sample::getName, query.getName(), Objects.nonNull(query.getName()))
                .between(Sample::getCreateTime, query.getStartDate(), query.getEndDate(), Objects.nonNull(query.getStartDate()) && Objects.nonNull(query.getEndDate()))
        );
    }

    default List<Sample> select2(SampleQueryDto query) {
        return this.selectListByQuery(QueryWrapper.create()
                .or(Sample::getId).eq(query.getId(), Objects.nonNull(query.getId()))
                .or(Sample::getName).like(query.getName(), Objects.nonNull(query.getName()))
                .or(Sample::getCreateTime).between(query.getStartDate(), query.getEndDate(), Objects.nonNull(query.getStartDate()) && Objects.nonNull(query.getEndDate()))
        );
    }

    default List<Sample> select3(SampleQueryDto query) {
        return this.selectListByQuery(QueryWrapper.create()
                .between(Sample::getCreateTime, query.getStartDate(), query.getEndDate(), Objects.nonNull(query.getStartDate()) && Objects.nonNull(query.getEndDate()))
                .and(queryWrapper -> {
                    queryWrapper.eq(Sample::getId, query.getId(), Objects.nonNull(query.getId()))
                            .or(Sample::getName).like(query.getName(), Objects.nonNull(query.getName()));
                }, Objects.nonNull(query.getId()) || Objects.nonNull(query.getName())));
    }
}

五、【Mybatis-Flex】QueryWrapper & APT方式

定义dao接口,使用Mybatis-Flex QueryWrapper 和 基于APT生成的查询辅助类 动态构建查询条件:

import com.mybatisflex.core.BaseMapper;
import com.mybatisflex.core.query.QueryWrapper;
import static com.luo.po.table.SampleTableDef.SAMPLE;

public interface SampleMapper extends BaseMapper<Sample> {

    default List<Sample> select1(SampleQueryDto query) {
        return this.selectListByQuery(QueryWrapper.create()
                .where(SAMPLE.ID.eq(query.getId(), Objects.nonNull(query.getId())))
                .and(SAMPLE.NAME.like(query.getName(), Objects.nonNull(query.getName())))
                .and(SAMPLE.CREATE_TIME.between(query.getStartDate(), query.getEndDate(), Objects.nonNull(query.getStartDate()) && Objects.nonNull(query.getEndDate())))
        );
    }

    default List<Sample> select2(SampleQueryDto query) {
        return this.selectListByQuery(QueryWrapper.create()
                .where(SAMPLE.ID.eq(query.getId(), Objects.nonNull(query.getId())))
                .or(SAMPLE.NAME.like(query.getName(), Objects.nonNull(query.getName())))
                .or(SAMPLE.CREATE_TIME.between(query.getStartDate(), query.getEndDate(), Objects.nonNull(query.getStartDate()) && Objects.nonNull(query.getEndDate())))
        );
    }

    default List<Sample> select3(SampleQueryDto query) {
        return this.selectListByQuery(QueryWrapper.create()
                .where(SAMPLE.CREATE_TIME.between(query.getStartDate(), query.getEndDate(), Objects.nonNull(query.getStartDate()) && Objects.nonNull(query.getEndDate())))
                .and(SAMPLE.ID.eq(query.getId(), Objects.nonNull(query.getId()))
                        .or(SAMPLE.NAME.like(query.getName(), Objects.nonNull(query.getName()))))
        );
    }
}

六、【Spring Data JPA】Specification方式

定义仓库接口,使用Spring Data JPA Specification构建查询条件:

import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
import org.springframework.util.CollectionUtils;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * 示例仓库(Specification)
 *
 * @author luohq
 * @date 2024-11-25 13:01
 * @link https://docs.spring.io/spring-data/jpa/reference/jpa/specifications.html
 */
public interface SampleRepo1 extends JpaRepository<Sample, String>, JpaSpecificationExecutor<Sample>, QuerydslPredicateExecutor<Sample> {

    default List<Sample> select1(SampleQuery query) {
        //构建查询条件
        Specification<Sample> specification = new Specification<>() {
            @Override
            public Predicate toPredicate(Root<Sample> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {
                List<Predicate> predicates = new ArrayList<>(3);
                if (Objects.nonNull(query.getId())) {
                    predicates.add(cb.equal(root.get("id"), query.getId()));
                }
                if (Objects.nonNull(query.getName())) {
                    predicates.add(cb.like(root.get("name"), "%" + query.getName() + "%"));
                }
                if (Objects.nonNull(query.getStartDate()) && Objects.nonNull(query.getEndDate())) {
                    predicates.add(cb.between(root.get("createTime"), query.getStartDate(), query.getEndDate()));
                }
                return cb.and(predicates.toArray(Predicate[]::new));
            }
        };
        //执行查询
        return this.findAll(specification);
    }

    default List<Sample> select2(SampleQuery query) {
        //构建查询条件
        Specification<Sample> specification = new Specification<>() {
            @Override
            public Predicate toPredicate(Root<Sample> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {
                List<Predicate> predicates = new ArrayList<>(3);
                if (Objects.nonNull(query.getId())) {
                    predicates.add(cb.equal(root.get("id"), query.getId()));
                }
                if (Objects.nonNull(query.getName())) {
                    predicates.add(cb.like(root.get("name"), "%" + query.getName() + "%"));
                }
                if (Objects.nonNull(query.getStartDate()) && Objects.nonNull(query.getEndDate())) {
                    predicates.add(cb.between(root.get("createTime"), query.getStartDate(), query.getEndDate()));
                }
                if (CollectionUtils.isEmpty(predicates)) {
                    //默认添加一个成立条件,避免多个or条件为空时拼接0=1
                    predicates.add(cb.equal(cb.literal(1), 1));
                }
                return cb.or(predicates.toArray(Predicate[]::new));
            }
        };
        //执行查询
        return this.findAll(specification);
    }

    default List<Sample> select3(SampleQuery query) {
        //构建查询条件
        Specification<Sample> specification = new Specification<>() {
            @Override
            public Predicate toPredicate(Root<Sample> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {
                List<Predicate> predicates = new ArrayList<>(2);
                if (Objects.nonNull(query.getId())) {
                    predicates.add(cb.equal(root.get("id"), query.getId()));
                }
                if (Objects.nonNull(query.getName())) {
                    predicates.add(cb.like(root.get("name"), "%" + query.getName() + "%"));
                }
                if (CollectionUtils.isEmpty(predicates)) {
                    //默认添加一个成立条件,避免多个or条件为空时拼接0=1
                    predicates.add(cb.equal(cb.literal(1), 1));
                }
                Predicate group1 = cb.or(predicates.toArray(Predicate[]::new));


                predicates = new ArrayList<>(1);
                if (Objects.nonNull(query.getStartDate()) && Objects.nonNull(query.getEndDate())) {
                    predicates.add(cb.between(root.get("createTime"), query.getStartDate(), query.getEndDate()));
                }
                Predicate group2 = cb.and(predicates.toArray(Predicate[]::new));

                return cb.and(group1, group2);
            }
        };
        //执行查询
        return this.findAll(specification);
    }
}

七、【Spring Data JPA】Specification & MetaModel方式

定义仓库接口,使用Spring Data JPA Specification 和 动态生成的JPA元模型 构建查询条件:

import com.luo.po.Sample;
import com.luo.po.Sample_;
import com.luo.query.SampleQuery;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
import org.springframework.util.CollectionUtils;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * 示例仓库(Specification、MetaModel)
 *
 * @author luohq
 * @date 2024-11-25 13:01
 * @link https://docs.spring.io/spring-data/jpa/reference/jpa/specifications.html
 * @link https://docs.jboss.org/hibernate/jpamodelgen/1.3/reference/en-US/html_single/
 */
public interface SampleRepo2 extends JpaRepository<Sample, String>, JpaSpecificationExecutor<Sample>, QuerydslPredicateExecutor<Sample> {

    default List<Sample> select1(SampleQuery query) {
        //构建查询条件
        Specification<Sample> specification = new Specification<>() {
            @Override
            public Predicate toPredicate(Root<Sample> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {
                List<Predicate> predicates = new ArrayList<>(3);
                if (Objects.nonNull(query.getId())) {
                    predicates.add(cb.equal(root.get(Sample_.ID), query.getId()));
                }
                if (Objects.nonNull(query.getName())) {
                    predicates.add(cb.like(root.get(Sample_.NAME), "%" + query.getName() + "%"));
                }
                if (Objects.nonNull(query.getStartDate()) && Objects.nonNull(query.getEndDate())) {
                    predicates.add(cb.between(root.get(Sample_.CREATE_TIME), query.getStartDate(), query.getEndDate()));
                }
                return cb.and(predicates.toArray(Predicate[]::new));
            }
        };
        //执行查询
        return this.findAll(specification);
    }

    default List<Sample> select2(SampleQuery query) {
        //构建查询条件
        Specification<Sample> specification = new Specification<>() {
            @Override
            public Predicate toPredicate(Root<Sample> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {
                List<Predicate> predicates = new ArrayList<>(3);
                if (Objects.nonNull(query.getId())) {
                    predicates.add(cb.equal(root.get(Sample_.ID), query.getId()));
                }
                if (Objects.nonNull(query.getName())) {
                    predicates.add(cb.like(root.get(Sample_.NAME), "%" + query.getName() + "%"));
                }
                if (Objects.nonNull(query.getStartDate()) && Objects.nonNull(query.getEndDate())) {
                    predicates.add(cb.between(root.get(Sample_.CREATE_TIME), query.getStartDate(), query.getEndDate()));
                }
                if (CollectionUtils.isEmpty(predicates)) {
                    //默认添加一个成立条件,避免多个or条件为空时拼接0=1
                    predicates.add(cb.equal(cb.literal(1), 1));
                }
                return cb.or(predicates.toArray(Predicate[]::new));
            }
        };
        //执行查询
        return this.findAll(specification);
    }

    default List<Sample> select3(SampleQuery query) {
        //构建查询条件
        Specification<Sample> specification = new Specification<>() {
            @Override
            public Predicate toPredicate(Root<Sample> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {
                List<Predicate> predicates = new ArrayList<>(2);
                if (Objects.nonNull(query.getId())) {
                    predicates.add(cb.equal(root.get(Sample_.ID), query.getId()));
                }
                if (Objects.nonNull(query.getName())) {
                    predicates.add(cb.like(root.get(Sample_.NAME), "%" + query.getName() + "%"));
                }
                if (CollectionUtils.isEmpty(predicates)) {
                    //默认添加一个成立条件,避免多个or条件为空时拼接0=1
                    predicates.add(cb.equal(cb.literal(1), 1));
                }
                Predicate group1 = cb.or(predicates.toArray(Predicate[]::new));


                predicates = new ArrayList<>(1);
                if (Objects.nonNull(query.getStartDate()) && Objects.nonNull(query.getEndDate())) {
                    predicates.add(cb.between(root.get(Sample_.CREATE_TIME), query.getStartDate(), query.getEndDate()));
                }
                Predicate group2 = cb.and(predicates.toArray(Predicate[]::new));

                return cb.and(group1, group2);
            }
        };
        //执行查询
        return this.findAll(specification);
    }
}

八、【Spring Data JPA】QueryDsl方式

定义仓库接口,使用 Spring Data JPA 和 QueryDsl 构建查询条件:

import com.luo.po.Sample;
import static com.luo.po.QSample.sample;
import com.luo.query.SampleQuery;
import com.querydsl.core.types.Predicate;
import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.core.types.dsl.Expressions;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.querydsl.QuerydslPredicateExecutor;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

/**
 * 示例仓库(Specification、QueryDsl)
 *
 * @author luohq
 * @date 2024-11-25 13:01
 * @link https://docs.spring.io/spring-data/jpa/reference/jpa/specifications.html
 * @link https://docs.spring.io/spring-data/jpa/reference/repositories/core-extensions.html#core.extensions.querydsl
 */
public interface SampleRepo3 extends JpaRepository<Sample, String>, JpaSpecificationExecutor<Sample>, QuerydslPredicateExecutor<Sample> {

    default List<Sample> select1(SampleQuery query) {
        //Predicate predicate = sample.id.eq(query.getId())
        //        .and(sample.name.contains(query.getName()))
        //        .and(sample.createTime.between(query.getStartDate(), query.getEndDate()));

        //构建查询条件
        List<BooleanExpression> predicates = new ArrayList<>();
        if (query.getId() != null) {
            predicates.add(sample.id.eq(query.getId()));
        }
        if (query.getName() != null) {
            predicates.add(sample.name.contains(query.getName()));
        }
        if (query.getStartDate() != null && query.getEndDate() != null) {
            predicates.add(sample.createTime.between(query.getStartDate(), query.getEndDate()));
        }
        //避免空指针异常
        if (predicates.isEmpty()) {
            predicates.add(Expressions.asBoolean(true).isTrue());
        }
        //合并查询条件
        BooleanExpression predicate = Expressions.allOf(predicates.toArray(new BooleanExpression[predicates.size()]));

        //执行查询
        Iterable<Sample> all = this.findAll(predicate);

        return StreamSupport.stream(all.spliterator(), false)
                .collect(Collectors.toList());
    }

    default List<Sample> select2(SampleQuery query) {
        //Predicate predicate = sample.id.eq(query.getId())
        //        .or(sample.name.contains(query.getName()))
        //        .or(sample.createTime.between(query.getStartDate(), query.getEndDate()));

        //构建查询条件
        List<BooleanExpression> predicates = new ArrayList<>();
        if (query.getId() != null) {
            predicates.add(sample.id.eq(query.getId()));
        }
        if (query.getName() != null) {
            predicates.add(sample.name.contains(query.getName()));
        }
        if (query.getStartDate() != null && query.getEndDate() != null) {
            predicates.add(sample.createTime.between(query.getStartDate(), query.getEndDate()));
        }
        //避免空指针异常
        if (predicates.isEmpty()) {
            predicates.add(Expressions.asBoolean(true).isTrue());
        }
        //合并查询条件
        BooleanExpression predicate = Expressions.anyOf(predicates.toArray(new BooleanExpression[predicates.size()]));

        //执行查询
        Iterable<Sample> all = this.findAll(predicate);

        return StreamSupport.stream(all.spliterator(), false)
                .collect(Collectors.toList());

    }

    default List<Sample> select3(SampleQuery query) {
        //Predicate predicate = sample.createTime.between(query.getStartDate(), query.getEndDate())
        //        .and(sample.id.eq(query.getId())
        //                .or(sample.name.contains(query.getName()))
        //        );

        //构建查询条件 - 分组1
        List<BooleanExpression> predicates = new ArrayList<>();
        if (query.getStartDate() != null && query.getEndDate() != null) {
            predicates.add(sample.createTime.between(query.getStartDate(), query.getEndDate()));
        }
        //避免空指针异常
        if (predicates.isEmpty()) {
            predicates.add(Expressions.asBoolean(true).isTrue());
        }
        //合并查询条件
        BooleanExpression group1 = Expressions.allOf(predicates.toArray(new BooleanExpression[predicates.size()]));

        //构建查询条件 - 分组2
        predicates = new ArrayList<>();
        if (query.getId() != null) {
            predicates.add(sample.id.eq(query.getId()));
        }
        if (query.getName() != null) {
            predicates.add(sample.name.contains(query.getName()));
        }
        //避免空指针异常
        if (predicates.isEmpty()) {
            predicates.add(Expressions.asBoolean(true).isTrue());
        }
        //合并查询条件
        BooleanExpression group2 = Expressions.anyOf(predicates.toArray(new BooleanExpression[predicates.size()]));

        //合并分组条件
        Predicate predicate = Expressions.allOf(group1, group2);
        //执行查询
        Iterable<Sample> all = this.findAll(predicate);
        return StreamSupport.stream(all.spliterator(), false)
                .collect(Collectors.toList());
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/924736.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

微前端-MicroApp

微前端即是由一个主应用来集成多个微应用&#xff08;可以不区分技术栈进行集成&#xff09; 下面是使用微前端框架之一 MicroApp 对 react微应用 的详细流程 第一步 创建主应用my-mj-app 利用脚手架 npx create-react-app my-mj-app 快速创建 安装 npm install --save rea…

深度学习—BP算法梯度下降及优化方法Day37

梯度下降 1.公式 w i j n e w w i j o l d − α ∂ E ∂ w i j w_{ij}^{new} w_{ij}^{old} - \alpha \frac{\partial E}{\partial w_{ij}} wijnew​wijold​−α∂wij​∂E​ α为学习率 当α过小时&#xff0c;训练时间过久增加算力成本&#xff0c;α过大则容易造成越过最…

wp the_posts_pagination 与分类页面搭配使用

<ul> <?php while( have_posts() ) : the_post(); <li > <a href"<?php the_permalink(); ?>"> <?php xizhitbu_get_thumbnail(thumb-pro); ?> </a> <p > <a href&q…

深度学习-49-AI应用实战之基于HyperLPR的车牌识别

文章目录 1 车牌识别系统1.1 识别原理1.1.1 车牌定位1.1.2 字符识别2 实例应用2.1 安装hyperlpr32.2 识别结果2.3 可视化显示2.4 结合streamlit3 附录3.1 PIL.Image转换成OpenCV格式3.2 OpenCV转换成PIL.Image格式3.3 st.image嵌入图像内容3.4 参考附录1 车牌识别系统 车牌识别…

ShuffleNet V2:高效卷积神经网络架构设计的实用指南

摘要 https://arxiv.org/pdf/1807.11164 当前&#xff0c;神经网络架构设计大多以计算复杂度的间接指标&#xff0c;即浮点运算数&#xff08;FLOPs&#xff09;为指导。然而&#xff0c;直接指标&#xff08;例如速度&#xff09;还取决于其他因素&#xff0c;如内存访问成本…

在C#中使用OpenCV的.net包装器EmguCV

Emgu.CV OpenCvSharp 两个库都是OpenCV的C#封装。这里不讨论优劣&#xff0c;两个都有相应的用途。 下载安装4.6.0.5131&#xff0c;执行文件exe https://sourceforge.net/projects/emgucv/files/emgucv/4.6.0/ 安装到一个目录下&#xff0c;这里安装到H:\Emgu\ 目录下。…

HarmonyOS:@Provide装饰器和@Consume装饰器:与后代组件双向同步

一、前言 Provide和Consume&#xff0c;应用于与后代组件的双向数据同步&#xff0c;应用于状态数据在多个层级之间传递的场景。不同于上文提到的父子组件之间通过命名参数机制传递&#xff0c;Provide和Consume摆脱参数传递机制的束缚&#xff0c;实现跨层级传递。 其中Provi…

webrtc 3A移植以及实时处理

文章目录 前言一、交叉编译1.Pulse Audio webrtc-audio-processing2.交叉编译 二、基于alsa进行实时3A处理1.demo源码2.注意项3.效果展示 总结 前言 由于工作需要&#xff0c;硬件3A中的AEC效果实在太差&#xff0c;后面使用SpeexDSP的软3A&#xff0c;效果依旧不是很好&#…

Java 反射(Reflection)

Java 反射&#xff08;Reflection&#xff09; Java 反射&#xff08;Reflection&#xff09;是一个强大的特性&#xff0c;它允许程序在运行时查询、访问和修改类、接口、字段和方法的信息。反射提供了一种动态地操作类的能力&#xff0c;这在很多框架和库中被广泛使用&#…

深入浅出剖析典型文生图产品Midjourney

2022年7月,一个小团队推出了公测的 Midjourney,打破了 AIGC 领域的大厂垄断。作为一个精调生成模型,以聊天机器人方式部署在 Discord,它创作的《太空歌剧院》作品,甚至获得了美国「数字艺术/数码摄影」竞赛单元一等奖。 这一事件展示了 AI 在绘画领域惊人的创造力,让人们…

【Linux】磁盘 | 文件系统 | inode

&#x1fa90;&#x1fa90;&#x1fa90;欢迎来到程序员餐厅&#x1f4ab;&#x1f4ab;&#x1f4ab; 主厨&#xff1a;邪王真眼 主厨的主页&#xff1a;Chef‘s blog 所属专栏&#xff1a;青果大战linux 总有光环在陨落&#xff0c;总有新星在闪烁 模电好难啊&#xff…

PHP 去掉特殊不可见字符 “\u200e“

描述 最近在排查网站业务时&#xff0c;发现有数据匹配失败的情况 肉眼上完全看不出问题所在 当把字符串 【M24308/23-14F‎】复制出来发现 末尾有个不可见的字符 使用删除键或左右移动时才会发现 最后测试通过 var_dump 打印 发现这个"空字符"占了三个长度 &#xf…

【C#设计模式(15)——命令模式(Command Pattern)】

前言 命令模式的关键通过将请求封装成一个对象&#xff0c;使命令的发送者和接收者解耦。这种方式能更方便地添加新的命令&#xff0c;如执行命令的排队、延迟、撤销和重做等操作。 代码 #region 基础的命令模式 //命令&#xff08;抽象类&#xff09; public abstract class …

使用zabbix监控k8s

一、 参考文献 小阿轩yx-案例&#xff1a;Zabbix监控kubernetes云原生环境 手把手教你实现zabbix对Kubernetes的监控 二、部署经验 关于zabbix监控k8s&#xff0c;总体来说是分为两块内容&#xff0c;一是在k8s集群部署zabbix-agent和zabbix- proxy。二是在zabbix进行配置。…

ThingsBoard规则链节点:GCP Pub/Sub 节点详解

目录 引言 1. GCP Pub/Sub 节点简介 2. 节点配置 2.1 基本配置示例 3. 使用场景 3.1 数据传输 3.2 数据分析 3.3 事件通知 3.4 任务调度 4. 实际项目中的应用 4.1 项目背景 4.2 项目需求 4.3 实现步骤 5. 总结 引言 ThingsBoard 是一个开源的物联网平台&#xff0…

10.机器学习--集成学习

机器学习领域有一个强大的思路&#xff1a;集成学习&#xff0c;该方法在诸多机器学习竞赛中往往能够获得最优的结果。集成学习的基本思想实际上非常简单&#xff1a;三个臭皮匠顶一个诸葛亮&#xff0c;即将多个模型组合在一起获得的效果往往要强于单一模型。 目录 集成学习…

结构体详解+代码展示

系列文章目录 &#x1f388; &#x1f388; 我的CSDN主页:OTWOL的主页&#xff0c;欢迎&#xff01;&#xff01;&#xff01;&#x1f44b;&#x1f3fc;&#x1f44b;&#x1f3fc; &#x1f389;&#x1f389;我的C语言初阶合集&#xff1a;C语言初阶合集&#xff0c;希望能…

深度解析猎板 PCB树脂塞孔工艺

PCB 的树脂塞孔工艺是一种在印制电路板制造过程中广泛应用的重要技术&#xff0c;以下是猎板PCB批量工厂对PCB树脂塞孔该工艺的详细介绍&#xff1a; 猎板 PCB树脂塞孔工艺目的 防止短路&#xff1a;在 PCB 制造中&#xff0c;若过孔未被有效封堵&#xff0c;锡膏可能会从孔内…

扫雷-完整源码(C语言实现)

云边有个稻草人-CSDN博客 在学完C语言函数之后&#xff0c;我们就有能力去实现简易版扫雷游戏了&#xff08;成就感满满&#xff09;&#xff0c;下面是扫雷游戏的源码&#xff0c;快试一试效果如何吧&#xff01; 在test.c里面进行扫雷游戏的测试&#xff0c;game.h和game.c…

当前就业形势下C++方向后端开发学习指南

文章目录 1. C后端开发的职业方向1.1 C的应用领域1.2 后端开发的职业选择 2. 当前就业形势分析2.1 C开发者的市场需求2.2 C开发者的薪资水平 3. 学习路线3.1 入门阶段&#xff1a;掌握基础知识3.2 进阶阶段&#xff1a;掌握后端开发的核心技术3.2.1 数据库与C3.2.2 网络编程 3.…