JDBC基础-各类作用+工具类抽取+事务管理

x33g5p2x  于2021-11-22 转载在 其他  
字(12.4k)|赞(0)|评价(0)|浏览(314)

Java数据库连接,(Java Database Connectivity,简称JDBC)是Java语言中用来规范客户端程序如何来访问数据库的应用程序接口,提供了诸如查询和更新数据库中数据的方法。JDBC也是Sun Microsystems的商标。我们通常说的JDBC是面向关系型数据库的。

一.最简单的jdbc-demo及基本步骤

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;

public class JdbcDemo {
    public static void main(String[] args) throws Exception {
        //注册驱动
        Class.forName("com.mysql.jdbc.Driver");
        //获取数据连接对象
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/root?serverTimezone=UTC","root","123456");
        //定义sql语句
        String sql = "update user set password = '123' where id =1";
        //获取sql对象Statement
        Statement stmt = conn.createStatement();
        //执行sql
        stmt.executeUpdate(sql);
        //释放资源
        stmt.close();
        conn.close();
    }
}

二.JDBC各类作用及应用

1.DriverManager:驱动管理对象

DriverManage的主要作用是注册驱动,即告诉程序使用哪一个数据库驱动jar
从Driver的源码文件中可以看出其在静态代码块执行驱动注册

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package com.mysql.cj.jdbc;

import java.sql.DriverManager;
import java.sql.SQLException;

public class Driver extends NonRegisteringDriver implements java.sql.Driver {
    public Driver() throws SQLException {
    }

    static {
        try {
            DriverManager.registerDriver(new Driver());
        } catch (SQLException var1) {
            throw new RuntimeException("Can't register driver!");
        }
    }
}

DriverManage的第二个作用是获取数据库连接
通过getConnection(String url,String user, String password)方法获取数据库连接
参数包括:
url:指定连接的路径
user:用户名
password:密码

  • url语法:jdbc:mysql://ip地址(域名):端口号/数据库名称
  • 例如jdbc:mysql://localhost:3306/root(root是我的一个数据库名称)
  • 由于我的时区有多个,所以传了一个参数(?serverTimezone=UTC)指定时区
  • 如果连接的是本地mysql服务器,并且mysql服务器默认端口是3306,则url可以简写为jdbc:mysql:///root
@CallerSensitive
    public static Connection getConnection(String url,
        String user, String password) throws SQLException {
        java.util.Properties info = new java.util.Properties();

        if (user != null) {
            info.put("user", user);
        }
        if (password != null) {
            info.put("password", password);
        }

        return (getConnection(url, info, Reflection.getCallerClass()));
    }
2.Connection:数据库连接对象

Connection的主要作用获取执行sql的对象并管理事务

  • 开启事务:setAutoCommit(boolean autoCommit):调用该方法设置参数为flase,即开启事务
  • 提交事务:commit()
  • 回滚事务:rollback()
3.Statement:执行sql的对象

可以形象的理解Connection的作用是建桥,建立Java和数据库的连接,Statement的作用是执行事务,形象理解为派个人过桥,提着篮子,去拿数据
实现代码:Statement stmt = conn.createStatement();

  • boolean execute(String sql):可以执行任意的sql
  • int executeUpdate:可以通过判断影响的行数判断sql语句是否执行成功
    下面是一个简单的jdbc-demo,相比于上一个demo改进的地方在于定义了一个count来判断sql语句是否执行成功
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;

public class JdbcDemo {
    public static void main(String[] args){
        Statement stmt = null;
        Connection conn = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            String sql = "insert into user (username, password) values ('admin','789')";
            conn = DriverManager.getConnection("jdbc:mysql:///root?serverTimezone=UTC","root","123456");
            stmt = conn.createStatement();
            int count = stmt.executeUpdate(sql);
            if(count>0){
                System.out.println("添加成功");
            }else {
                System.out.println("添加失败");
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException exception) {
            exception.printStackTrace();
        }finally {
            if(stmt!=null){
                try {
                    stmt.close();
                } catch (SQLException exception) {
                    exception.printStackTrace();
                }
            }
            if(conn!=null){
                try {
                    conn.close();
                } catch (SQLException exception) {
                    exception.printStackTrace();
                }
            }
        }
    }
}
4.ResultSet:封装结果集对象,封装查询结果
  • next():游标向下移动一行
  • getXxx(参数):获取数据
  • Xxx代表数据类型
  • 参数:
  • 1.int代表列的编号,从1开始,如:getString(1);
  • 2.String代表列名称,如getDouble("")
    下面是一个简单的jdbc-demo,相比于上一个demo,这个demo增加了一个ResultSet作为结果集接收sql执行结果
import javax.xml.transform.Result;
import java.sql.*;

public class JdbcDemo {
    public static void main(String[] args){
        Statement stmt = null;
        Connection conn = null;
        ResultSet rs = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            String sql = "select * from user ";
            conn = DriverManager.getConnection("jdbc:mysql:///root?serverTimezone=UTC","root","123456");
            stmt = conn.createStatement();
            rs = stmt.executeQuery(sql);
            rs.next();
            int id = rs.getInt(1);
            String username = rs.getString("username");
            String password = rs.getString("password");
            System.out.println(id+"---"+username+"---"+password);

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException exception) {
            exception.printStackTrace();
        }finally {
            if(rs!=null){
                try {
                    rs.close();
                } catch (SQLException exception) {
                    exception.printStackTrace();
                }
            }
            if(stmt!=null){
                try {
                    stmt.close();
                } catch (SQLException exception) {
                    exception.printStackTrace();
                }
            }
            if(conn!=null){
                try {
                    conn.close();
                } catch (SQLException exception) {
                    exception.printStackTrace();
                }
            }
        }
    }
}

下面是一个简单的jdbc-demo,相比于上一个demo,这个demo增加了 while (rs.next())使得每条查询记录都能打印出来(上一个demo只能打印一条查询记录)

import javax.xml.transform.Result;
import java.sql.*;

public class JdbcDemo {
    public static void main(String[] args){
        Statement stmt = null;
        Connection conn = null;
        ResultSet rs = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            String sql = "select * from user ";
            conn = DriverManager.getConnection("jdbc:mysql:///root?serverTimezone=UTC","root","123456");
            stmt = conn.createStatement();
            rs = stmt.executeQuery(sql);
            while (rs.next()){
                int id = rs.getInt(1);
                String username = rs.getString("username");
                String password = rs.getString("password");
                System.out.println(id+"---"+username+"---"+password);
            }

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException exception) {
            exception.printStackTrace();
        }finally {
            if(rs!=null){
                try {
                    rs.close();
                } catch (SQLException exception) {
                    exception.printStackTrace();
                }
            }
            if(stmt!=null){
                try {
                    stmt.close();
                } catch (SQLException exception) {
                    exception.printStackTrace();
                }
            }
            if(conn!=null){
                try {
                    conn.close();
                } catch (SQLException exception) {
                    exception.printStackTrace();
                }
            }
        }
    }
}

下面是一个简单的jdbc-demo,相比于上一个demo,这个demo增加了 user类,对于user表,将查询的数据封装为对象装载进入集合

public class User {
    private int id;
    private String username;
    private String password;

    public int getId() {
        return id;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}
import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public class JdbcDemo2 {
    public static void main(String[] args) {
        List<User> list = new JdbcDemo2().findAll();
        System.out.println(list);
    }

    public List<User> findAll(){
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;
        List<User> list = new ArrayList<User>();
        try {
            Class.forName("com.mysql.jdbc.Driver");
            conn = DriverManager.getConnection("jdbc:mysql:///root?serverTimezone=UTC","root","123456");
            String sql = "select * from user";
            stmt = conn.createStatement();
            rs = stmt.executeQuery(sql);
            while (rs.next()){
                int id = rs.getInt("id");
                String username = rs.getString("username");
                String password = rs.getString("password");
                User user = new User();
                user.setId(id);
                user.setUsername(username);
                user.setPassword(password);
                list.add(user);
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException exception) {
            exception.printStackTrace();
        }finally {
            if(rs!=null){
                try {
                    rs.close();
                } catch (SQLException exception) {
                    exception.printStackTrace();
                }
            }
            if(stmt!=null){
                try {
                    stmt.close();
                } catch (SQLException exception) {
                    exception.printStackTrace();
                }
            }
            if(conn!=null){
                try {
                    conn.close();
                } catch (SQLException exception) {
                    exception.printStackTrace();
                }
            }
        }
        return list;

    }

}
5.PreparedStatement:预防sql注入

详细的内容可以查看我的另一篇博文sql注入问题

三.抽取JDBC工具类:JDBCUtils

以上的代码重复度过高,所以我们需要抽取方法,简化书写,首先将一些惯用的常量放在配置文件druid.properties中

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/root?serverTimezone=UTC
username=root
password=123456

下面是工具类的书写,值得关注的是类加载器ClassLoader的使用

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.net.URL;
import java.sql.*;
import java.util.Properties;

public class JDBCUtils {
    //文件的读取,只需要读取一次即可拿到这些值,使用静态代码块
    private static String url;
    private static String user;
    private static String password;
    private static String driver;

    static {
        try {
            //读取资源文件
            //创建Properties集合类
            Properties pro = new Properties();
            //类加载器ClassLoader可以获取src路径下的文件
            ClassLoader classLoader = JDBCUtils.class.getClassLoader();
            URL res = classLoader.getResource("druid.properties");
            String path = res.getPath();
            pro.load(new FileReader(path));
            url = pro.getProperty("url");
            user = pro.getProperty("username");
            password = pro.getProperty("password");
            driver = pro.getProperty("driver");
            //注册驱动
            Class.forName(driver);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException exception) {
            exception.printStackTrace();
        }

    }

    public static Connection getConnection(){
        try {
            return DriverManager.getConnection(url,user,password);
        } catch (SQLException exception) {
            exception.printStackTrace();
        }
        return null;
    }

    /** * 释放资源 * @param stmt * @param conn */
    public static void close(Statement stmt,Connection conn){
        if(stmt!=null){
            try {
                stmt.close();
            } catch (SQLException exception) {
                exception.printStackTrace();
            }
        }
        if(conn!=null){
            try {
                conn.close();
            } catch (SQLException exception) {
                exception.printStackTrace();
            }
        }
    }

    /** * 重载方法 * @param rs * @param stmt * @param conn */
    public static void close(ResultSet rs,Statement stmt, Connection conn){
        if(rs!=null){
            try {
                rs.close();
            } catch (SQLException exception) {
                exception.printStackTrace();
            }
        }
        if(stmt!=null){
            try {
                stmt.close();
            } catch (SQLException exception) {
                exception.printStackTrace();
            }
        }
        if(conn!=null){
            try {
                conn.close();
            } catch (SQLException exception) {
                exception.printStackTrace();
            }
        }
    }
}

下面是实现类,代码量精简了很多

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public class JdbcDemo2 {
    public static void main(String[] args) {
        List<User> list = new JdbcDemo2().findAll();
        System.out.println(list);
    }

    public List<User> findAll(){
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;
        List<User> list = new ArrayList<User>();
        try {
            conn = JDBCUtils.getConnection();
            String sql = "select * from user";
            stmt = conn.createStatement();
            rs = stmt.executeQuery(sql);
            while (rs.next()){
                int id = rs.getInt("id");
                String username = rs.getString("username");
                String password = rs.getString("password");
                User user = new User();
                user.setId(id);
                user.setUsername(username);
                user.setPassword(password);
                list.add(user);
            }
        } catch (SQLException exception) {
            exception.printStackTrace();
        }finally {
            JDBCUtils.close(rs,stmt,conn);
        }
        return list;

    }

}

下面是运用JDBCUtils工具类实现了登录的案例,从键盘录入用户名和密码,通过与数据库内的值进行匹配判断是否能登录

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Scanner;

public class JdbcDemo3 {
    public static void main(String[] args) {
        //键盘录入。接收用户名和密码
        Scanner scanner = new Scanner(System.in);
        String username = scanner.nextLine();
        String password = scanner.nextLine();
        //调用方法
        boolean flag = new JdbcDemo3().login(username,password);
        //判断结果,输出不同语句
        if(flag){
            System.out.println("登录成功");
        }else {
            System.out.println("登录失败");
        }
    }

    /** * 登录方法 * @param username * @param password * @return */
    public boolean login(String username,String password){
        if(username == null || password == null){
            return false;
        }
        Connection connection = null;
        Statement stmt = null;
        ResultSet rs = null;
        try {
            //连接数据库判断是否登录成功
            connection = JDBCUtils.getConnection();
            //定义sql
            String sql = "select * from user where username = '"+username+"' and password = '"+password+"'";
            //获取执行sql的对象
            stmt = connection.createStatement();
            //执行查询
            rs = stmt.executeQuery(sql);
            //判断
            return rs.next();

        } catch (SQLException exception) {
            exception.printStackTrace();
        }finally {
            JDBCUtils.close(rs,stmt,connection);
        }
        return false;
    }

}

四.JDBC事务管理

当我们在执行sql时候,如果在连续执行sql语句过程中出现异常,则会导致执行中断,即后面的sql语句无法执行,为了避免这种情况,我们使用事务管理。
下面是一个demo,在获取连接后开启事务,在sql执行后提交事务,在异常处理中添加事务回滚,如果出现异常通过回滚可以执行被中断的方法

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class JdbcDemo4 {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement pstmt1 = null;
        PreparedStatement pstmt2 = null;
        try {
            //获取连接
            conn = JDBCUtils.getConnection();
            //开启事务
            conn.setAutoCommit(false);
            //定义sql
            String sql1 = "update user set password = ? where id = ?";
            String sql2 = "update user set password = ? where id = ?";
            //获取执行sql对象
            pstmt1 = conn.prepareStatement(sql1);
            pstmt2 = conn.prepareStatement(sql2);
            //设置参数
            pstmt1.setString(1,"yhyhyh");
            pstmt1.setInt(2,1);
            pstmt2.setString(1,"henrik");
            pstmt2.setInt(2,2);
            //执行sql
            pstmt1.executeUpdate();
            pstmt2.executeUpdate();
            //提交事务
            conn.commit();
        } catch (Exception exception) {
            //事务回滚
            try {
                if(conn!=null){
                    conn.rollback();
                }
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
            exception.printStackTrace();
        }finally {
            JDBCUtils.close(pstmt1,conn);
            JDBCUtils.close(pstmt2,null);
        }
    }
}

相关文章