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. 10 分钟了解 Actor 模型

    http://www.moye.me/2016/08/14/akka-in-action_actor-model/ 过去十几年CPU一直遵循着摩尔定律发展,单核频率越来越快,但是最近这几年,摩尔定律已 ...

  2. docker的daemon配置

    文件:/etc/docker/daemon.json,如果没有就创建 修改后重启生效:systemctl restart docker 示例内容: { "registry-mirrors&q ...

  3. [51Nod 1220] - 约数之和 (杜教筛)

    题面 令d(n)d(n)d(n)表示nnn的约数之和求 ∑i=1n∑j=1nd(ij)\large\sum_{i=1}^n\sum_{j=1}^nd(ij)i=1∑n​j=1∑n​d(ij) 题目分析 ...

  4. 经肝药酶CYP3A4代谢的药物对比记录

    罗非昔布 罗非昔布,解热镇痛抗炎药,选择性环氧化酶-2(COX-2)抑制药,有研究表明,该类药可增加心脏病发作.卒中或其他严重后果概率,不良反应为,增加心肌梗死和心脏猝死的风险,现已撤市.经肝和肠壁细 ...

  5. python3 爬虫继续爬笔趣阁 ,,,,,,,

    学如逆水行舟,不进则退 今天想看小说..找了半天,没有资源.. 只能自己爬了 想了半天.,,,忘记了这个古老的技能 捡了一下 import requests from bs4 import Beaut ...

  6. gdb命令行

    1.当程序出现core dump时,使用下面的命令调试:       gdb 程序名 core.1234  或       gdb core.1234       gdb -c core.1234 程 ...

  7. java 数组遍历(方法内部的代码)

    //数组遍历(依次输出数组中的每一个元素)二维数组: int[][] arr={{1,2},{3,4,5},{6,7}}; for(int i=0;i<arr.length;i++){ for( ...

  8. PowerDesigner 画流程图

    原因: 以前赶时间写了n长一个类,现在又增加新需求了,but以前怎么写的忘了,虽然注释都有,一个一个方法的看很累,准备把它用面向对象改造一下,不知道时间够不,先试一试在说.之前设计数据库用的Power ...

  9. 《RabbitMQ 实战》读书笔记

    MQ的好处: 1.业务上接口(系统扩展性变强) 2.性能提升(同步变异步,效率提高,还方便做负载均衡) 3.技术兼容(可以连接各种不同语言的系统,作为粘合剂) 读书笔记: 1.消息队列的应用场景:系统 ...

  10. SP19997 MOON2 - Moon Safari (Hard) 【数论,多项式】

    题目描述:求 \[ \sum_{i=1}^ni^kr^i \] 对某个质数取模.\(T\)组数据. 数据范围:\(n,r\le 10^{18},\sum k\le 2.56\times 10^6\) ...