【JDBC操作数据库】JDBC-数据库连接/对数据库CRUD(增、删、改、查)封装可通用方法

前言

     当你项目不考虑并发、高性能、追求更快的开发效率,业务只涉及单表时推荐使用该方法(不写重复代码)

关于JDBC操作数据库主要分享两点

  1. 【图+说】JDBC-数据库连接
  2. 【JDBC工具类】对数据库 CRUD(增、删、改、查)封装可通用方法

JDBC操作数据库步骤

  1. 导入jar包,加载驱动
  2. 获取连接Connection
  3. 获取执行SQL语句的对象PreparedStatement
  4. 执行增删改查操作
  5. 解析查询结果ResultSet
  6. 关闭释放资源

1,2.3在JDBC--数据库连接讲解说明

3,4,5在对数据库CRUD(增、删、改、查)封装可通用方法中实战说说明具体操作

一.JDBC--数据库连接

1.1.1导入MySQL数据库驱动jar包 mysql-connector-java-xxx.jar(xxx是驱动的版本)

1.1.2【maven项目】MySQL数据库驱动依赖写法(pom.xml中加入,这里我用的是5.1.22驱动版本)

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.22</version>
</dependency>

1.2.加载MySQL驱动,核心代码Class.forName("com.mysql.jdbc.Driver");

        此处可能会抛出java.lang.ClassNotFoundException: com.mysql.jdbc.Driver异常,抛出该异常的原因就是未正确导入jar包

static {
    try {
        //加载驱动
        Class.forName("com.mysql.jdbc.Driver");
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
}

2.获取和MySQL的连接,获取连接时需要提供待连接的数据库的url、用户名和密码

   private static String url = "jdbc:mysql://localhost:3306/数据库名?useSSL=true&useUnicode=true&characterEncoding=UTF-8"
        private static String username = "数据库用户名";
        private static  String password = "数据库密码"; 
//获取数据库连接
        public static Connection getConection(){
            Connection con = null ;
            try {
                con = DriverManager.getConnection(url, username, password);
            } catch (SQLException e) {
                e.printStackTrace();
            }
            return con ;
        }

6关闭数据库资源

        注意是先关闭结果集(ResultSet),再关闭语句(PreparedStatement),最后关闭连接(Connection)。

原因:如果connection关闭了,后面Statement和ResultSet相关的操作就会受到影响。所以平时一定要注意关闭资源的先后顺序,先关闭ResultSet,然后是Statement,最后是Connetion,刚好与创建相应对象时的顺序相反。

public static void closeAll(AutoCloseable...ables){
        for (AutoCloseable able : ables) {
            if(able!=null){
                try {
                    able.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

二、【JDBC工具类】对数据库 CRUD(增、删、改、查)封装可通用方法

CRUD通用方法局限性

  • 实体类名字必须和表名一致
  • 安全性低(暴漏字段名)
  • 灵活性低(通用和灵活永远的矛盾体)
  • Update操作时会全表更新
  • Select操作会全字段查询

这里直接上代码解说了,里面一行一注释!!不懂最后留言互动!!

CRUD(增、删、改、查)代码【可直接使用,亲测有效】

声明:Object...obj为可变数组参数,传参数时可传可不传,效果类似Object[] obj

调用时什么都没有传,那么Object[]的长度就是0。传的时候传了几个,Object[]的长度就是几,下标获取对应传参值


public boolean  CUD(String sql , Object...obj){}

  • 参数1:要执行的sql语句(insert/update/delete)
  • 参数2:要注入的参数值与sql中?对应的参数 

public <T> List<T> Query(String sql, Class<T> clazz, Object...obj)

  • 参数1:要执行查询的的sql语句(select)
  • 参数2:反射获取Class实例对象(三种方式:类名.class/new 类名().getClass/Clas.forName(全限定类名))
  • 参数3要注入的参数值与sql中?对应的参数
package com.cxl.jdbcutils;
​
import java.awt.image.RasterFormatException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
​
/**
 * @author 萌小崔
 * @version 1.0
 * @description: JDBC工具类
 * @date 2021/11/2 16:48
 */
public class JDBCUtils {
​
    private String url = null;
    private String username = null;
    private String password = null;
    //初始化工具类  连接数据库  参数1:url  参数2:数据库用户名  参数3:数据库用户密码
    public JDBCUtils(String url,String username,String password) {
        this.url = url;
        this.username = username;
        this.password = password;
    }
​
    //加载驱动
    static {
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
​
    //连接数据库
    public Connection getConnection(){
        Connection con = null ;
        try {
            con = DriverManager.getConnection(url, username, password);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return con;
    }
​
    //释放资源
    public  void closeresource(AutoCloseable...ables){
        for (AutoCloseable able : ables) {
            if(able!=null){
                try {
                    able.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
​
    //增删改通用方法
    public boolean CUD(String sql , Object...obj){
        //连接数据库
        Connection con = getConnection();
        PreparedStatement pstmt = null ;
        try {
            //获取预编译对象
            pstmt = con.prepareStatement(sql);
            //获取预编译对象元数据
            ParameterMetaData pmd = pstmt.getParameterMetaData();
            //获取元数据参数个数
            int parameterCount = pmd.getParameterCount();
            //判断参数个数同占位符数量是否一致
            if(parameterCount!=obj.length){
                //不一致
                throw new RasterFormatException("占位符同参数个数不等");
            }else{
                for (int i = 0; i < obj.length; i++) {
                    //一致 将其赋值  顺序必须一致
                    pstmt.setObject(i+1, obj[i]);
                }
                int executeUpdate = pstmt.executeUpdate();
                return executeUpdate>0;
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally {
            //关流
            closeresource(pstmt,con);
        }
        return false;
    }
​
    //查询通用方法
    public <T> List<T> Query(String sql, Class<T> clazz, Object...obj){
        //T  Student  泛型方法     List<T> 实现List接口泛型集合,
        ArrayList<T> list = new ArrayList();
        Connection con = getConnection();
        PreparedStatement ps = null ;
        ResultSet rs=null;
        try {
            //获取sql的预编译对象
            ps = con.prepareStatement(sql);
            //获取该对象的元数据
            ParameterMetaData pmd = ps.getParameterMetaData();
            //获取数据中的参数个数   也就是占位符的个数
            int parameterCount = pmd.getParameterCount();
            //判断占位符个数同参入个数是否相等
            if(parameterCount!=obj.length){
                //不相等报错提示
                throw new RasterFormatException("占位符数同参数数量不等");
            }else{
                //相等情况下将传入参数赋值给sql语句
                for(int i=0;i<obj.length;i++){
                    ps.setObject(i+1, obj[i]);
                }
                //执行sql语句
                rs = ps.executeQuery();//查询       返回ResultSet  结果集rs
                //获取结果集的元数据
                ResultSetMetaData metaData = rs.getMetaData();
                //获取列名数量
                int columnCount = metaData.getColumnCount();
                while(rs.next()){
                    //反射创建对象  无参构造
                    T bean = clazz.newInstance();
                    for(int i=1;i<=columnCount;i++){
                        //获取列名 (字段名在同一列  从1开始  往下)
                        //获取列名  时 数据库 +  别名 (同实体类对应)
                        String catalogName = metaData.getColumnName(i);
                        //通过列名获取对应的值
                        Object object = rs.getObject(catalogName);
                        //通过反射 获取 列名的 set get 方法 比如 你的eid
                        //   (PropertyDescriptor下面有解释)
                        PropertyDescriptor propertyDescriptor = new PropertyDescriptor(catalogName, clazz);
                        //调用写入属性值得方法
                        Method writeMethod = propertyDescriptor.getWriteMethod();
                        //调用方法  给其赋值
                        writeMethod.invoke(bean, object);
                    }
                        /*
                        思路:rs  是你查询到的结果集
                           循环遍历rs  while里主要执行是创建你传入的对象 将其赋值 然后加到list中去
                        */
                    list.add(bean);
                }
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally {
            closeresource(rs,ps,con);   //先关闭结果集(ResultSet),再关闭语句(PreparedStatement),最后关闭连接(Connection)
        }
        return list;
    }
​
}

【解释】查询方法中PropertyDescriptor 类表示 JavaBean 类通过存储器导出一个属性。

构造方法有:

PropertyDescriptor(String propertyName, Class<?> beanClass)
​
PropertyDescriptor(String propertyName, Class<?> beanClass, String readMethodName, String writeMethodName)
​
PropertyDescriptor(String propertyName, Method readMethod, Method writeMethod)

常用方法有:

Class<?> getPropertyType() // 获取属性的java类型对象
Method getReadMethod() // 获得用于读取属性值的方法
Method getWriteMethod() // 获得用于写入属性值的方法

【实战】CRUD封装方法的使用教程

如上所说的该方法有一定的局限性,主要一点实体类名字必须和表名一致

数据库/实体类 

测试类

public class MyTest {
​
    public static void main(String[] args) {
        //初始化工具类  连接数据库  参数1:url  参数2:数据库用户名  参数3:数据库用户密码
        JDBCUtils jdbc = new JDBCUtils("jdbc:mysql://localhost:3306/zg2cvs?useUnicode=true&characterEncoding=utf-8", "root", "123456");
        List<Waipai> byLIst = jdbc.findByLIst("select * from waipai", Waipai.class);
        for (Waipai waipai : byLIst) {
            System.out.println(waipai);
        }
    }
}

测试效果:


到此JDBC操作数据库讲解就结束了!有疑问尽可留言互动!!!!

Thanks!1

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

北九二七

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值