使用原生JDBC方式实现对数据库的增删改查, 查询时能够将数据库记录映射到实体对象上

package com.xiao;

import java.lang.reflect.Field;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;


/**
 * @Author:令狐冲
 * @Version:1.0
 * @DateTime:2024/7/7 13:13
 * @Since:jdk1.8
 * @Description:
 */
public class Test {
    public static void main(String[] args) {
        Connection conn = null;
        try {
            // 1. 加载驱动
            Class.forName("com.mysql.jdbc.Driver");
            // 2. 在Driver类中的static静态代码块中已经将驱动注册到驱动管理器中, 所以不需要重复注册
            // 直接使用DriverManager拿到数据库连接
            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/practice?useSSL=false", "root", "admin123");
            System.out.println(conn);
            // 3. 使用java对象作为数据载体增删改查
            // 3.1 增
            StuInfo stuInfo = new StuInfo();
            stuInfo.setStuName("杰瑞");
            stuInfo.setStuNum("100001");
            stuInfo.setGender("男");
            insert(conn, stuInfo);
            // 3.2 删 -> 根据id删
            deleteById(conn, 2);
            // 3.3 改
            updateById(conn, "tom", 1);
            // 3.4 查
            StuInfo si = findById(conn, 1);
            System.out.println(si);
        } catch (ClassNotFoundException | SQLException e) {
            throw new RuntimeException(e);
        } finally {
            close(conn);
        }
    }


    // 增
    public static void insert(Connection connection, StuInfo stuInfo) {
        // 1. 定义sql
        String sql = "insert into stu_info values (?, ?, ?, ?)";
        PreparedStatement ps = null;
        try {
            // 2. 获取预编译语句
            ps = connection.prepareStatement(sql);
            ps.setObject(1, stuInfo.getId());
            ps.setObject(2, stuInfo.getStuName());
            ps.setObject(3, stuInfo.getStuNum());
            ps.setObject(4, stuInfo.getGender());
            // 3. 执行sql
            ps.execute();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            close(ps);
        }
    }

    // 删
    public static void deleteById(Connection connection, Integer id) {
        String sql = "delete from stu_info where id = ?";
        PreparedStatement ps = null;
        try {
            ps = connection.prepareStatement(sql);
            ps.setObject(1, id);
            ps.execute();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            close(ps);
        }
    }

    // 改
    public static void updateById(Connection connection, Object... args) {
        String sql = "update stu_info set stu_name = ? where id = ?";
        PreparedStatement ps = null;
        try {
            ps = connection.prepareStatement(sql);
            ps.setObject(1, args[0]);
            ps.setObject(2, args[1]);
            ps.execute();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            close(ps);
        }
    }


    // 查
    public static StuInfo findById(Connection connection, Integer id) {
        String sql = "select * from stu_info where id = ?";
        PreparedStatement ps = null;
        try {
            ps = connection.prepareStatement(sql);
            ps.setObject(1, id);
            ResultSet resultSet = ps.executeQuery();
            // 将结果集封装成一个StuInfo对象
            List<StuInfo> stuInfos = getObjs(StuInfo.class, resultSet);
            // 因为是根据唯一字段查的, 所以将集合中第一个stuInfo返回即可
            return stuInfos.isEmpty() ? null : stuInfos.get(0);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            close(ps);
        }
    }

    // 表与java对象的映射
    public static <T> List<T> getObjs(Class<T> clazz, ResultSet resultSet) {
        // 1. 要想把数据库记录和java对象做映射, java类的属性定义必须遵守规则; 数据库 stu_num -> 属性 stuNum
        try {
            // 2. 拿到结果集的列信息
            ResultSetMetaData metaData = resultSet.getMetaData();
            // 3. 拿到一共多少列
            int columnCount = metaData.getColumnCount();
            // 4. 定义一个集合, 用于存储映射出来的对象
            List<T> ts = new ArrayList<>();
            // 5. 遍历结果集
            while (resultSet.next()) {
                // 6. 定义一个T类型对象, 用于存储当前记录
                T t = clazz.newInstance();
                // 7. 遍历列
                for (int i = 1; i <= columnCount; i++) {
                    // 8. 获得列名和列值
                    String columnName = metaData.getColumnName(i);
                    Object value = resultSet.getObject(i);
                    // 9. 将列名转化成属性名格式
                    String fieldName = tableColNameToFieldName(columnName);
                    // 10. 查找类对象的fieldName为属性名的属性
                    Field field = clazz.getDeclaredField(fieldName);
                    // 11. 开启访问权限
                    field.setAccessible(true);
                    // 12. 为t对象设置改属性的值
                    field.set(t, value);
                }
                // 13. 没一行遍历完成后得到一个完整的T对象, 将他放入集合之中
                ts.add(t);
            }
            return ts;
        } catch (SQLException | InstantiationException | IllegalAccessException | NoSuchFieldException e) {
            throw new RuntimeException(e);
        } finally {
            close(resultSet);
        }
    }

    // stu_name -> stuName
    public static String tableColNameToFieldName(String colName) {
        StringBuilder sb = new StringBuilder();
        String[] sp = colName.split("_");
        // 将第一个字符串先加进来
        sb.append(sp[0]);
        for (int i = 1; i < sp.length; i++) {
            char firstChar = sp[i].charAt(0);
            // 将除第一个字符的首字母大写
            String s = sp[i].replaceFirst(firstChar + "", Character.toUpperCase(sp[i].charAt(0)) + "");
            sb.append(s);
        }
        return sb.toString();
    }

    // 关闭资源
    public static void close(AutoCloseable res) {
        try {
            res.close();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值