自己实现简单版的注解Mybatis
Mybatis属于ORM(Object Relational Mapping)框架,将java对象和关系型数据库建立映射关系,方便对数据库进行操作,其底层还是对jdbc的封装。
实现的思路是:
1 定义注解,对Dao中的方法进行标注
2 为Dao创建代理类
3 在invocationHandler中对进行具体的逻辑操作
@Target({ ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface ExtInsert {
String value();
}
public interface UserDao {
@ExtSelect("select * from User where userName=#{userName} and userAge=#{userAge} ")
User selectUser(@ExtParam("userName") String name, @ExtParam("userAge") Integer userAge);
@ExtInsert("insert into user(userName,userAge) values(#{userName},#{userAge})")
int insertUser(@ExtParam("userAge") Integer userAge, @ExtParam("userName") String name);
@ExtDelete("delete from user where userName=#{userName} ")
void deleteUserByUserName(@ExtParam("userName") String name);
@ExtUpdate("update user set userAge = #{userAge} where userName = #{userName} ")
void updateUser(@ExtParam("userAge") Integer userAge, @ExtParam("userName") String name);
}
public class SqlSession {
// 获取getMapper
@SuppressWarnings("unchecked")
public static <T> T getMapper(Class<T> clz)
throws IllegalArgumentException, InstantiationException, IllegalAccessException {
return (T) Proxy.newProxyInstance(clz.getClassLoader(), new Class[] { clz },
new MyInvocationHandlerMbatis(clz));
}
}
public class MyInvocationHandlerMbatis implements InvocationHandler {
/**
* 这个就是我们要代理的真实对象
*/
private Object subject;
/**
* 构造方法,给我们要代理的真实对象赋初值
*
* @param subject
*/
public MyInvocationHandlerMbatis(Object subject) {
this.subject = subject;
}
/**
* 该方法负责集中处理动态代理类上的所有方法调用。 调用处理器根据这三个参数进行预处理或分派到委托类实例上反射执行
*
* @param proxy
* 代理类实例
* @param method
* 被调用的方法对象
* @param args
* 调用参数
* @return
* @throws Throwable
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 判断方法上是否有ExtInsert注解
ExtInsert extInsert = method.getAnnotation(ExtInsert.class);
if (extInsert != null) {
return insertSQL(extInsert, method, args);
}
// 判断方法上是否有ExtSelect注解
ExtSelect extSelect = method.getAnnotation(ExtSelect.class);
if (extSelect != null) {
return selectMybatis(extSelect, method, args);
}
// 判断方法上是否有ExtDelete注解
ExtDelete extDelete = method.getAnnotation(ExtDelete.class);
if(extDelete != null) {
deleteSQL(extDelete,method,args);
return null;
}
// 判断方法上是否有ExtUpdate注解
ExtUpdate extUpdate = method.getAnnotation(ExtUpdate.class);
if(extUpdate != null) {
updateSQL(extUpdate,method,args);
return null;
}
return null;
}
private void updateSQL(ExtUpdate extUpdate, Method method, Object[] args) {
// 获取注解上的sql
String updateSql = extUpdate.value();
System.out.println("sql:" + updateSql);
// 获取方法上的参数
Parameter[] parameters = method.getParameters();
// 将方法上的参数存放在Map集合中
ConcurrentHashMap<Object, Object> parameterMap = getExtParams(parameters, args);
// 获取SQL语句上需要传递的参数 ,即获取的是#{userName} 里的userName
String[] sqlParameter = SQLUtils.sqlUpdateParameter(updateSql);
List<Object> parameValues = new ArrayList<>();
for (int i = ; i < sqlParameter.length; i++) {
String str = sqlParameter[i];
Object object = parameterMap.get(str);
parameValues.add(object);
}
String newSql = SQLUtils.parameQuestion(updateSql, sqlParameter);
System.out.println("newSql:" + newSql);
// 调用jdbc代码执行 , 第二个参数false表示返回的是影响的行数
JDBCUtils.execute(newSql, parameValues.get(),parameValues.get());
}
private void deleteSQL(ExtDelete extDelete, Method method, Object[] args) {
//获取注解上的sql
String deleteSql = extDelete.value();
System.out.println("sql:" + deleteSql);
// 将SQL语句替换为?号
String newSql = SQLUtils.parameQuestion(deleteSql, new String[] {"userName"});
System.out.println("newSql:" + newSql);
// 调用jdbc代码执行 , 第二个参数false表示返回的是影响的行数
JDBCUtils.execute(newSql, args[]);
}
public int insertSQL(ExtInsert extInsert, Method method, Object[] args) {
// 获取注解上的sql
String insertSql = extInsert.value();
System.out.println("sql:" + insertSql);
// 获取方法上的参数
Parameter[] parameters = method.getParameters();
// 将方法上的参数存放在Map集合中
ConcurrentHashMap<Object, Object> parameterMap = getExtParams(parameters, args);
// 获取SQL语句上需要传递的参数 ,即获取的是#{userName} 里的userName
String[] sqlParameter = SQLUtils.sqlInsertParameter(insertSql);
List<Object> parameValues = new ArrayList<>();
for (int i = ; i < sqlParameter.length; i++) {
String str = sqlParameter[i];
Object object = parameterMap.get(str);
parameValues.add(object);
}
// 将SQL语句替换为?号
String newSql = SQLUtils.parameQuestion(insertSql, sqlParameter);
System.out.println("newSql:" + newSql);
// 调用jdbc代码执行 , 第二个参数false表示返回的是影响的行数
int insertResult = JDBCUtils.insert(newSql, false, parameValues);
return insertResult;
}
public Object selectMybatis(ExtSelect extInsert, Method method, Object[] args) throws SQLException {
try {
// 获取查询SQL语句
String selectSQL = extInsert.value();
// 将方法上的参数存放在Map集合中
Parameter[] parameters = method.getParameters();
// 获取方法上参数集合
ConcurrentHashMap<Object, Object> parameterMap = getExtParams(parameters, args);
// 获取SQL传递参数
List<String> sqlSelectParameter = SQLUtils.sqlSelectParameter(selectSQL);
// 排序参数
List<Object> parameValues = new ArrayList<>();
for (int i = ; i < sqlSelectParameter.size(); i++) {
String parameterName = sqlSelectParameter.get(i);
Object object = parameterMap.get(parameterName);
parameValues.add(object.toString());
}
// 变为?号
String newSql = SQLUtils.parameQuestion(selectSQL, sqlSelectParameter);
System.out.println("执行SQL:" + newSql + "参数信息:" + parameValues.toString());
// 调用JDBC代码查询
ResultSet rs = JDBCUtils.query(newSql, parameValues);
// 获取返回类型
Class<?> returnType = method.getReturnType();
if (!rs.next()) {
// 没有查找数据
return null;
}
// 向上移动
rs.previous();
// 实例化对象
Object newInstance = returnType.newInstance();
while (rs.next()) {
for (String parameterName : sqlSelectParameter) {
// 获取集合中数据
Object value = rs.getObject(parameterName);
// 查找对应属性
Field field = returnType.getDeclaredField(parameterName);
// 设置允许私有访问
field.setAccessible(true);
// 赋值参数
field.set(newInstance, value);
}
}
return newInstance;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private ConcurrentHashMap<Object, Object> getExtParams(Parameter[] parameters, Object[] args) {
// 获取方法上参数集合
ConcurrentHashMap<Object, Object> parameterMap = new ConcurrentHashMap<>();
for (int i = ; i < parameters.length; i++) {
// 参数信息
Parameter parameter = parameters[i];
ExtParam extParam = parameter.getDeclaredAnnotation(ExtParam.class);
// 参数名称
String paramValue = extParam.value();
// 参数值
Object oj = args[i];
parameterMap.put(paramValue, oj);
}
return parameterMap;
}
}
项目结构:
jdbc工具类,
在一个字符串中找出含有特殊符号的多个子串的工具方法
利用jdk动态代理创建代理对象

github地址: https://github.com/jake1263/MYORM
自己实现简单版的注解Mybatis的更多相关文章
- Mybatis中使用association及collection进行自关联示例(含XML版与注解版)
XML版本: 实体类: @Data @ToString @NoArgsConstructor public class Dept { private Integer id; private Strin ...
- Mybatis中使用collection进行多对多双向关联示例(含XML版与注解版)
Mybatis中使用collection进行多对多双向关联示例(含XML版与注解版) XML版本: 实体类: @Data @NoArgsConstructor public class Course ...
- SSM 框架-06-详细整合教程(IDEA版)(Spring+SpringMVC+MyBatis)
SSM 框架-06-详细整合教程(IDEA版)(Spring+SpringMVC+MyBatis) SSM(Spring.Spring MVC和Mybatis)如果你使用的是 Eclipse,请查看: ...
- SSM 框架-05-详细整合教程(Eclipse版)(Spring+SpringMVC+MyBatis)
SSM 框架-05-详细整合教程(Eclipse版)(Spring+SpringMVC+MyBatis) 如果你使用的是 Intellij IDEA,请查看: SSM的配置流程详细的写了出来,方便很少 ...
- JavaMail简单版实验测试
前言: 最近由于实现web商城的自动发送邮件功能的需求,故涉猎的邮箱协议的内部原理.现将简单版的Java Mail实例做个代码展示,并附上其中可能出现的bug贴出,方便感兴趣的读者进行测试! 1.载入 ...
- 小米抢购(简单版v0.1)-登录并验证抢购权限,以及获取真实抢购地址
小米(简单版)-登录并验证抢购权限,以及获取真实抢购地址! 并不是复制到浏览器就行了的 还得传递所需要的参数 这里只是前部分 后面的自己发挥了 { "stime": 1389 ...
- Java实现简单版SVM
Java实现简单版SVM 近期的图像分类工作要用到latent svm,为了更加深入了解svm,自己动手实现一个简单版的. 之所以说是简单版,由于没实用到拉格朗日,对偶,核函数等等.而 ...
- MySQL数据库执行计划(简单版)
+++++++++++++++++++++++++++++++++++++++++++标题:MySQL数据库执行计划简单版时间:2019年2月25日内容:MySQL数据库执行计划简单版重点:MySQL ...
- 红警大战JAVA简单版
代码结构: 相关源码: 武器类: 属性:武器,攻击力,子弹数量. 方法:给属性赋值(set属性()方法) 获取属性值(get属性()方法) package 红警大战简单版; public class ...
随机推荐
- rsync提权
介绍:Rsync是linux下一款数据备份工具,默认开启873端口 利用条件:rsync未授权 列出模板 rsync rsync://目标ip:873/ 列出模块src下的文件 rsync rsync ...
- H5中实现加载更多的逻辑及代码执行。
H5中加载更多的逻辑总结: 1.首先,需要三个底部的提示,分别是“加载中”.“--我是有底线的--”.“暂时没有记录”,当然,这三句话根据不同的项目,可以自定义.具体代码例子如下: <div c ...
- JavaScript的入门篇
快速认识JavaScript 熟悉JavaScript基本语法 窗口交互方法 通过DOM进行网页元素的操作 学会如何编写JS代码 运用JavaScript去操作HTML元素和CSS样式 <!DO ...
- Linux 把进程为D(不可中断进程)转换成其他状态
问题现象:当前集群跑hadoop的时候,,任务失败,但是跑任务的容器没有正常退出,显示一大堆的YarcChild进程,,more /proc/进程/status 查看其状态,进程为D(disk s ...
- SDN第六次上机作业
1.实验拓扑 实验拓扑图如下: 搭建代码如下: 创建py脚本文件,并编写代码,如下: class MyTopo(Topo): def __init__(self): # initilaize topo ...
- Ajax:修改了项目的ajax相关代码,点击运行没有效果
在运行ajax代码的时候发现这个问题,无论是重启浏览器还是IDE依旧不能解决. 原因: 浏览器调试的缓存 措施: 浏览器启用开发者模式,以Chrome.IDEA为例 1.浏览器设置disable ca ...
- 关于java nio的channel读写的一个困惑
这里提的需求基本都是IM的,IM的解决方案是怎么样的? 网上的需求: 1. 某一用户发了一条信息, 需要服务器反回一个信息(这种最简单) 2. 某一用户发了一条信息,需要服务器广播给所有客户端 3. ...
- linux学习(3):linux常用命令大全
Linux常用命令大全(非常全!!!) 最近都在和Linux打交道,感觉还不错.我觉得Linux相比windows比较麻烦的就是很多东西都要用命令来控制,当然,这也是很多人喜欢linux的原因,比较短 ...
- (十三)GBDT模型用于评分卡模型python实现
python信用评分卡建模(附代码,博主录制) https://study.163.com/course/introduction.htm?courseId=1005214003&utm_ca ...
- rqalpha学习-1
1 setup 安装 C:\work\python\rqalpha\setup.py install C:\work\python\rqalpha 2 mod list 列出mod C:\work\p ...