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的更多相关文章

  1. Mybatis中使用association及collection进行自关联示例(含XML版与注解版)

    XML版本: 实体类: @Data @ToString @NoArgsConstructor public class Dept { private Integer id; private Strin ...

  2. Mybatis中使用collection进行多对多双向关联示例(含XML版与注解版)

    Mybatis中使用collection进行多对多双向关联示例(含XML版与注解版) XML版本: 实体类: @Data @NoArgsConstructor public class Course ...

  3. SSM 框架-06-详细整合教程(IDEA版)(Spring+SpringMVC+MyBatis)

    SSM 框架-06-详细整合教程(IDEA版)(Spring+SpringMVC+MyBatis) SSM(Spring.Spring MVC和Mybatis)如果你使用的是 Eclipse,请查看: ...

  4. SSM 框架-05-详细整合教程(Eclipse版)(Spring+SpringMVC+MyBatis)

    SSM 框架-05-详细整合教程(Eclipse版)(Spring+SpringMVC+MyBatis) 如果你使用的是 Intellij IDEA,请查看: SSM的配置流程详细的写了出来,方便很少 ...

  5. JavaMail简单版实验测试

    前言: 最近由于实现web商城的自动发送邮件功能的需求,故涉猎的邮箱协议的内部原理.现将简单版的Java Mail实例做个代码展示,并附上其中可能出现的bug贴出,方便感兴趣的读者进行测试! 1.载入 ...

  6. 小米抢购(简单版v0.1)-登录并验证抢购权限,以及获取真实抢购地址

    小米(简单版)-登录并验证抢购权限,以及获取真实抢购地址! 并不是复制到浏览器就行了的   还得传递所需要的参数 这里只是前部分  后面的自己发挥了 { "stime": 1389 ...

  7. Java实现简单版SVM

    Java实现简单版SVM 近期的图像分类工作要用到latent svm,为了更加深入了解svm,自己动手实现一个简单版的.         之所以说是简单版,由于没实用到拉格朗日,对偶,核函数等等.而 ...

  8. MySQL数据库执行计划(简单版)

    +++++++++++++++++++++++++++++++++++++++++++标题:MySQL数据库执行计划简单版时间:2019年2月25日内容:MySQL数据库执行计划简单版重点:MySQL ...

  9. 红警大战JAVA简单版

    代码结构: 相关源码: 武器类: 属性:武器,攻击力,子弹数量. 方法:给属性赋值(set属性()方法) 获取属性值(get属性()方法) package 红警大战简单版; public class ...

随机推荐

  1. JPA EnableJpaAuditing 审计功能

    关于自动填充或更新实体中的 CreateDate.CreatedBy 等在之前有一篇 jeecg 默认为空的字段值是如何被填充的? 有提到通过拦截器的方式实现,但是今天带大家了解一下如果使用 JPA ...

  2. siameseNet网络以及信号分类识别应用

    初学siameseNet网络,希望可以用于信号的识别分类应用.此文为不间断更新的笔记. siameseNet简介 全连接孪生网络(siamese network)是一种相似性度量方法,适用于类别数目多 ...

  3. LeetCode 1079. Letter Tile Possibilities

    原题链接在这里:https://leetcode.com/problems/letter-tile-possibilities/ 题目: You have a set of tiles, where ...

  4. 封装原生promise函数

    阿里面试题: 手动封装promise函数 <!DOCTYPE html> <html lang="en"> <head> <meta ch ...

  5. (尚021)Vue_eslint编码规范检查

    1.eslint 1.1说明 1)ESLint是一个代码规范检查工具 2)它定义了很多特定的规则,一旦你的代码违背了某一规则,eslint会做出非常有用的提示 3)官网:http://eslint.o ...

  6. rpm 简单 package 创建demo

    安装的工具 yum install -y rpmdevtools 准备环境 主要是初始化,会自动创建rpm 包构建需要的目录 rpmdev-setuptree 编写简单的spec cd ~/rpmbu ...

  7. JMeter学习2

    JMeter学习(四)参数化 参数化:录制脚本中有登录操作,需要输入用户名和密码,假如系统不允许相同的用户名和密码同时登录,或者想更好的模拟多个用户来登录系统. 这个时候就需要对用户名和密码进行参数化 ...

  8. 定量变量和定性变量的转换(Transform of Quantitative & Qualitative Variables)

    定量变量(Quantitative Variables):也称为数值型变量(Numerical Variables),可以用连续值或离散值表示.比如:气温(连续值),学生人数(离散值). 为什么要对定 ...

  9. 【CSP模拟赛】starway(玄学建边 最小生成树)

    问題描述 小w伤心的走上了 Star way to heaven.   到天堂的道路是一个笛卡尔坐标系上一个n×m的长方形通道(顶点在(0,0))和(n,m)),小w从最左边任意一点进入,从右边任意一 ...

  10. OpenFOAM——90度T型管

    本算例来自<ANSYS Fluid Dynamics Verification Manual>中的VMFL010: Laminar Flow in a 90° Tee-Junction. ...