手写简易的MyBatis框架

如题所示: 尝试手写简易的mybatis框架, 参照大佬的文章,写出来后在代码中加了部分注解,以此记录当做学习过程

参照原文链接: https://blog.csdn.net/l1028386804/article/details/117409076

提供Table 注解

package test.orm;

import java.lang.annotation.*;

/**
 * @author: 骑猪撞地球
 * @date: 2021/6/3 14:15
 * @content:
 */
@Inherited  // 用于放在注解上, 用上了@Inherited修饰的注解, 那么其子类也会继承这个注解
@Target({
    
    ElementType.TYPE}) // 用于描述注解的使用范围  类型总共有十种  1.8之前是八种,JDK1.8新加了两种
@Retention(RetentionPolicy.RUNTIME) // 注解的注解,称为元注解   可以确定带有该注解的注解保留多久  总共有3种
@Documented
public @interface Table {
    
    
    String value() default "";
}

提供Column 注解

package test.orm;

import java.lang.annotation.*;

/**
 * @author: 骑猪撞地球
 * @date: 2021/6/3 14:16
 * @content:
 */
@Inherited
@Target({
    
    ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Column {
    
    
    String value() default "";
}

实体类 所用的两个注解均为自己提供的注解

package test.orm;

/**
 * @author: 骑猪撞地球
 * @date: 2021/6/3 14:17
 * @content:
 */
@Table("table_name")
public class Entity {
    
    
    /**
     * 提供有参无参方法
     */
    public Entity() {
    
    
    }

    public Entity(String userName, Integer age, String sex) {
    
    
        this.userName = userName;
        this.age = age;
        this.sex = sex;
    }

    @Column("user_name")
    private String userName;

    @Column("age")
    private Integer age;

    @Column("sex")
    private String sex;

    public String getUserName() {
    
    
        return userName;
    }

    public void setUserName(String userName) {
    
    
        this.userName = userName;
    }

    public Integer getAge() {
    
    
        return age;
    }

    public void setAge(Integer age) {
    
    
        this.age = age;
    }

    public String getSex() {
    
    
        return sex;
    }

    public void setSex(String sex) {
    
    
        this.sex = sex;
    }
}

核心代码 根据实体类创建sql

package test.orm;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * @author: 骑猪撞地球
 * @date: 2021/6/3 14:20
 * @content: sql生成器
 */
public class SqlBuilder {
    
    
    /**
     * 通过注解来组装查询条件,生成查询语句
     *
     * @param obj
     * @return
     */
    public static String assembleSqlFromObj(Object obj) {
    
    
        // 获取指定注释类型的注释  该方法以对象的形式返回该类
        Table table = obj.getClass().getAnnotation(Table.class);
        StringBuffer sbSql = new StringBuffer();
        // 获取table中的值   即表名
        String tableName = table.value();
        sbSql.append("select * from " + tableName + " where 1 = 1 ");

        // 获得类中所有声明的字段  包括public、private和proteced  但是不包括父类的申明字段
        Field[] fileds = obj.getClass().getDeclaredFields();
        // Field[] fields = obj.getClass().getFields();  作用相同  但该方法获取的是所有的公共(public)的字段  包括父类中的字段

        for (Field f : fileds) {
    
    
            // 获取字段名称 并且拼接出获取该字段值的方法名称
            String fieldName = f.getName();
            String methodName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
            try {
    
    
                // 取出该字段对应的 Column 标签内值 用来拼接sql
                Column column = f.getAnnotation(Column.class);
                if (column != null) {
    
    
                    // 根据方法名称从obj中获取到值
                    Method method = obj.getClass().getMethod(methodName);
                    Object v = method.invoke(obj);
                    if (v != null) {
    
    
                        // 判断是否为字符串
                        if (v instanceof String) {
    
    
                            String value = v.toString().trim();
                            // 判断参数含有','  即 --> 1,2,3  采用in   此处不够严谨,如果想用','搜索  即做不到了
                            if (value.contains(",")) {
    
    
                                // 去掉value中的,
                                String sqlParams = value.replace(",", "").trim();
                                // value中都是纯数字
                                if (isNum(sqlParams)) {
    
    
                                    sbSql.append(" and " + column.value() + " in (" + value + ") ");
                                } else {
    
    
                                    // 查询字段非数字  则进行拼接
                                    String[] split = value.split(",");
                                    //将value重置为空
                                    value = "";
                                    for (int i = 0; i < split.length - 1; i++) {
    
    
                                        value += "'" + split[i] + "',";
                                    }
                                    value += "'" + split[split.length - 1] + "'";
                                    sbSql.append(" and " + column.value() + " in (" + value + ") ");
                                }
                            } else {
    
    
                                if (value.length() > 0) {
    
    
                                    sbSql.append(" and " + column.value() + " like '%" + value + "%' ");
                                }
                            }
                        } else {
    
    
                            sbSql.append(" and " + column.value() + " = " + v.toString() + " ");
                        }
                    }
                }
            } catch (Exception e) {
    
    
                e.printStackTrace();
            }
        }
        return sbSql.toString();
    }

    /**
     * 检查给定的值是不是 数字 类型
     *
     * @param target
     * @return
     */
    private static boolean isNum(String target) {
    
    
        boolean isNum = false;
        // 检查字段是否为纯数字类型
        if (target.matches("\\d+")) {
    
    
            isNum = true;
        }
        return isNum;
    }
}

进行测试

package test.orm;

/**
 * @author: 骑猪撞地球
 * @date: 2021/6/3 14:33
 * @content:
 */
public class Test {
    
    

    public static void main(String[] args) {
    
    
        Entity entity = new Entity("张三", 18, "男");
        Entity entity1 = new Entity("张三", null, null);
        String sql1 = SqlBuilder.assembleSqlFromObj(entity);
        String sql2 = SqlBuilder.assembleSqlFromObj(entity1);
        System.out.println(sql1);
        System.out.println(sql2);
    }
}

测试结果:

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_44974020/article/details/117523720