首页 > 数据库 >手写持久层框架------无需写sql语句即可完成对单表的CRUD操作。

手写持久层框架------无需写sql语句即可完成对单表的CRUD操作。

时间:2024-07-10 21:26:11浏览次数:18  
标签:tableField String CRUD field 单表 sql null name

目的:巩固知识点

  1. 技术栈:java+mysql+反射+自定义注解+泛型+jdbc
  2. 持久层框架:与数据库交互的一层成为持久层。完成orm操作
  3. o(Object对象)  r:(relative关系)   m:(mapping映射)。实体类---数据库表    属性---表的字段   实体类对象---- 一条记录   集合----表中多条记录
  4. 手撕持久层框架:自己编写持久层和框架,可以完成无需写sql语句即可完成对单表的CRUD操作。

1.1创建一个maven的java工程 

 1.2 引入依赖的jar

<dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>8.0.28</version>
    </dependency>
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>druid</artifactId>
      <version>1.1.10</version>
    </dependency>

1.3 创建数据源的属性文件 

driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/数据库名?serverTimezone=Asia/Shanghai
username=账号
password=密码

 1.4  创建DbUtil工具类

package com.syh.util;

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import javax.xml.crypto.Data;
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 final DataSource dataSource;
//    private static String driverClassName;
//    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);
            dataSource = DruidDataSourceFactory.createDataSource(properties);
        }
        catch (Exception e) {
            throw new RuntimeException("无法读取db.properties");
        }
    }
    //获取连接数据库对象:思考:如果我们把驱动名和url和密码硬编码放在配置文件中,那么我们就不需要在代码中写死这些内容了,只需要在配置文件中读取即可
    public static Connection getConnection() {
        try {
            return dataSource.getConnection();
        }
        catch (Exception e) {
            throw new RuntimeException("1111");
        }
    }

    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) {
            throw new RuntimeException("无法关闭数据库连接");
        }
    }
}

1.5 定义注解

 

//属性的注解
@Target(ElementType.FIELD)
//运行时执行
@Retention(RetentionPolicy.RUNTIME)
public @interface TableField {
    String name();
}


//主键的注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TableFieldKey {
    String value() default "id";
}


//表名的注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TableName {
    String value();
}

1.6  单表的添加

public class BaseDao<T> {
    private Class<T> clazz;

    public BaseDao() {
        //this表示子类的dao对象
        Class<? extends BaseDao> aClass = this.getClass();
        //获取当前子类的父类的的反射类
        ParameterizedType genericSuperclass = (ParameterizedType) aClass.getGenericSuperclass();

        //获取反射类中的泛型类型
        Type actualTypeArgument = genericSuperclass.getActualTypeArguments()[0];
        clazz = (Class) actualTypeArgument;
    }

    //添加功能
    public int insert(T t) {
        StringBuilder sql = new StringBuilder("insert into ");
        //根据对象获取该对象的反射类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);
        //获取所有列名
        Field[] fields = aClass.getDeclaredFields();
        ArrayList<String> columns = new ArrayList<String>();
        //获取所有值
        ArrayList<Object> values = new ArrayList<Object>();
        for (Field field : fields) {
            TableField tableField = field.getAnnotation(TableField.class);
            TableFieldKey tableFieldKey = field.getAnnotation(TableFieldKey.class);
            String name = "";
            if (tableFieldKey != null) {
                continue;
            }
            if (tableField != null) {
                name = tableField.name();
            } else {
                name = field.getName();
            }
            Object v = null;
            field.setAccessible(true);
            try {
                v = field.get(t);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            values.add("'" + v + "'");
            columns.add(name);
        }


        String columName = columns.toString().replace("[", "(").replace("]", ")");
        String valueNames = values.toString().replace("[", "(").replace("]", ")");
        sql.append(columName);
        sql.append(" values ");
        sql.append(valueNames);
        System.out.println(sql);

        int i = 0;

        try {
            Connection connection = Dbutil.getConnection();
            PreparedStatement preparedStatement = connection.prepareStatement(sql.toString());
            i = preparedStatement.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }

        return i;
    }
}

1.7  单表的修改

public int update(T t) {
        StringBuffer sql = new StringBuffer("update ");
        //获取表名
        Class<?> aClass = t.getClass();
        String tableName = aClass.getSimpleName();
        TableName annotation = aClass.getAnnotation(TableName.class);
        if (annotation != null) {
            //获取注解的表名
            tableName = annotation.value();
        }
        sql.append(tableName + " set ");
        String where = " where ";
        //获取所有列对象
        Field[] fields = aClass.getDeclaredFields();
        for (Field field : fields) {
            //获取属性名
            String name = field.getName();
            TableField tableField = field.getAnnotation(TableField.class);
            // 尝试获取字段上的TableFieldKay注解,用于后续判断是否需要拼接SQL的where条件
            //获取主键
            TableFieldKey tableFieldKey = field.getAnnotation(TableFieldKey.class);
            // 设置字段可访问,以突破访问权限限制,获取字段值
            field.setAccessible(true);
            Object value = null;
            try {
                // 尝试获取字段的值
                value = field.get(t);
            } catch (IllegalAccessException e) {
                // 当访问字段失败时,打印异常堆栈跟踪,但并未对异常进行进一步处理
                e.printStackTrace();
            }
            // 如果字段上存在TableFieldKay注解,则拼接SQL的where条件
            if (tableFieldKey != null) {
                // 从注解中获取字段在数据库表中的名称
                String tableFieldKayName = tableFieldKey.value();
                // 拼接where条件,此处应注意SQL注入的风险
                where += tableFieldKayName + "='" + value + "'";
                continue;
            }
            if (tableField != null) {
                //获取注解的属性名
                name = tableField.name();
            }
            sql.append(name + "='" + value + "',");
        }
        try {

            sql.deleteCharAt(sql.length() - 1).append(where);
            System.out.println(sql);
            Connection connection = Dbutil.getConnection();
            PreparedStatement preparedStatement = connection.prepareStatement(sql.toString());
            int i = preparedStatement.executeUpdate();
            return i;
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return 0;
    }

1.8 单表的删除

//删除
    public int delete(Object id) {
        StringBuffer sql = new StringBuffer("delete from ");
        //获取表名
        String tableName = clazz.getSimpleName();
        //获取注解的表名
        TableName annotation = clazz.getAnnotation(TableName.class);
        if (annotation != null) {
            tableName = annotation.value();
        }
        sql.append(tableName + " where ");
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            //获取where条件注解
            TableFieldKey tableField = field.getAnnotation(TableFieldKey.class);
            //允许获得私有属性的值
            field.setAccessible(true);
            if (tableField != null) {
                String tableFieldKay = tableField.value();
                sql.append(tableFieldKay + "='" + id + "'");
            }
        }
        try {
            System.out.println(sql);
            Connection conn = Dbutil.getConnection();
            PreparedStatement ps = conn.prepareStatement(sql.toString());
            int i = ps.executeUpdate();
            return i;
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return 0;
    }

 1.9  根据id查询

public T selectById(Object id) {
        StringBuffer sql = new StringBuffer("select * from ");
        //获取表名
        String tableName = clazz.getSimpleName();
        TableName annotation = clazz.getAnnotation(TableName.class);
        if (annotation != null) {
            tableName = annotation.value();
        }
        sql.append(tableName + " where ");
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            TableFieldKey tableField = field.getAnnotation(TableFieldKey.class);
            if (tableField != null) {
                String tableFieldKay = tableField.value();
                sql.append(tableFieldKay + "='" + id + "'");
            }
        }
        System.out.println(sql);
        Connection conn = Dbutil.getConnection();
        PreparedStatement ps = null;
        try {
            ps = conn.prepareStatement(sql.toString());
            ResultSet rs = ps.executeQuery();
            while (rs.next()) {
                T t = clazz.newInstance();
                for (Field field : fields) {
                    field.setAccessible(true);
                    TableField tableField = field.getAnnotation(TableField.class);
                    TableFieldKey tableId = field.getAnnotation(TableFieldKey.class);
                    //获取属性名
                    String name = field.getName();
                    if (tableField != null) {
                        name = tableField.name();
                    }
                    if (tableId != null) {
                        name = tableId.value();
                    }
                    Object object = rs.getObject(name);
                    field.set(t, object);
                }
                System.out.println(t);
                return t;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

 1.10  查询所有

public List<T> selectAll() {
        List<T> list=new ArrayList<>();
        StringBuilder sql = new StringBuilder("select * from ");
        //获取表名
        String tableName = clazz.getSimpleName();
        TableName annotation = clazz.getAnnotation(TableName.class);
        if (annotation != null) {
            tableName = annotation.value();
        }
        sql.append(tableName);
        Connection conn = Dbutil.getConnection();
        try {
            PreparedStatement ps = conn.prepareStatement(sql.toString());
            ResultSet rs = ps.executeQuery();

            Field[] fields = clazz.getDeclaredFields();
            while (rs.next()) {
                T t = clazz.newInstance();
                for (Field field : fields) {
                    field.setAccessible(true);
                    TableField tableField = field.getAnnotation(TableField.class);
                    TableFieldKey tableId = field.getAnnotation(TableFieldKey.class);
                    String name = field.getName();
                    if (tableField != null) {
                        name = tableField.name();
                    }
                    if (tableId != null) {
                        name = tableId.value();
                    }
                    Object object = rs.getObject(name);
                    field.set(t, object);
                }
                list.add(t);
            }
            System.out.println(list);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return list;
    }

 2. 测试

可姨进行相关测试,自己测试

 

标签:tableField,String,CRUD,field,单表,sql,null,name
From: https://blog.csdn.net/m0_72156649/article/details/140315150

相关文章

  • 查看SQLServer最耗资源时间的SQL语句(转载)
    sqlserver中,如果想知道有哪些语句是执行效率不高的,应该如何查看呢?下面就将为您介绍sqlserver中如何查看执行效率不高的语句,供您参考。 1.找出执行时间最长的10条SQL(适用于SQLSERVER2005及其以上版本)Sql代码SELECTtop10(total_elapsed_time/execution_count)......
  • 宋红康MySQL笔记
    MySQL数据库入门到大牛,mysql安装到优化,百科全书级,全网天花板https://www.bilibili.com/video/BV1iq4y1u7vj?p=43&vd_source=ecbebcd4db8fad7f74c518d13e78b165HAVING的使用#练习:查询各个部门中最高工资比10000高的部门信息#错误的写法:SELECTdepartment_id,MAX(salary)FROMem......
  • sqlite3之基础
    最近在用Python借助于pySimpleGui做一个桌面小工具,奉行小巧,简单的宗旨,使用了本地数据库sqlite3来进行本地数据的存储参考:官网: https://www.sqlite.org/指导教程:https://www.sqlitetutorial.net/ 基础语法比较简单,跟MySQL差异并不大,半小时了解一下: http......
  • SQL漏洞--简介及数字型注入
    数据库注入漏洞主要指开发人员在构建代码时,没有对输入边界进行安全考虑,导致攻击者可以通过合法的输入点提交一些精心构造的语句,从而欺骗后台数据库对其进行执行,导致数据库信息泄露的一种漏洞。 一、数字型注入:通过pikachu搭建的靶场进行SQL数字型注入测试:一、数字型注......
  • SQL注入介绍
    一.简介:对于Web应用程序而言,用户核心数据存储在数据库中,例如:MySQL、SQLServer、Oracle等。通过SQL注入攻击,可以获取、修改、删除数据库信息,并且通过提权来控制Web服务器等其他操作。SQL注入由研究员RainForestPuppy发现,在1998年对外发表文章《NTWebTec......
  • 基于springboot+layui+thymeleaf的学生成绩管理系统设计与实现(源码+SQL+使用说明)
    本项目适合做计算机相关专业的毕业设计,课程设计,技术难度适中、工作量比较充实。完整资源获取点击下载完整资源1、资源项目源码均已通过严格测试验证,保证能够正常运行;2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通;3、本项目比较适合计算......
  • 基于SpringBoot + SpringCloud+ElasticSear的在线教育管理系统设计与实现(MySQL、Mongo
    本项目适合做计算机相关专业的毕业设计,课程设计,技术难度适中、工作量比较充实。完整资源获取点击下载完整资源1、资源项目源码均已通过严格测试验证,保证能够正常运行;2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通;3、本项目比较适合计算......
  • MySQL和Redis更新一致性问题
    1.先更新数据库,再更新缓存适用场景:适用于对数据一致性要求不是特别高,且缓存更新失败对系统影响较小的场景。例如,某些非关键数据的缓存更新。风险:如果缓存更新失败,会导致数据库和缓存数据不一致。//更新数据库updateMySQL(data);//更新缓存updateRedis(data);2......
  • SQL Server Compact的简单使用
    今天遇到公司之前一个项目,使用的是SQLServerCompact(SQLCE)数据库,记录一下创建SDF数据库:1.VisualStudio2022安装扩展,SQLiteandSQLServerCompactToolbox2.工具-->SQLite/SQLServerCompactToolbox2.添加一个连接 3.选择路径或者创建一个新的数据库4.已经......
  • MySQL中datetime和timestamp的区别
    #MySQL中datetime和timestamp的区别相同点两个数据类型存储时间的格式一致。均为YYYY-MM-DDHH:MM:SS两个数据类型都包含「日期」和「时间」部分。两个数据类型都可以存储微秒的小数秒(秒后6位小数秒)自动更新和默认值TIMESTAMP:支持默认值为当前时间,且在记录更新时可以......