打怪升级之小白的大数据之旅(三十四)<JDBC的数据库连接与基本操作>

Posted GaryLea

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了打怪升级之小白的大数据之旅(三十四)<JDBC的数据库连接与基本操作>相关的知识,希望对你有一定的参考价值。

打怪升级之小白的大数据之旅(三十四)

JDBC的数据库连接与基本操作

上次回顾

上一章,我们对第一个认识的数据库---->mysql数据库进行了学习,本章节的JDBC是基于Java和Mysql的知识进行的,所以小伙伴们要是对里面的知识点有疑问,可以回看我前面的博客哈。下面开始进入正题

JDBC概述

  • JDBC全称Java Database Connectivity,它是一个独立于特定数据库管理系统、通用的SQL数据库存取和操作的公共接口,定义了用来访问数据库的标准Java类库,使用这个类库可以以一种标准的方法、方便地访问数据库资源
  • 通俗的来说,JDBC就是让我们通过Java来连接任何提供了JDBC驱动程序的数据库系统,比如我有一个SQLServer数据和一个Mysql数据库,我可以通过Java的JDBC来完成前面学习SQL中的所有操作,而无需在命令行来分别连接它们两个,就像这样在这里插入图片描述

JDBC操作数据库、操作表步骤

我来总结一下JDBC操作数据库与表的步骤,然后详细来介绍它们

  1. 注册驱动 (只做一次)
  2. 建立连接(Connection)
  3. 创建执行SQL的语句(Statement)
  4. 执行语句
  5. 处理执行结果(ResultSet)
  6. 释放资源
    看到这里是不是很熟悉,没错,就跟我们前面学习Mysql一样,首先我来介绍一下JDBC的结构与数据库的连接

JDBC体系结构与JDBC API

JDBC体系结构由下面两部分组成:

  • 面向应用的API:Java API,抽象接口,供应用程序开发人员使用(连接数据库,执行SQL语句,获得结果)。
  • 面向数据库的API:Java Driver API,供开发商开发数据库驱动程序使用

JDBC API

  • JDBC API 是一系列的接口,它使得应用程序能够进行数据库联接,执行SQL语句,并且得到返回结果在这里插入图片描述

注册与加载驱动

Driver接口

  • java.sql.Driver 接口是所有 JDBC 驱动程序需要实现的接口。这个接口是提供给数据库厂商使用的,不同数据库厂商提供不同的实现
  • 在程序中不需要直接去访问实现了 Driver 接口的类,而是由驱动程序管理器类(java.sql.DriverManager)去调用这些Driver实现
    • Oracle的驱动:oracle.jdbc.driver.OracleDriver
    • mySql的驱动: com.mysql.jdbc.Driver

加载与注册 JDBC 驱动

  • 前面我们说了,JDBC就是通过一个接口和不同数据库提供了JDBC的驱动来完成数据的操作,因此,我们将驱动加载到JDBC中,加载驱动有两种方式:
  • 方式一:加载 JDBC 驱动需调用 Class 类的静态方法 forName(),向其传递要加载的 JDBC 驱动的类名
     Class.forName(“com.mysql.jdbc.Driver”);
    
  • 方式二:DriverManager 类是驱动程序管理器类,负责管理驱动程序
    DriverManager.registerDriver(com.mysql.jdbc.Driver);
    
  • 通常不用显式调用 DriverManager 类的 registerDriver() 方法来注册驱动程序类的实例,因为 Driver 接口的驱动程序类都包含了静态代码块,在这个静态代码块中,会调用 DriverManager.registerDriver() 方法来注册自身的一个实例

建立连接(Connection)

  • 当我们注册并加载驱动后,就可以连接数据库了,方法和前面我们学习Mysql一样,首先需要输入账号,密码等信息

  • 在JDBC中,我们需要调用DriverManager 类的 getConnection() 方法建立到数据库的连接

  • user,password可以用“属性名=属性值”方式告诉数据库;

  • 在JDBC中连接数据库需要一个特殊的属性,JDBC URL,它用于连接我们需要操作的数据库

  • JDBC URL的标准由三部分组成,各部分间用冒号分隔。

    jdbc:子协议:子名称
    协议:JDBC URL中的协议总是jdbc 
    子协议:子协议用于标识一个数据库驱动程序
    子名称:一种标识数据库的方法。子名称可以依不同的子协议而变化,用子名称的目的是为了定位数据库提供足够的信息。包含主机名(对应服务端的ip地址),端口号,数据库名
    
  • 下面我来列举几个常见的JDBC URL,大家使用的时候直接复制就好

    // 对于 Oracle 数据库连接,采用如下形式: 
    jdbc:oracle:thin:@localhost:1521:DatabaseName
    // 对于 SQLServer 数据库连接,采用如下形式:
    jdbc:microsoft:sqlserver//localhost:1433; DatabaseName=sid
    // 对于 MYSQL 数据库连接,采用如下形式:   
    jdbc:mysql://localhost:3306/DatabaseName
    // 插入中文的时候,这个url要写成这个
    jdbc:mysql://localhost:3306/数据库名称?useUnicode=true&characterEncoding=UTF-8
    
  • 小伙伴们注意一下,当我们使用Java向数据库中插入一个数据时,如果是中文,首先数据库和表的编码是utf8,其次就是我们要在URL中声明一下编码是UTF-8,不然插入数据是?,如果你们遇到这个问题,那就忽略它

  • 好了,下面是连接数据库的示例代码,这里我操作的是Mysql数据库

    package com.company;
    // 导入依赖包
    import org.junit.Test;
    import java.io.FileInputStream;
    import java.sql.Connection;
    import java.sql.Driver;
    import java.sql.DriverManager;
    import java.sql.SQLException;
    import java.util.Properties;
    
    public class Demo1 {
    /*
    *获取connect的三种方式
    *  */
        public static void main(String[] args) {
            System.out.println("JDBC Test...");
        }
    	
    	// 使用Driver来实现数据库连接
        @Test
        public void test1() throws SQLException {
    		// 
            Driver driver=new com.mysql.jdbc.Driver();
            Properties p1 = new Properties();
            p1.setProperty("user", "root");
            p1.setProperty("password", "mysql123");
            Connection connect = driver.connect("jdbc:mysql://localhost:3306/myemployees", p1);
            System.out.println("connect = " + connect);
    
        }
    	
    	// 使用DriverManager来实现数据库连接
        @Test
        public void test2() throws SQLException {
            com.mysql.jdbc.Driver driver = new com.mysql.jdbc.Driver();
            Properties p1 = new Properties();
            p1.setProperty("user", "root");
            p1.setProperty("password", "mysql123");
            DriverManager.registerDriver(driver);
            Connection connection = DriverManager.getConnection
                    ("jdbc:mysql://localhost:3306/myemployees", p1);
    
            System.out.println("connection = " + connection);
    
        }
    	// 将账号密码抽出到配置文件中,并使用IO流读取配置文件的方式连接数据库
        @Test
        public void test3() throws Exception {
            Properties p = new Properties();
    
            FileInputStream fis = new FileInputStream("p.properties");
            p.load(fis);
            fis.close();
            Class.forName(p.getProperty("driverClass"));
            Connection connection = DriverManager.getConnection(p.getProperty("url"),
                    p.getProperty("user"), p.getProperty("password"));
            System.out.println("connection = " + connection);
    
        }
    }
    

    properties文件内容

    url=jdbc:mysql://localhost:3306/myemployees
    user=root
    password=mysql123
    driverClass=com.mysql.jdbc.Driver
    

使用PreparedStatement

  • 介绍完注册驱动与数据库的连接,接下来就是操作SQL了,在JDBC中,操作SQL需要使用Connection 对象的 preparedStatement() 方法获取 PreparedStatement 对象

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

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

  • 在操作SQL前还要说明一下数据类型,我们知道SQL与Java的数据类型命名是不一样的,所以我们在编码时要注意

    java类型SQL类型
    booleanBIT
    byteTINYINT
    shortSMALLINT
    intINTEGER
    longBIGINT
    StringCHAR,VARCHAR,LONGVARCHAR
    byte arrayBINARY , VAR BINARY
    java.sql.DateDATE
    java.sql.TimeTIME
    java.sql.TimestampTIMESTAMP
  • 使用PreparedStatementSQL的操作步骤

    • 调用连接对象的prepareStatement方法,创建PreparedStatement对象
    • 完成预编译的SQL语句
    • 对SQL语句中的占位符进行赋值
    • 提交SQL语句
    • 释放资源
  • 接下来就是操作SQL增删改查的示例代码(为了方便操作,我将数据库连接抽出到了JDBCUtils类中)

    // 使用PreparedStatement来完成数据的增删改查操作
    package com.company.jdbc;
    
    import org.junit.Test;
    
    import java.io.FileInputStream;
    import java.sql.*;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Properties;
    
    /*
     对数据库进行增,删,改,查的操作
     */
    public class CRUDDemo {
    
        /*
            添加一条数据
    
            CREATE TABLE student(
            sid INT,
            sname VARCHAR(20),
            sage INT
            )
         */
        @Test
        public void test() throws SQLException {
            //1.获取数据库连接对象
            Connection connection = JDBCUtils.getConnection();
            //2.预编译
            // ? : 占位符(只能是设置数据的地方可以写成占位符)
            String sql = "insert into student(sid,sname,sage) values(?,?,?)";
            PreparedStatement ps = connection.prepareStatement(sql);
            //3.给占位符赋值
            /*
            setInt(int parameterIndex, int x)
            parameterIndex : 参数索引(第几个占位符)
            x : 数据
             */
            ps.setInt(1,100);
            //数据设置成中文可不可以取决于表的编码集
            ps.setString(2,"longge");
            ps.setInt(3,20);
            //4.执行sql
            //返回值 : 有几条数据受到影响
            int result = ps.executeUpdate();//增,删,改的语句使用该方法
            System.out.println("有"+result+"条数据受到影响");
            //5.关资源
            JDBCUtils.close(ps,connection);
        }
    
        /*
            改
         */
        @Test
        public void test2() throws SQLException {
            //1.获取数据库连接对象
            Connection connection = JDBCUtils.getConnection();
            //2.预编译
            String sql = "update student set sid=? where sid=?";
            PreparedStatement ps = connection.prepareStatement(sql);
            //3.给占位符赋值
            ps.setInt(1,10);
            ps.setInt(2,100);
            //4.执行sql语句
            int result = ps.executeUpdate();
            System.out.println("有"+result+"条数据受到影响");
            //5.关闭资源
            JDBCUtils.close(ps,connection);
        }
    
        /*
            删除数据
         */
        @Test
        public void test3() throws SQLException {
            //1.获取数据库连接对象
            Connection connection = JDBCUtils.getConnection();
            //2.预编译
            String sql = "delete from student where sid=?";
            PreparedStatement ps = connection.prepareStatement(sql);
            //3.给占位符赋值
            ps.setInt(1,10);
            //4.执行sql语句
            int i = ps.executeUpdate();
            System.out.println("有"+i+"条数据受到影响");
            //5.关闭资源
            JDBCUtils.close(ps,connection);
        }
    
        /*
            查询数据
         */
        @Test
        public void test4() throws Exception {
            List<Student> students = getStudent();
            for (Student s : students) {
                System.out.println(s);
            }
    
        }
    
        public List<Student> getStudent() throws Exception {
            //1.获取数据库连接对象
            Connection connection = JDBCUtils.getConnection();
            //2.预编译
            PreparedStatement ps = connection.prepareStatement("select sid,sname,sage from student");
            //3.执行sql语句
            ResultSet resultSet = ps.executeQuery();//查询语必须执行此方法
    
            List<Student> list =  new ArrayList<>();
            //4.遍历ResultSet
            while(resultSet.next()){//是否有数据
                /*
                    getInt(String columnLabel) :根据字段名获取对应的数据
                    getInt(int columnIndex) : 根据列的索引获取对应的数据
                 */
                int sid = resultSet.getInt("sid");
                String sname = resultSet.getString("sname");
                int sage = resultSet.getInt("sage");
    
                //System.out.println(sid + " " + sname + " " + sage);
                list.add(new Student(sid,sname,sage));
            }
            //5.关闭资源
            JDBCUtils.close(ps,connection,resultSet);
    
            return list;
        }
    
    }
    
    
  • JDBCUtils连接数据库的工具类

    //JDBCUtils类,专门实现数据库的连接与资源释放操作
    package com.company.jdbc;
    
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.sql.*;
    import java.util.Properties;
    
    public class JDBCUtils {
        private static String driverClass;
        private static String url;
        private static String username;
        private static String password;
    
        static{
            FileInputStream fis = null;
            try {
                //1.获取数据库连接对象
                //通过Properties读取内容
                //1.创建Properties对象
                Properties p = new Properties();
                //2.加载流
                fis = new FileInputStream("jdbc.properties");
                p.load(fis);
                driverClass = p.getProperty("driverClass");
                url = p.getProperty("url");
                username = p.getProperty("username");
                password = p.getProperty("password");
            }catch (Exception e){
                //终止程序的运行
                e.printStackTrace();
                //将编译时异常转换成运行时异常
                throw new RuntimeException("xxxxxxxx");
            }finally {
                if (fis != null){
                    //3.关资源
                    try {
                        fis.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    
        /*
            获取连接对象
         */
        public static Connection getConnection(){
            try {
                Class.forName(driverClass);
                //获取数据库连接对象
                Connection connection = DriverManager.getConnection(url, username, password);
                return connection;
            }catch (Exception e){
                e.printStackTrace();
                throw new RuntimeException("获取连接失败");
            }
        }
    
        /*
            关闭资源
         */
        public static void close(PreparedStatement ps, Connection connection) {
            if (ps != null){
                try {
                    ps.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
    
            if (connection != null){
                try {
                    connection.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
        }
    
        public static void close(PreparedStatement ps, Connection connection, ResultSet resultSet) {
            close(ps,connection);
            if (resultSet != null){
                try {
                    resultSet.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
        }
    }
    
    

关于ResultSet的说明

  • 在前面对数据的增删改查操作中,查询操作比较复杂一些,因为我们要接收数据库返回的结果,因此我们要了解一下ResultSet 接口,它由数据库厂商实现
  • 查询需要调用Prepared Statement 的 executeQuery() 方法,查询结果是一个 ResultSet 对象
  • ResultSet 对象维护了一个指向当前数据行的游标,初始的时候,游标在第一行之前,可以通过 ResultSet 对象的 next() 方法移动到下一行,具体方法可以自定百度
  • ResultSet:代表结果集,其封装了使用 JDBC 进行查询的结果. 调用 PreparedStatement 对象的 executeQuery() 可以得到结果集.
    ResultSet 返回的实际上就是一张数据表. 有一个指针指向数据表的第一条记录的前面在这里插入图片描述

总结

本章主要介绍了JDBC以及JDBC如何连接数据库,实现数据的增删改查操作,下一章是JDBC的扩展知识—>我们自己实现的那个连接数据库的工具类毕竟不是那么严谨,下一章就是介绍一个框架,以后连接数据库就不用这么麻烦了.

以上是关于打怪升级之小白的大数据之旅(三十四)<JDBC的数据库连接与基本操作>的主要内容,如果未能解决你的问题,请参考以下文章

打怪升级之小白的大数据之旅(三十六)<初识Maven>

打怪升级之小白的大数据之旅(三十七)<Maven的核心知识>

打怪升级之小白的大数据之旅(七十四)<初识Kafka>

打怪升级之小白的大数据之旅(七十四)<初识Kafka>

打怪升级之小白的大数据之旅(七十四)<初识Kafka>

打怪升级之小白的大数据之旅(七十四)<初识Kafka>