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. session内置对象

    SimpleDateFormat sdf = new SimpleDateFormat(yyyy年MM月dd日)  //处理日期格式 session.getCreationDate() 是获取sess ...

  2. Django 实现文件下载

    1. 思路: 文件,让用户下载 - a标签+静态文件 - 设置响应头(django如何实现文件下载) 2. a标签实现 <a href="/static/xxx.xlsx"& ...

  3. S1_搭建分布式OpenStack集群_07 nova服务配置 (计算节点)

    一.服务安装(计算节点)安装软件:# yum install openstack-nova-compute -y 编辑/etc/nova/nova.conf文件并设置如下内容:# vim /etc/n ...

  4. .net Web 项目的文件/文件夹上传下载

    以ASP.NET Core WebAPI 作后端 API ,用 Vue 构建前端页面,用 Axios 从前端访问后端 API ,包括文件的上传和下载. 准备文件上传的API #region 文件上传  ...

  5. [USACO14MAR] Sabotage 二分答案 分数规划

    [USACO14MAR] Sabotage 二分答案 分数规划 最终答案的式子: \[ \frac{sum-sum[l,r]}{n-len[l,r]}\le ans \] 转换一下: \[ sum[1 ...

  6. NLP算法工程师(实习生)面试总结(持续更新)

    爱奇艺 1. attention<attention is all you need> 2. 相关项目 3. 逻辑回归 4. linux的指令(重命名文件,vim替换,vim指向文章最末行 ...

  7. IOI2019题解

    由于太懒了,好久没更新了.发个题解好了. shoes 首先不难证明鞋子配对一定是从前往后将同一种的左和右配对. 配好对之后首先我们可以假设左在右的左边,然后讨论可知将左边靠前的排在前面更优. rect ...

  8. BJOI做题记录

    BJOI做题记录 终于想起还要做一下历年省选题了2333 然而咕了的还是比做了的多2333 LOJ #2178. 「BJOI2017」机动训练 咕了. LOJ #2179. 「BJOI2017」树的难 ...

  9. GoCN每日新闻(2019-10-13)

    GoCN每日新闻(2019-10-13) 1. 通过测试学习Go语言 https://mp.weixin.qq.com/s/MGT_yoP_NdWVGpwlAJFK4A2. go panic reco ...

  10. java生成HMACSHA256的方法

    data要加密的数据,key密钥 public static String HMACSHA256(String data, String key) throws Exception { Mac sha ...