JDBC java数据库连接

一、什么是JDBC

JDBC的全称是Java数据库连接(Java Database Connectivity),它是一套用于执行SQL语句的Java API。应用程序可通过这套API连接到关系型数据库,并使用SQL语句完成对数据库中数据的新增、删除、修改和查询等操作。

二、JDBC常用API

在开发JDBC程序前,先了解一下JDBC常用的API。JDBC API主要位于java.sql包中,该包定义了一系列访问数据库的接口和类。

(1)Driver接口

Driver接口是所有JDBC驱动程序必须实现的接口,该接口专门提供给数据库厂商使用。需要注意的是,在编写JDBC程序时,必须要把所使用的数据库驱动程序或类库加载到项目的classpath中(这里指MySQL驱动JAR包)。

(2)DriverManager接口

DriverManager接口用于加载JDBC驱动、创建与数据库的连接。在DriverManager接口中,定义了两个比较重要的静态方法.

(3)Connection接口

Connection接口用于处理与特定数据库的连接,Connection对象是表示数据库连接的对象,只有获得该连接对象,才能访问并操作数据库。

(4)Statement接口

Statement接口用于执行静态的SQL语句,并返回一个结果对象。Statement接口对象可以通过Connection实例的createStatement()方法获得,该对象会把静态的SQL语句发送到数据库中编译执行,然后返回数据库的处理结果。

(5)PreparedStatement 接口

Statement接口封装了JDBC执行SQL语句的方法,可以完成Java程序执行SQL语句的操作。然而在实际开发过程中往往需要将程序中的变量作为SQL语句的查询条件,而使用Statement接口操作这些SQL语句会过于繁琐,并且存在安全方面的问题。针对这一问题,JDBC API 提供了扩展的PreparedStatement接口。

PreparedStatement是Statement的子接口,用于执行预编译的SQL语句。PreparedStatement接口扩展了带有参数SQL语句的执行操作,该接口中的SQL语句可以使用占位符“?”代替参数,然后通过setter()方法为SQL语句的参数赋值。

(6)ResultSet接口

ResultSet接口用于保存JDBC执行查询时返回的结果集,该结果集封装在一个逻辑表格中。在ResultSet接口内部有一个指向表格数据行的游标(或指针),ResultSet对象初始化时,游标在表格的第一行之前,调用next()方法可以将游标移动到下一行。如果下一行没有数据,则返回false。在应用程序中经常使用next()方法作为while循环的条件来迭代ResultSet结果集。

程序既可以通过字段的名称来获取指定数据,也可以通过字段的索引来获取指定的数据,字段的索引是从1开始编号的。

三、实现JDBC

第一步,加载并注册数据库驱动

两种方式

第一种,java.lang.Class类的静态方法forName(String  className)

Class.forName("DriverName");

第二种,DriverManager类的静态方法registerDriver(Driver driver)

DriverManager.registerDriver(Driver driver);

实际开发中常用第一种,DriverName表示数据库的驱动类。例如在mysql中,MySQL驱动类在6.0.2版本之前为com.mysql.jdbc.Driver,而在6.0.2版本之后为com.mysql.cj.jdbc.Driver。

第二步 ,通过DriverManager获取数据库连接

获取数据库连接的具体方式

Connection conn = DriverManager.getConnection(String url, String user, String pwd);

以上三个参数分别表示连接数据库的地址、登录数据库的用户名和密码。

eg:jdbc:mysql://hostname:port/databasename

如果是在高版本mysql中以上格式会报错,只需要改为:

url=jdbc:mysql://127.0.0.1:3306/jdbc?characterEncoding=utf8&useSSL=true  即可

jdbc:mysql:是固定的写法,mysql指的是MySQL数据库,hostname指的是主机的名称,port指的是连接数据库的端口号(MySQL端口号默认为3306),databasename指的是MySQL中相应数据库的名称。

第三步,通过第二步中的Connection对象获取Statement对象

Connection创建Statement对象的方法有3个(预处理对象):

createStatement():创建基本的Statement对象。

prepareStatement():创建PreparedStatement对象(主要)

repareCall():创建CallableStatement对象

 第四步,使用Statement执行SQL语句

所有的Statement都有3种执行SQL语句的方法:

execute():可以执行任何SQL语句,返回布尔值

executeQuery():通常执行查询语句,执行后返回代表结果集的ResultSet对象。

 executeUpdate():主要用于执行DML和DDL语句。执行DML语句,如INSERT、UPDATE或DELETE时,返回受SQL语句影响的行数。

第五步,操作ResultSet结果集

如果是查询语句,执行结果将返回一个ResultSet对象。该对象保存了SQL语句查询的结果。程序可以通过操作该ResultSet对象取出查询结果。

next()向下移动一行,同时如果没有下一行,返回false

previous()向上移动一行,如果没有上一行,返回false

getxxx(列的索引 || 列名),返回对应列的值,接收的类型和xxx一样

getObject(列的索引 || 列名),返回对应列的值,接收的类型为Object

第六步,关闭连接,释放资源

每次操作数据库结束后都要关闭数据库连接,释放资源,关闭顺序和声明顺序相反。需要关闭的资源包括ResultSet、Statement和Connection等。

注意:

在后续可以不必显式注册驱动。因为在DriverManager的源码中已经存在静态代码块,实现了驱动的注册。  

代码

前置环境,需要有数据库,创建表数据。在项目中添加相关的依赖。

public class example01 {
    public static void main(String[] args) throws Exception {
        Connection conn = null;
        Statement statement = null;
        ResultSet resultSet = null;
        try {
            //1.注册数据库驱动
            Class.forName("com.mysql.cj.jdbc.Driver");
            //2.获取数据库连接
            String url = "jdbc:mysql://localhost:3306/mydb";
            String root = "root";
            String password = "123456";
            conn = DriverManager.getConnection(url, root, password);
            //3.获取Statement对象
            statement = conn.createStatement();
            //4.使用Statement执行SQl语句
            String sql = "select * from user";
            resultSet = statement.executeQuery(sql);
            //5.操作ResultSet结果集
            while (resultSet.next()) {
                int id = resultSet.getInt("id");// 通过列名获取指定字段的值
                String name = resultSet.getString("username");
                String password1 = resultSet.getString("password");
                System.out.println(id + "  |  " + name + "  |  " + password1);
            }
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
        if (resultSet != null) {
            try {
                resultSet.close();
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }
        if (statement != null) {
            try {
                statement.close();
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }
        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

四、使用JDBC实现增删改查的基本操作

以上为正常的数据库连接,接下来使用便捷的方法。

创建一个properties的文件,文件输入相应的配置信息。

将JDBC操作的连接,关闭封装到一个类中,使用时调用相对应的方法。

使用PreparedStatement进行操作: 

PreparedStatement 接口是 Statement 的子接口,它表示一条预编译过的SQL语句

 PreparedStatement 对象所代表的 SQL 语句中的参数用问号(?)来表示,调用 PreparedStatement 对象的 setXxx() 方法来设置这些参数。setXxx() 方法有两个参数,第一个参数是要设置的 SQL 语句中的参数的索引( 1 开始),第二个是设置的 SQL 语句中的参数的值。

public class JDBCUtils{
    /**
     * 数据库连接
     * @return
     * @throws Exception
     */
    public static Connection getConnection() throws Exception{
        //1.读取配置文件的4个基本信息
        InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties");
        Properties pros = new Properties();
        pros.load(is);
        String user = pros.getProperty("user");
        String password = pros.getProperty("password");
        String url = pros.getProperty("url");
        String driverClass = pros.getProperty("driverClass");
        //2.加载驱动
        Class.forName(driverClass);
        //3.获取连接
        Connection conn = DriverManager.getConnection(url,user,password);
        return conn;
    }

    /**
     * 数据库资源关闭
     * @param conn
     * @param ps
     * @param rs
     */
    public static void closeResource(Connection conn, Statement ps, ResultSet rs){
        try {
            if (ps != null)
                ps.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        try {
            if(conn != null)
                conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        try {
            if(rs != null)
                rs.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
   @Test
   public void test() throws Exception {
       Com com = new Com();
       String sql =  "update user set password = ? where id = ? ";
       com.update(sql,123456 ,1);
   }

ResultSetMetaData

getColumnName(int column):获取指定列的名称

getColumnLabel(int column):获取指定列的别名 

getColumnCount():返回当前 ResultSet 对象中的列数。

getColumnTypeName(int column):检索指定列的数据库特定的类型名称。

getColumnDisplaySize(int column):指示指定列的最大标准宽度,以字符为单位。

isNullable(int column):指示指定列中的值是否可以为 null

isAutoIncrement(int column):指示是否自动为指定列进行编号,这样这些列仍然是只读的。

Java与数据库交互涉及到的相关Java API中的索引都从1开始。  

    /**
     * 针对不同数据表的查询操作
     * @param clazz
     * @param sql
     * @param args
     * @return
     * @param <T>
     */
    public <T> T getInstance(Class<T> clazz, String sql, Object... args) {
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            // 1.获取数据库连接
            conn = JDBCUtils.getConnection();
            // 2.预编译sql语句,得到PreparedStatement对象
            ps = conn.prepareStatement(sql);
            // 3.填充占位符
            for (int i = 0; i < args.length; i++) {
                ps.setObject(i + 1, args[i]);
            }
            // 4.执行executeQuery(),得到结果集:
            ResultSet resultSet = ps.executeQuery();
            // 5.得到结果集的元数据:ResultSetMetaData
            ResultSetMetaData rsmd = resultSet.getMetaData();
            // 6.1通过ResultSetMetaData得到columnCount,columnLabel;通过ResultSet得到列值
            int columnCount = rsmd.getColumnCount();
            if (resultSet.next()) {
                T t = clazz.newInstance();
                for (int i = 0; i < columnCount; i++) {
                    //获取列值
                    Object columnVal = resultSet.getObject(i + 1);
                    // 获取列的别名:列的别名,使用类的属性名充当
                    String columnLabel = rsmd.getColumnLabel(i + 1);
                    // 6.2使用反射,给对象的相应属性赋值 记得有对应的类以及属性
                    Field field = clazz.getDeclaredField(columnLabel);
                    field.setAccessible(true);
                    field.set(t, columnVal);
                }
                return t;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally { // 7.关闭资源
            JDBCUtils.closeResource(conn, ps, rs);
        }
        return null;
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值