一篇文章让你彻底明白JDBC~

Posted SharingOfficer

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一篇文章让你彻底明白JDBC~相关的知识,希望对你有一定的参考价值。

1. 啥是 JDBC ?

JDBC 全称:

Java DataBase Connection
复制代码

意思就是使用 java 代码连接数据库

但是问题来了,世界上有一堆数据库例如 mysql、Oracle、mongodb 等,他们的使用方法都不太一样。

难道我要连不同的数据库就需要写不同的 java 程序吗?这也太麻烦了。

为了解决这个问题,SUN 公司(开发JDK的公司)就决定指定一套接口,这套接口就是使用 java 连接数据库的规范,其实就是 JDBC。

而 JDBC 接口的实现类由数据库厂家负责编写,他们编写后把实现类打包成 jar 包。

这个 jar 包就是一个驱动(例如电脑要连上网需要安装网卡驱动),我们下载好这个驱动后把他放到我们的项目里。

接着编写 java 代码去完善 jar 包要求的连接数据库的信息,然后就能连接到与驱动对应的数据库了。

前面我们在学面向对象的时候知道接口体现了多态性。SUN 公司设计一个 JDBC 规范,不用过多关注数据库厂商怎样实现这个接口,大大提高了程序的可扩展性。

2. 导入 jar 包

这里我们以连接 Mysql 为例。

  1. 将连接 mysql 数据库的 jar 包放到 lib 目录下。

注:jar 包就是连接数据库的驱动。每个数据库的厂商将自己实现了 JDBC 的代码打包成 jar 包。

  1. 将 jar 包作为库添加到项目中。

注:因为 jar 包就是编译后的 java 代码,所以这里就相当于在项目中添加了 java 代码。

选择 lib 目录,右键选择 Add as a Library。

3. 开发步骤

  1. 加载数据库的驱动
Class.forName("com.mysql.jdbc.Driver");
复制代码

注:这里驱动的名字要和数据库的版本对应。

Mysql5版本:

Class.forName("com.mysql.jdbc.Driver");
复制代码

Mysql8版本:

Class.forName("com.mysql.cj.jdbc.Driver");
复制代码
  1. 创建数据库的连接
 // 2. 获得数据库连接
String url = "jdbc:mysql://localhost:3306/course_price";
String user = "root";
String password = "12345678";
Connection conn = DriverManager.getConnection(url, user, password);
复制代码

创建数据库的连接需要三个参数:

url,user,password
复制代码

要想连接数据库,第一需要知道数据库是什么类型的数据库,第二需要知道连接的数据库名称吧。所以 url 的格式:

jdbc:数据库类型://localhost:3306/数据库名称
复制代码

有了 url,还需要知道数据库的账号密码。所以有了这三个参数,就能通过 java 程序连接数据库了。

  1. 测试连接
   public static void main(String[] args) 
        Connection conn = null;
        try 
            // 1. 加载数据库驱动
            Class.forName("com.mysql.cj.jdbc.Driver");
            // 2. 获得数据库连接
            String url = "jdbc:mysql://localhost:3306/course_price";
            String user = "root";
            String password = "12345678";
            // 3. 创建数据库的连接
            conn = DriverManager.getConnection(url, user, password);
            if(null!=conn)
                System.out.println("数据库连接成功");
            else
                System.out.println("数据库连接失败");
            
         catch (Exception e) 
            e.printStackTrace();
         finally 
            //4、释放资源
            if (conn != null) 
                try 
                    conn.close();
                 catch (SQLException e) 
                    e.printStackTrace();
                
            
        
    
复制代码

测试结果:

注:Connection、PrepareStatement、ResultSet 都会占用一定的资源,它们需要全部释放/关闭。

  1. 常见错误

账号或者密码错误

Access denied for user 'root'@'localhost' (using password: YES)
复制代码

数据库名称错误

Unknown database 'course_pric'
复制代码

url 中数据库类型错误

No suitable driver found for jdbc:mysq://localhost:3306/course_price
复制代码

4. 读取配置文件信息

我们在开发的时候,一般会将连接数据库的信息写到配置文件里面。这样如果连接信息有改变,直接改配置文件里面的信息就行。

4.1 新建 jdbc.properties 文件

url=jdbc:mysql://localhost:3306/course_price
user=root
password=12345678
driver:com.mysql.jdbc.Driver
复制代码

4.2 加载配置文件信息

// 1. 加载配置文件
Properties pro=new Properties();
pro.load(new FileReader("resource/jdbc.properties"));
// 2. 获取配置文件中连接数据库的信息
String url=pro.getProperty("url");
String user=pro.getProperty("user");
String password=pro.getProperty("password");
String driver=pro.getProperty("driver");
复制代码

4.3 完整代码

public static void main(String[] args) 
      Connection conn = null;
      try 
          // 1. 加载配置文件
          Properties pro=new Properties();
          pro.load(new FileReader("resource/jdbc.properties"));
          // 2. 获取配置文件中连接数据库的信息
          String url=pro.getProperty("url");
          String user=pro.getProperty("user");
          String password=pro.getProperty("password");
          String driver=pro.getProperty("driver");
          // 3. 加载数据库的驱动
          Class.forName(driver);
          // 4. 创建数据库的连接
          conn = DriverManager.getConnection(url, user, password);
          if(null!=conn)
              System.out.println("数据库连接成功");
          else
              System.out.println("数据库连接失败");
          
       catch (Exception e) 
          e.printStackTrace();
       finally 
          //5、释放资源
          if (conn != null) 
              try 
                  conn.close();
               catch (SQLException e) 
                  e.printStackTrace();
              
          
      
  
复制代码

5. 实现增删改查

5.1 数据库操作对象

连接数据库之后我们就可以使用 java 程序操作数据库,尽情地蹂躏数据库中的数据了。

那怎样操作数据库中的数据呢?其实就是使用 java 程序执行 SQL 语句,然后返回执行结果。

我们创建的数据库连接对象 connection 有一个小弟,这小弟叫数据库操作对象,它专门用来执行 SQL 语句并返回执行结果。

这个小弟有两种类型:

Statement 和 PrepareStatement。
复制代码

Statement 是先进行 SQL 语句拼接,再进行 SQL 语句的编译,存在SQL注入问题。

PreparedStatement 是预先编译 SQL 语句(带有占位符的SQL),然后再给占位符赋值,可以防止 SQL 注入。

因为 PreparedStatement 效率高并且可以防 SQL 注入,所以这里我们使用 PreparedStatement 对象进行增删改查。

5.2 查询数据

public static void main(String[] args) 
    Connection conn = null;
    PreparedStatement ps = null;
    ResultSet rs = null;
    try 
        // 1. 加载配置文件
        Properties pro = new Properties();
        pro.load(new FileReader("resource/jdbc.properties"));
        // 2. 获取配置文件中连接数据库的信息
        String url = pro.getProperty("url");
        String user = pro.getProperty("user");
        String password = pro.getProperty("password");
        String driver = pro.getProperty("driver");
        // 3. 加载数据库的驱动
        Class.forName(driver);
        // 4. 创建数据库的连接
        conn = DriverManager.getConnection(url, user, password);
        // 5. sql 语句
        String sql = "select * from user";
        // 6. 创建执行sql的对象
        ps = conn.prepareStatement(sql);
        // 7. 执行结果
        rs = ps.executeQuery();
        while (rs.next()) 
            System.out.println("id:" + rs.getString("id"));
            System.out.println("name:" + rs.getString("name"));
            System.out.println("------");
        
     catch (Exception e) 
        e.printStackTrace();
     finally 
        //8、释放资源
        if (conn != null) 
            try 
                conn.close();
             catch (SQLException e) 
                e.printStackTrace();
            
        
        if (ps != null) 
            try 
                ps.close();
             catch (SQLException e) 
                e.printStackTrace();
            
        
        if (rs != null) 
            try 
                rs.close();
             catch (SQLException e) 
                e.printStackTrace();
            
        
    

复制代码

注:

    1. ResultSet 表示执行的结果
    1. while(resultSet.next()) 表示如果执行结果有数据,就一直遍历数据。

执行结果:

5.3 添加数据

public static void main(String[] args) 
      Connection conn = null;
      PreparedStatement ps = null;
      try 
          // 1. 加载配置文件
          Properties pro = new Properties();
          pro.load(new FileReader("resource/jdbc.properties"));
          // 2. 获取配置文件中连接数据库的信息
          String url = pro.getProperty("url");
          String user = pro.getProperty("user");
          String password = pro.getProperty("password");
          String driver = pro.getProperty("driver");
          // 3. 加载数据库的驱动
          Class.forName(driver);
          // 4. 创建数据库的连接
          conn = DriverManager.getConnection(url, user, password);
          // 5. sql 语句
          String sql = "insert into user(id,name) values(?,?)";
          // 6. 创建执行sql的对象
          ps = conn.prepareStatement(sql);
          // 7. 给 ?赋值
          ps.setInt(1, 5);
          ps.setString(2, "张无忌");
          // 8. 执行sql
          int count = ps.executeUpdate();
          if (count > 0) 
              System.out.println("添加成功");
           else 
              System.out.println("添加失败");
          
       catch (Exception e) 
          e.printStackTrace();
       finally 
          //9、释放资源
          if (conn != null) 
              try 
                  conn.close();
               catch (SQLException e) 
                  e.printStackTrace();
              
          
          if (ps != null) 
              try 
                  ps.close();
               catch (SQLException e) 
                  e.printStackTrace();
              
          
      
  
复制代码

执行结果:

5.4 修改数据

public static void main(String[] args) 
      Connection conn = null;
      PreparedStatement ps = null;
      try 
          // 1. 加载配置文件
          Properties pro = new Properties();
          pro.load(new FileReader("resource/jdbc.properties"));
          // 2. 获取配置文件中连接数据库的信息
          String url = pro.getProperty("url");
          String user = pro.getProperty("user");
          String password = pro.getProperty("password");
          String driver = pro.getProperty("driver");
          // 3. 加载数据库的驱动
          Class.forName(driver);
          // 4. 创建数据库的连接
          conn = DriverManager.getConnection(url, user, password);
          // 5. sql 语句
          String sql = "update user set name = ? where id = ?";
          // 6. 创建执行sql的对象
          ps = conn.prepareStatement(sql);
          // 7. 给 ?赋值
          ps.setString(1, "周芷若");
          ps.setInt(2, 5);
          // 8. 执行sql
          int count = ps.executeUpdate();
          if (count > 0) 
              System.out.println("修改成功");
           else 
              System.out.println("修改失败");
          
       catch (Exception e) 
          e.printStackTrace();
       finally 
          //9、释放资源
          if (conn != null) 
              try 
                  conn.close();
               catch (SQLException e) 
                  e.printStackTrace();
              
          
          if (ps != null) 
              try 
                  ps.close();
               catch (SQLException e) 
                  e.printStackTrace();
              
          
      
  
复制代码

执行结果:

5.5 删除数据

public static void main(String[] args) 
      Connection conn = null;
      PreparedStatement ps = null;
      try 
          // 1. 加载配置文件
          Properties pro = new Properties();
          pro.load(new FileReader("resource/jdbc.properties"));
          // 2. 获取配置文件中连接数据库的信息
          String url = pro.getProperty("url");
          String user = pro.getProperty("user");
          String password = pro.getProperty("password");
          String driver = pro.getProperty("driver");
          // 3. 加载数据库的驱动
          Class.forName(driver);
          // 4. 创建数据库的连接
          conn = DriverManager.getConnection(url, user, password);
          // 5. sql 语句
          String sql = "delete from user where id = ?";
          // 6. 创建执行sql的对象
          ps = conn.prepareStatement(sql);
          // 7. 给 ?赋值
          ps.setInt(1, 4);
          // 8. 执行sql
          int count = ps.executeUpdate();
          if (count > 0) 
              System.out.println("删除成功");
           else 
              System.out.println("删除失败");
          
       catch (Exception e) 
          e.printStackTrace();
       finally 
          //9、释放资源
          if (conn != null) 
              try 
                  conn.close();
               catch (SQLException e) 
                  e.printStackTrace();
              
          
          if (ps != null) 
              try 
                  ps.close();
               catch (SQLException e) 
                  e.printStackTrace();
              
          
      
  
复制代码

执行结果:

6. 工具类

从上面的例子中,我们发现每次操作都要写一堆连接数据库的信息,操作完还要释放资源,真是烦死了。那能不能简化一下呢?

能,把数据库连接封装成工具类

我们之前学 static 关键字的时候知道 static 修饰的方法可以直接用类名调用,所以特别适合工具类的使用。

JDBC 工具类:

public class JDBCUtils 
    private static String user;
    private static String password;
    private static String url;
    private static String driver;
    static 
        //  静态代码块只需要加载一次,读取资源文件
        try 
            // 1. 加载配置文件
            Properties pro = new Properties();
            pro.load(new FileReader("resource/jdbc.properties"));
            // 2. 获取配置文件中连接数据库的信息
            url = pro.getProperty("url");
            user = pro.getProperty("user");
            password = pro.getProperty("password");
            driver = pro.getProperty("driver");
            // 3. 创建数据库连接驱动
            Class.forName(driver);
         catch (FileNotFoundException e) 
            e.printStackTrace();
         catch (IOException e) 
            e.printStackTrace();
         catch (ClassNotFoundException e) 
            e.printStackTrace();
        
    

    //  4. 获取连接对象
    public static Connection getConnection() throws SQLException 
        return DriverManager.getConnection(url, user, password);
    

    //  5. 释放资源
    public static void close(PreparedStatement ps, Connection conn) 
        close(null, ps, conn);
    

    //  6. 释放资源(重载)
    public static void close(ResultSet rs, PreparedStatement ps, Connection conn) 
        if (null != rs) 
            try 
                rs.close();
             catch (SQLException e) 
                e.printStackTrace();
            
        
        if (null != ps) 
            try 
                ps.close();
             catch (SQLException e) 
                e.printStackTrace();
            
        
        if (null != conn) 
            try 
                conn.close();
             catch (SQLException e) 
                e.printStackTrace();
            
        
    

复制代码

有了 JDBC 连接的工具类,代码就可以很清爽,例如:

public static void main(String[] args) 
    Connection conn = null;
    PreparedStatement ps = null;
    try 
        // 1. 获取数据库连接对象
        conn = JDBCUtils.getConnection();
        // 2. sql 语句
        String sql = "delete from user where id = ?";
        // 3. 创建执行sql的对象
        ps = conn.prepareStatement(sql);
        // 4. 给 ?赋值
        ps.setInt(1, 4);
        // 5. 执行sql
        int count = ps.executeUpdate();
        if (count > 0) 
            System.out.println("删除成功");
         else 
            System.out.println("删除失败");
        
     catch (Exception e) 
        e.printStackTrace();
     finally 
        // 6. 释放资源
        JDBCUtils.close(ps, conn);
    

以上是关于一篇文章让你彻底明白JDBC~的主要内容,如果未能解决你的问题,请参考以下文章

操作系统关于多线程同步中的死锁问题一篇文章让你彻底搞明白死锁到底是什么情况及如何解决死锁

让你彻底明白sql注入攻击

超详细轮播图,让你彻底明白轮播图!

一篇文章让你彻底搞清楚Python中self的含义

彻底讲明白MySQL的乐观锁和悲观锁

让你彻底明白TCP三次握手,四次挥手