手撕ORM框架(泛型+注解+反射)

目录

 一、Annitation包:自定义注解 用于实体类上

三、BaseDao类:父类

BaseDao中的添加方法

BaseDao中的删改和查询方法

 entity包:实体类Student  Teacher

dao包:操作类

 测试


手写ORM框架:----O(Object 对象) R(relative 关系) M(Mapping 映射) 对象关系映射

就是把数据库中的表映射为java的类,表中的记录映射为java的对象,列映射为java类中属性。

该框架可以在不写sql语句的前题下完成对单表的CRUD操作。

 一、Annitation包:自定义注解 用于实体类上

        TableName:表明和实体类名不一致时使用

        TableField:列名和属性名不一致时使用

        TableId:列名和属性名不一致时使用                

package com.wjk.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TableField {
    String value();
}
/**
 * Created by Intellij IDEA
 *
 * @author 王俊凯
 * @Date: 2022/10/28 14:17
 * @Version 1.0
 */
package com.wjk.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TableId {
    String value() default "id";
}

package com.wjk.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TableName {
    String value();
}

二、until:公共类

DBUtils:获取连接对象和关闭连接资源

/**
 * Created by Intellij IDEA
 *
 * @author 王俊凯
 * @Date: 2022/10/28 9:27
 * @Version 1.0
 */
package com.wjk.until;

import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Properties;

public class DBUtil {

    private static String driverName="";
    private static String url="";
    private static String username="";
    private static String password="";

    //静态代码块 随着类的加载而被加载到内存中,且只会被加载一次
    static {
        try {
            //该类用于读取属性文件
            Properties properties=new Properties();
            InputStream inputStream = ClassLoader.getSystemResourceAsStream("db.properties");
            properties.load(inputStream);

            //读取属性文件中相应的内容
            driverName =properties.getProperty("jdbc.driverName");
            url =properties.getProperty("jdbc.url");
            username =properties.getProperty("jdbc.username");
            password =properties.getProperty("jdbc.password");
        }catch (Exception e){
            throw new RuntimeException("无法读取db.properties");
        }
    }


    /**
     * 获取数据库连接
     * @return
     */
    public static Connection getConnection()throws Exception{
        Class.forName("com.mysql.cj.jdbc.Driver");
        Connection connection= DriverManager.getConnection(url,username,password);
        return connection;
    }

    /**
     * 关闭资源
     * @param connection
     * @param ps
     * @param rs
     */
    public static void closeAll(Connection connection, PreparedStatement ps, ResultSet rs){
        try {
            if (rs!=null){
                rs.close();
            }
            if (ps!=null){
                ps.close();
            }
            if (connection!=null){
                connection.close();
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

}

三、BaseDao类:父类

如何获取类名中泛型T:

//this对应的是子类对象  获取当前类的反射类对象
Class<? extends BaseDao> aClass = this.getClass();
//获取当前反射类的父类反射类----包含了父类的泛型
ParameterizedType genericSuperclass = (ParameterizedType) aClass.getGenericSuperclass();
//获取泛型的反射类
Type[] actualTypeArguments = genericSuperclass.getActualTypeArguments();
clazz = (Class<?>) actualTypeArguments[0];

BaseDao中的添加方法

/**
 * Created by Intellij IDEA
 *
 * @author 王俊凯
 * @Date: 2022/10/28 12:57
 * @Version 1.0
 */
package com.wjk.until;

import com.wjk.annotation.TableField;
import com.wjk.annotation.TableId;
import com.wjk.annotation.TableName;
import org.junit.Test;

import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.util.ArrayList;
import java.util.List;

public class BaseDao<T> {

    /**
     * 添加功能
     * insert into
     * @param t
     * @return
     */
    public int insert(T t)throws Exception{
        StringBuilder sql=new StringBuilder("insert into ");
        //根据对象获取该对象反射类的Class
        Class<?> aClass = t.getClass();
        //获取反射类上的注解
        TableName annotation = aClass.getAnnotation(TableName.class);
        //获取注解的属性
        String tableName = annotation.value();
        //拿到表名
        sql.append(tableName);

        //获取所有的列名
        Field[] fields = aClass.getDeclaredFields();
        //声明集合  代表所有的列名
        List<String> columns=new ArrayList<>();
        //声明集合  代表的所有列值
        List<Object> values=new ArrayList<>();
        for (Field field:fields){
            //获取属性对象上的注解对象
            TableField tableField = field.getAnnotation(TableField.class);
            TableId tableId = field.getAnnotation(TableId.class);
            String name ="";
            if (tableId!=null){
                continue;
            }

            if (tableField!=null){
                name=tableField.value();
            }else {
                name=field.getName();
            }
            //允许访问
            field.setAccessible(true);
            //获取对象t对应的列值
            Object o = field.get(t);

            values.add("'"+o+"'");
            columns.add(name);
        }

        //获取到了列名
        String columnNames=columns.toString().replace("[","(").replace("]",")");
        //获取到了列值
        String valuesNames=values.toString().replace("[","(").replace("]",")");
        sql.append(columnNames);
        sql.append("values");
        sql.append(valuesNames);
        System.out.println(sql);

        //执行sql
        Connection connection = DBUtil.getConnection();
        PreparedStatement preparedStatement = connection.prepareStatement(sql.toString());
        int i = preparedStatement.executeUpdate();

        return 0;
    }

}

BaseDao中的删改和查询方法

/**
 * Created by Intellij IDEA
 *
 * @author 王俊凯
 * @Date: 2022/10/28 12:57
 * @Version 1.0
 */
package com.wjk.until;

import com.wjk.annotation.TableField;
import com.wjk.annotation.TableId;
import com.wjk.annotation.TableName;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

public class BaseDao<T> {
    private Class<?> aClazz;

    public BaseDao(){
        //this对应的是子类对象  获取当前类的反射对象
        Class<? extends BaseDao> aClass = this.getClass();
        //获取当前反射类的父类
        ParameterizedType genericSuperclass = (ParameterizedType) aClass.getGenericSuperclass();
        //获取泛型的反射类
        Type[] types = genericSuperclass.getActualTypeArguments();
        aClazz= (Class<?>) types[0];
    }
    private Connection conn = null;
    private ResultSet rs=null;

    /**
     * 修改功能
     * @param t
     * @return
     * @throws Exception
     */
    public int update(T t) throws Exception {
        StringBuilder sql=new StringBuilder("update ");

        //根据对象获取该对象反射类的Class
        Class<?> aClass = t.getClass();
        //获取反射类上的注解
        TableName annotation = aClass.getAnnotation(TableName.class);
        //获取注解的属性
        String tableName = "";
        //判断是否存在注解
        if (annotation!=null){
            tableName=annotation.value();
        }else {
            tableName=aClass.getSimpleName();
        }
        sql.append(tableName+" set ");
        String colunmValue="";
        String where ="where ";
        //获取所有属性
        Field[] declaredFields = aClass.getDeclaredFields();
        boolean flag=false;
        for (Field field:declaredFields){
            //允许访问
            field.setAccessible(true);
            //获取属性对象的指定注解
            TableField tableField = field.getAnnotation(TableField.class);
            TableId tableId = field.getAnnotation(TableId.class);

            if (tableId!=null){
                flag=true;
                where+=tableId.value()+"='"+field.get(t)+"'";
            }else {
                if (tableField!=null){
                    colunmValue+=tableField.value()+"='"+field.get(t)+"',";
                }else {
                    //获取属性名称
                    colunmValue+=field.getName()+"='"+field.get(t)+"',";
                }
            }
        }
        if (flag==false){
            throw new RuntimeException("没有添加主键注解");
        }
        //这里要删除最后的逗号
        colunmValue= colunmValue.substring(0, colunmValue.lastIndexOf(","));
        sql.append(colunmValue);
        sql.append(where);

        System.out.println(sql);

        conn=DBUtil.getConnection();
        PreparedStatement ps = conn.prepareStatement(sql.toString());
        int row = ps.executeUpdate();
        return row;

    }

    /**
     * 删除功能
     * @param id
     * @return
     */
    public int delete(Object id)throws Exception{
        StringBuilder sql=new StringBuilder("delete from ");
        //获取表名
        TableName tableName = aClazz.getAnnotation(TableName.class);
        if (tableName!=null){
            sql.append(tableName.value());
        }else {
            sql.append(aClazz.getSimpleName());
        }

        sql.append(" where ");
        Field[] fields = aClazz.getDeclaredFields();
        boolean  flag=false;
        for (Field field:fields){
            TableId tableId = field.getAnnotation(TableId.class);
            if (tableId!=null){
                sql.append(tableId.value()+" = '"+id+"'");
                flag=true;
                break;
            }
        }
        if (flag==false){
            throw new RuntimeException("没有主键注解");
        }
        System.out.println(sql);

        Connection connection = DBUtil.getConnection();
        PreparedStatement ps = connection.prepareStatement(sql.toString());
        int i = ps.executeUpdate();
        return i;

    }

    /**
     * 查询所有
     * @return
     */
    public List<T> selectAll()throws Exception{
        List<T> list = new ArrayList<>();

        StringBuilder sql=new StringBuilder("select ");
        //获取所有属性对象
        Field[] declaredFields = aClazz.getDeclaredFields();

        boolean flag=false;

        for (Field field:declaredFields){
            //允许访问
            field.setAccessible(true);
            TableField tableField = field.getAnnotation(TableField.class);
            TableId tableId = field.getAnnotation(TableId.class);

            if (tableId!=null){
                flag=true;
                sql.append(tableId.value()+",");
            }else {
                if (tableField!=null){
                    sql.append(tableField.value()+",");
                }else {
                    //获取属性名称
                    sql.append(field.getName()+",");
                }
            }
        }
        if (flag==false){
            throw new RuntimeException("没有主键注解");
        }
        sql.deleteCharAt(sql.length()-1);
        sql.append(" from ");
        //获取表名
        TableName tableName = aClazz.getAnnotation(TableName.class);
        if (tableName!=null){
            sql.append(tableName.value());
        }else {
            sql.append(aClazz.getSimpleName());
        }
        Connection connection = DBUtil.getConnection();
        PreparedStatement ps = connection.prepareStatement(sql.toString());
        rs = ps.executeQuery();
        while (rs.next()){
            Object o = aClazz.newInstance();
            Field[] declaredFields1 = aClazz.getDeclaredFields();
            boolean flag1=false;
            for (Field field:declaredFields1){
                field.setAccessible(true);
                TableField tableField = field.getAnnotation(TableField.class);
                TableId tableId = field.getAnnotation(TableId.class);
                if (tableId!=null){
                    flag1=true;
                    field.set(o,rs.getObject(tableId.value()));
                }else {
                    if (tableField!=null){
                        field.set(o,rs.getObject(tableField.value()));
                    }else {
                        field.set(o,rs.getObject(field.getName()));
                    }
                }
            }
            if (flag1==false){
                throw new RuntimeException("没有主键注解");
            }
            list.add((T) o);
        }
        return list;
    }

    /**
     * 根据id查询
     * @param id
     * @return
     */
    public T selectById(Object id)throws Exception{
        T t =null;
        StringBuilder sql=new StringBuilder("select ");
        //获取所有的属性对象
        Field[] declaredFields = aClazz.getDeclaredFields();

        String where = " where ";
        boolean flag=false;
        for (Field field:declaredFields){
            field.setAccessible(true);
            //获取属性对象的注解
            TableField tableField = field.getAnnotation(TableField.class);
            TableId tableId = field.getAnnotation(TableId.class);
            if (tableId!=null){
                flag=true;
                sql.append(tableId.value()+",");
                where+=tableId.value()+" = ";
            }else {
                if (tableField!=null){
                    sql.append(tableField.value()+",");
                }else {
                    //获取属性名称
                    sql.append(field.getName()+",");
                }
            }
        }
        if (flag==false){
            throw new RuntimeException("没有主键注解");
        }
        sql.deleteCharAt(sql.length()-1);
        sql.append(" from ");
        //获取表名
        TableName tableName = aClazz.getAnnotation(TableName.class);
        if (tableName!=null){
            sql.append(tableName.value());
        }else {
            sql.append(aClazz.getSimpleName());
        }
        sql.append(where+id);

        Connection connection = DBUtil.getConnection();
        PreparedStatement ps = connection.prepareStatement(sql.toString());
        rs=ps.executeQuery();
        while (rs.next()){
            t= (T) aClazz.newInstance();
            Field[] declaredFields1 = aClazz.getDeclaredFields();
            boolean flag1=false;
            for (Field field:declaredFields1){
                field.setAccessible(true);
                //获取属性对象的注解
                TableField tableField = field.getAnnotation(TableField.class);
                TableId tableId = field.getAnnotation(TableId.class);
                if (tableId!=null){
                    flag1=true;
                    field.set(t,rs.getObject(tableId.value()));
                }else {
                    if (tableField!=null){
                        field.set(t,rs.getObject(tableField.value()));
                    }else {
                        field.set(t,rs.getObject(field.getName()));
                    }
                }
            }
            if (flag1==false){
                throw new RuntimeException("没有主键注解");
            }

        }

        return t;
    }

}

 entity包:实体类Student  Teacher

/**
 * Created by Intellij IDEA
 *
 * @author 王俊凯
 * @Date: 2022/10/28 12:59
 * @Version 1.0
 */
package com.wjk.entity;

import com.wjk.annotation.TableField;
import com.wjk.annotation.TableId;
import com.wjk.annotation.TableName;

@TableName(value = "t_student")
public class Student {
    @TableId
    private Integer id;
    @TableField(value = "stu_name")
    private String stuName;
    @TableField(value = "stu_age")
    private Integer stuAge;
    private String address;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getStuName() {
        return stuName;
    }

    public void setStuName(String stuName) {
        this.stuName = stuName;
    }

    public Integer getStuAge() {
        return stuAge;
    }

    public void setStuAge(Integer stuAge) {
        this.stuAge = stuAge;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
}





/**
 * Created by Intellij IDEA
 *
 * @author 王俊凯
 * @Date: 2022/10/28 13:00
 * @Version 1.0
 */
package com.wjk.entity;

import com.wjk.annotation.TableId;
import com.wjk.annotation.TableName;
import lombok.Data;

@TableName(value = "t_teacher")
@Data
public class Teacher {
    @TableId
    public int id;
    private String name;
    private int age;
    private String sex;
}

dao包:操作类

/**
 * Created by Intellij IDEA
 *
 * @author 王俊凯
 * @Date: 2022/10/28 12:58
 * @Version 1.0
 */
package com.wjk.dao;

import com.wjk.entity.Student;
import com.wjk.until.BaseDao;

public class StudentDao extends BaseDao<Student> {

}




/**
 * Created by Intellij IDEA
 *
 * @author 王俊凯
 * @Date: 2022/10/28 13:00
 * @Version 1.0
 */
package com.wjk.dao;

import com.wjk.entity.Teacher;
import com.wjk.until.BaseDao;

public class TeacherDao extends BaseDao<Teacher> {

}



 测试

/**
 * Created by Intellij IDEA
 *
 * @author 王俊凯
 * @Date: 2022/10/28 14:45
 * @Version 1.0
 */
package com.wjk.test;

import com.wjk.dao.TeacherDao;
import com.wjk.entity.Teacher;

public class Test01 {
    public static void main(String[] args) throws Exception {
        TeacherDao teacherDao=new TeacherDao();
        Teacher teacher=new Teacher();
        teacher.setId(11);
        teacher.setName("八嘎");
        teacher.setAge(99);
        teacher.setSex("男");
        int update = teacherDao.update(teacher);

        TeacherDao teacherDao1=new TeacherDao();
        teacherDao1.delete(1);



    }
}

/**
 * Created by Intellij IDEA
 *
 * @author 王俊凯
 * @Date: 2022/10/29 12:11
 * @Version 1.0
 */
package com.wjk.test;

import com.wjk.dao.TeacherDao;
import com.wjk.entity.Teacher;

import java.lang.reflect.Method;
import java.util.List;

/**
 * 查询所有
 */
public class Test02 {
    public static void main(String[] args) throws Exception{
        TeacherDao teacherDao=new TeacherDao();
        List<Teacher> teachers = teacherDao.selectAll();
        System.out.println(teachers);

    }
}



/**
 * Created by Intellij IDEA
 *
 * @author 王俊凯
 * @Date: 2022/10/29 12:27
 * @Version 1.0
 */
package com.wjk.test;

import com.wjk.dao.TeacherDao;
import com.wjk.entity.Teacher;

/**
 * 查询单个
 */
public class Test03 {
    public static void main(String[] args) throws Exception{
        TeacherDao teacherDao=new TeacherDao();
        Teacher teacher = teacherDao.selectById(5);
        System.out.println(teacher);
    }
}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值