简单模拟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 {@Overridepublic 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]);}// 执行sqlString 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@Overridepublic 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);}}// 创建接口的实现类并注册到springfor (Class<?> clazz : classes) {// 将代理类实例注册到 Spring 容器中BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(clazz);// 调用BeanDefinition的setInstanceSupplier方法,传入一个Lambda表达式,该表达式返回代理对象的实例builder.getBeanDefinition().setInstanceSupplier(() -> {Enhancer enhancer = new Enhancer();enhancer.setSuperclass(clazz);enhancer.setCallback(new MyInterceptor());Object proxyInstance = enhancer.create();return proxyInstance;});registry.registerBeanDefinition(clazz.getSimpleName(), builder.getBeanDefinition());}}
}

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

@Slf4j
@RestController
@RequestMapping("/test")
public class TestController {@Autowiredprivate 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方法。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AI面试官:LINQ和Lambda表达式(一)

AI面试官&#xff1a;LINQ和Lambda表达式&#xff08;一&#xff09; 当面试官面对C#中关于LINQ和Lambda表达式的面试题时&#xff0c;通常会涉及这两个主题的基本概念、用法、实际应用以及与其他相关技术的对比等。以下是一些可能的面试题目&#xff0c;附带简要解答和相关案…

HTML <option> 标签

实例 创建带有 4 个选项的选择列表: <select><option value ="volvo">Volvo</option><option value ="saab">Saab</option><option value="opel">Opel</option><option value="audi"…

Server - 调用 K8S 集群 GPU 环境运行算法脚本

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://blog.csdn.net/caroline_wendy/article/details/131899662 Kubeflow 是基于 Kubernetes 的机器学习工具包&#xff0c;提供了一套技术栈&#xff0c;包含了很多组件&#xff0c;用于支持…

使用RestTemplate访问内部服务时返回的json字符串未做转换处理之后再次返回json字符到前台导致json字符串无法解析的解决办法

1. 以下是使用RestTemplate调用接口的方法 RequestMapping("/getQrList") //获取qrlable列表String getQrList(Qr qr) {//返回的数据本身就是 ResponBody也就是json&#xff0c;当前方法再次返回json&#xff0c;就会导致导出时无法解析数据&#xff08;table是能…

SQL SERVER安装

其中服务器名称输入./自己本机电脑名称. nchar类型一个单位可以放一个汉字-------长度短的补空格一个字节8位一个汉字两个字节 char类型两个单位可以放一个汉字 nvarchar类型是可变长度-----------长度短不会补空格 varchar类型是可变长度两个单位可以放一个汉字---------…

GStreamer Basic tutorial 学习笔记(十三)

1 播放速度 GStreamer提供了两种改变播放速度的机制&#xff1a;步进事件&#xff08;Step Events&#xff09;和搜索事件&#xff08;Seek Events&#xff09;。步进事件允许跳过一定量的媒体&#xff0c;并改变随后的播放速度&#xff08;只能为正值&#xff09;。搜索事件还…

“深入解析Spring Boot:从入门到实战“

标题&#xff1a;深入解析Spring Boot&#xff1a;从入门到实战 摘要&#xff1a;本篇博客将深入解析Spring Boot&#xff0c;从入门到实战&#xff0c;帮助读者了解Spring Boot的核心概念、特性和使用方法&#xff0c;并通过示例代码演示如何使用Spring Boot开发一个简单的We…

Python3 unittest学习

Python3 unittest学习 unittest单元测试框架基本结构执行测试普通方式执行通过unittest模块执行 跳过测试与预期失败使用子测试区分测试迭代类与函数class unittest.TestCase(methodNamerunTest)用于运行测试的方法断言方法其他方法和属性 class unittest.IsolatedAsyncioTestC…

JVM五大内存模型

什么是JVM JVM是Java Virtual Machine&#xff08;Java虚拟机&#xff09;的缩写&#xff0c;JVM是一个虚构出来的计算机&#xff0c;有着自己完善的硬件架构&#xff0c;如处理器、堆栈等。 JVM的作用 Java语言使用Java虚拟机屏蔽了与具体平台相关的信息&#xff0c;使得Jav…

Istio Pilot源码学习(三):xDS的异步分发

本文基于Istio 1.18.0版本进行源码学习 5、xDS的异步分发 DiscoveryService主要包含下述逻辑&#xff1a; 启动GRPC Server并接收来自Envoy端的连接请求接收Envoy端的xDS请求&#xff0c;从ConfigController和ServiceController中获取配置和服务信息&#xff0c;生成响应消息…

文心一言 VS 讯飞星火 VS chatgpt (64)-- 算法导论6.5 3题

文心一言 VS 讯飞星火 VS chatgpt &#xff08;64&#xff09;-- 算法导论6.5 3题 三、要求用最小堆实现最小优先队列&#xff0c;请写出 HEAP-MINIMUM、HEAP-EXTRACT-MIN、HEAP DECREASE-KEY 和 MIN-HEAP-INSERT 的伪代码。 文心一言&#xff1a; 以下是使用最小堆实现最小…

国内攻克OLED屏幕修复术,成本暴降2/3不用拆机换屏

连着许多年各家手机发布会&#xff0c;屏幕基本是会花大精力宣传的三大件之一 也对&#xff0c;无论是外观还是实际的视觉、操作体验&#xff0c;屏幕都是非常重要的一环。 屏幕素质越来越高&#xff0c;用着也的确更爽了&#xff0c;但也越来越不敢摔了。 普普通通的一块 60…

【传感器】应用充气泵方案的压力传感器

压力传感器&#xff0c;是指以膜片装置&#xff08;不锈钢膜片、硅酮膜片等&#xff09;为媒介&#xff0c;用感压元件对气体和液体的压力进行测量&#xff0c;并转换成电气信号输出的设备。其原理是半导体压电阻抗扩散压力传感器是在薄片表面形成半导体变形压力&#xff0c;通…

SNMP协议是什么?

SNMP协议是什么&#xff1f; 简单网络管理协议&#xff08;Simple Network Management Protocol&#xff0c;SNMP&#xff09;是由互联网工程任务组定义的一套网络管理协议。该协议是基于简单网关监视协议&#xff08;Simple Gateway Monitor Protocol&#xff0c;SGMP&#x…

ChatGPT助力校招----面试问题分享(十二)

1 ChatGPT每日一题&#xff1a;运算放大器与比较器的区别 问题&#xff1a;运算放大器与比较器的区别 ChatGPT&#xff1a;运算放大器和比较器都是电子电路中常用的模拟电路元件&#xff0c;但它们的设计和应用略有不同。下面是两者的主要区别&#xff1a; 功能不同&#xf…

TC3XX - MCAL知识点(十一):WDG EB-tresos配置说明与代码浅析

目录 1、概述 1.1、简介 1.2、Safety Watchdog 1.3、CPU Watchdogs 1.4、看门狗定时器的功能列表

服务器负载均衡算法有哪些

算法举例 服务器负载均衡算法是用于分配网络流量到多个服务器的策略&#xff0c;以实现负载均衡和提高系统性能。以下是一些常见的服务器负载均衡算法的详细说明&#xff1a; 轮询&#xff08;Round Robin&#xff09;算法&#xff1a; 轮询算法是最简单且常见的负载均衡算法之…

2.python设计模式【面向对象设计的SOLID原则 基础概念】

1.可放封闭原则 概念&#xff1a;一个软件实体如类、模块和函数应该对扩展开放&#xff0c;对修改关闭。即软件实体应该尽量在不修改原有代码的情况下进行扩展 2.里式替换原则 概念&#xff1a;所有引用父类的地方必须能透明地使用其子类的对象 3.依赖倒置原则 概念&#…

qs.stringify() 和 JSON.stringfy 的区别

qs 是 nodejs 的一个模块。qs.stringify()常用于对象转url参数&#xff1b;qs.parse()常用户url参数转对象&#xff1b; JSON.stringfy是js自带的方法。 JSON.stringify()用于对象转字符串&#xff1b;JSON.parse()用于字符串转对象&#xff1b; 两者都能进行序列化&#xff0c…