简单模拟Mybatis通过注解查询SQL

这篇具有很好参考价值的文章主要介绍了简单模拟Mybatis通过注解查询SQL。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

通过自定义注解,简单模拟Mybatis通过注解查询SQL。

首先,创建自定义注解@MyDao和@MySelect。

MyDao.java

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyDao {
    String[] value() default {};
}

MySelect.java

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MySelect {
    String[] value() default {};
}

创建UserDao,使用上面的自定义注解。

UserDao.java

@MyDao
public interface UserDao {

    @MySelect("select * from sys_user where id = #{id}")
    String getNameById(String id);

}

MyInterceptor.java
处理@MySelect注解的方法实现。

@Slf4j
@Component
public class MyInterceptor implements InvocationHandler {

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        MySelect mySelect = method.getAnnotation(MySelect.class);
        if (mySelect != null) {
            String sql = mySelect.value()[0];
            // 解析sql中的参数
            Map<String, Object> paramMap = new HashMap<>();
            Parameter[] parameters = method.getParameters();
            for (int i = 0; i < parameters.length; i++) {
                paramMap.put(parameters[i].getName(), args[i]);
            }
            // 执行sql
            String workSql = format(sql, paramMap);
            log.info("work sql: {}", workSql);
        }
        return null;
    }


    /**
     * 替换sql中的参数
     */
    private String format(String str, Map<String, Object> paramMap) {
        if (MapUtil.isEmpty(paramMap)) {
            return str;
        }
        AtomicReference<String> text = new AtomicReference<>(str);
        paramMap.forEach((paramName, paramValue) -> {
            String value = String.valueOf(paramValue);
            if (paramValue instanceof String) {
                value = "'" + value + "'";
            }
            text.set(StringUtils.replace(text.get(), "#{" + paramName + "}", value));
        });
        return text.get();
    }
}

InterfaceDynamicRegister.java
处理@MyDao的注解的Mapper。

@Configuration
public class InterfaceDynamicRegister implements ImportBeanDefinitionRegistrar {
    private static final String BASE_PACKAGE = "com.jjh.business.mapper"; // 指定扫描的包路径
    private static final String RESOURCE_PATTERN = "/**/*.class"; // 指定扫描的文件类型

    @SneakyThrows
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

        // 扫描所有包含MyDao注解的类
        List<Class<?>> classes = new ArrayList<>();
        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
                ClassUtils.convertClassNameToResourcePath(BASE_PACKAGE) + RESOURCE_PATTERN;
        Resource[] resources = resolver.getResources(packageSearchPath);
        SimpleMetadataReaderFactory metadataReaderFactory = new SimpleMetadataReaderFactory();
        ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false);
        scanner.addIncludeFilter(new AnnotationTypeFilter(MyDao.class));
        for (Resource resource : resources) {
            if (resource.isReadable()) {
                MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(resource);
                String className = metadataReader.getClassMetadata().getClassName();
                Class<?> clazz = Class.forName(className);
                classes.add(clazz);
            }
        }
        // 创建接口的实现类并注册到spring
        for (Class<?> clazz : classes) {
            // 将代理类实例注册到 Spring 容器中
            BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(clazz);
            // 调用BeanDefinition的setInstanceSupplier方法,传入一个Lambda表达式,该表达式返回代理对象的实例
            builder.getBeanDefinition().setInstanceSupplier(() -> {
                // CGlib代理
                // Enhancer enhancer = new Enhancer();
                // enhancer.setSuperclass(clazz);
                // enhancer.setCallback(new MyInterceptor());
                // Object proxyInstance = enhancer.create();
                // return proxyInstance;

                // JDK代理
                return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class[]{clazz},
                        new MyInterceptor());
            });
            registry.registerBeanDefinition(clazz.getSimpleName(), builder.getBeanDefinition());
        }

    }
}

TestController.java
调用userDao,查询数据。

@Slf4j
@RestController
@RequestMapping("/test")
public class TestController {

    @Autowired
    private UserDao userDao;
    
    @GetMapping("/do_sql_select")
    public Object doSqlSelect() {
        log.info("do_sql_select is do. {}", System.currentTimeMillis());
        userDao.getNameById("0001");
        return "Ok";
    }
}

pom 依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

调用 http://localhost:8080/test/do_sql_select 即可执行userDao方法。文章来源地址https://www.toymoban.com/news/detail-601759.html

到了这里,关于简单模拟Mybatis通过注解查询SQL的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • MyBatis(多表查询,动态SQL的使用)

    目录 多表查询  查询文章详情 查询一个用户底下的所有文章 动态SQL的使用 if 标签 trim 标签  where 标签 set 标签 foreach 标签 现在有俩张表,一张是 文章表 ,一张是 用户表 .如下: 我们现在想查询得到一张表,表里面的内容和文章表大多一致,只是要 在文章表的基础上添加用户表中

    2024年02月10日
    浏览(36)
  • MyBatis动态SQL、模糊查询与结果映射

    目录 前言 一、MyBatis动态SQL 1.动态SQL是什么 2.动态SQL的作用 3.常用动态SQL元素 1. where + if 元素 2. set + if 元素 3. choose + when + otherwise 元素 4. 自定义 trim 元素  1. 自定义 trim 元素改写上面的 where + if 语句 2. 自定义 trim 元素改写上面的 set + if 语句 5. foreach 元素 6.SQL片段重用 二、

    2024年02月11日
    浏览(29)
  • mybatis xml多表查询,子查询,连接查询,动态sql

    student_type 表 student 表 Student 类 一个学生只有一个年级 Type 类 一个年级有多个学生,所以用 list 下列代码中: 1 resultMap 里面property对应实体类属性,column对应数据库字段名 2 主键用 id 标签 其他用result 3 关联查询(子查询和连接查询) 连接查询查一次 4 一个年级多个学生,所以

    2024年01月21日
    浏览(46)
  • 在mybatis-plus项目中自带要编写sql语句,@select注解的使用

    提示:在mybatisplus中编写sql语句有两种方法,我重点使用@select注释这种方法,还有一种是增加mapper.xml文件配置,这里不做讲解 现在mybatis-plus中已经封装了绝大部分简单sql,只用一部分负责sql需要自行编写,所以用@select的方式可以减少开发量,减少项目的复杂性。 @select是myb

    2023年04月12日
    浏览(36)
  • MyBatis进阶:掌握MyBatis动态SQL与模糊查询、结果映射,让你在面试中脱颖而出!!

    目录 一、引言 二、MyBatis动态SQL 2.1.if元素使用 2.2.foreach元素使用 三、MyBatis模糊查询 ①使用#{字段名} ②使用${字段名} ③使用concat{\\\'%\\\',#{字段名},\\\'%\\\'} 总结 四、MyBatis结果映射 4.1.案例演示 4.1.1.resultType进行结果映射 4.1.2.resultMap进行结果映射 在当今的软件开发环境中,数据库的使

    2024年02月11日
    浏览(37)
  • Mybatis 动态SQL条件查询(注释和XML方式都有)

    需求 : 根据用户的输入情况进行条件查询 新建了一个 userInfo2Mapper 接口,然后写下如下代码,声明 selectByCondition 这个方法 我们先用XML的方式实现 在resources 中创建 Userinfo2XMLMapper.xml 文件  将 Userinfo2XMLMapper.xml 文件中的 namespace 进行修改,改为 userInfo2Mapper 接口中的第一行 package 的

    2024年01月22日
    浏览(31)
  • Springboot 封装整活 Mybatis 动态查询条件SQL自动组装拼接

    ps:最近在参与3100保卫战,战况很激烈,刚刚打完仗,来更新一下之前写了一半的博客。 该篇针对日常写查询的时候,那些动态条件sql 做个简单的封装,自动生成(抛砖引玉,搞个小玩具,不喜勿喷)。 来看看我们平时写那些查询,基本上都要写的一些动态sql:   一个字段

    2024年02月12日
    浏览(20)
  • 【MyBatis 学习三】子段不一致问题 && 多表查询 && 动态SQL

    目录 一、解决Java实体类属性与数据库表字段不一致问题 🌷现象1:显示字段不对应:使用ResultType查询结果为null; 🌷解决办法:字段不对应:使用ResultMap解决。 二、数据库的多表查询 🌷方式1:使用对象user  🌷方式2:直接写具体的属性 三、动态SQL的使用 🌷1、if标签:单

    2024年02月15日
    浏览(27)
  • 通过实现MyBatis的Interceptor接口在SQL头部增加统一注释

    从事运维或DBA工作的童鞋会非常熟悉在SQL前部增加注释的操作。类似如下的SQL语句: 这种注释虽然不会影响SQL执行,但是会为运维和DBA工作带来极大的便利如: 对慢查询进行优化时,可以通过注释信息快速找到研发团队及研发人员,同时研发人员也可以快速定位到对应业务

    2024年02月03日
    浏览(34)
  • MyBatis案例 | 使用映射配置文件实现CRUD操作——动态SQL优化条件查询

    本专栏主要是记录学习完JavaSE后学习JavaWeb部分的一些知识点总结以及遇到的一些问题等,如果刚开始学习Java的小伙伴可以点击下方连接查看专栏 本专栏地址:🔥JavaWeb Java入门篇: 🔥Java基础学习篇 Java进阶学习篇(持续更新中):🔑Java进阶学习篇 本系列文章会将讲述有关

    2024年02月02日
    浏览(66)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包