JDBC

用到的jar包

mysql-connector-java-5.1.37-bin.jar

放到和src同级的libs里面,右键Add as Library

JDBC程序编写步骤

  1. 注册驱动——加载Driver类

    Driver driver = new Driver();
    
  2. 获取连接——得到Connection

    1)jdbc:mysql://

    规定好表示协议,通过jdbc的方式连接mysql

    2)localhost 主机,可以是ip地址

    3)3306 表示mysql监听的端口

    4)mysql的连接本质就是socket连接

    String url = "jdbc:mysql://localhost:3306/数据库名"
        
    //将用户名和密码放入到Properties对象
    Properties properties = new Properties();
    
    //user和password是规定好的,后面的值根据实际情况填写
    properties.setProperty("user","root");
    properties.setProperty("password","hsp");
    
    //网络连接
    Connection connect = driver.connect(url,properties);
    
  3. 执行增删改查——发送SQL给mysql执行

    String sql = "sql语句...";
    
    //statement 用于执行静态SQL语句并返回其生成的结果的对象
    Statement statement = connect.createStatement();
    
    //如果是dml语句,返回影响行数
    int rows = statement.executeUpdate(sql);
    
  4. 释放资源——关闭相关连接

    statement.close();
    connect.close();
    

获取数据库连接的五种方式

方式一

会直接使用com.mysql.jdbc.Driver()

属于静态加载,灵活性差,依赖强

//获取Driver实现类对象
Driver driver = new com.mysql.jdbc.Driver();

String url = "jdbc:mysql://localhost:3306/数据库名";

Properties info = new Properties();
info.setProperty("user","root");
info.setProperty("password","hsp");

Connection conn = driver.connect(url,info);
System.out.println(conn);

方式二

使用反射加载Driver类,动态加载,更加灵活,减少依赖性

Class clazz = Class.forName("com.mysql.jdbc.Driver");
Driver driver = (Driver)clazz.newInstance();

String url = "jdbc:mysql://localhost:3306/数据库";

Properties info = new Properties();
info.setProperty("user","root");
info.setProperty("password","abc123");

Connection conn = driver.connect(url,info);
System.out.println(conn);

方式三

使用DriverManager替代Driver进行统一管理

Class<?> class = Class.forName("com.mysql.jdbc.Driver");
Driver driver = (Driver)class.newInstance();

String url = "jdbc:mysql://localhost:3306/数据库";
String user = "root";
String password = "hsp";

//注册Driver驱动
DriverManager.registerDriver(driver);

Connection connection = DriverManager.getConnection(url,user,password);

方式四

使用Class.forName自动完成注册驱动

源码:

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

静态代码块,在类加载时,会执行一次

因此注册driver的工作已经完成

Class.forName("com.mysql.jdbc.Driver");

String url = "jdbc:mysql://localhost:3306/数据库名";
String user = "root";
String password = "hsp";

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

※ 注:

  1. mysql驱动5.1.6可以无需

    Class.forName("com.mysql.jdbc.Driver");
    
  2. 从jdk1.5以后使用了jdbc4,不再需要显示调用class.forName()注册驱动而是自动调用驱动jar包下的META-INF\services\java.sql.Driver文本中的类名称去注册

  3. 建议还是写上

方式五

使用配置文件,连接数据库更灵活

mysql.properties

jdbc.properties
user=root
password=root
url=jdbc:mysql://localhost:3306/数据库名
driver=com.mysql.jdbc.Driver

jdbc.java

Properties properties = new Properties();
properties.load(new FileInputStream("src\\mysql.properties"));

String user = properties.getProperty("user");
String password = properties.getProperty("password");
String driver = properties.getProperty("driver");
String url = properties.getProperty("url");

Class.forName(driver);

Connection connection = DriverManager.getConnection(url,user,password);

ResultSet

表示数据库结果集的数据表,通常通过执行查询数据库的语句生成。

ResultSet对象保持一个光标指向其当前的数据行。最初,光标位于第一行之前。next方法将光标移动到下一行,并且由于在ResultSet对象中没有更多行时返回false,因此可以在while循环中使用循环来遍历结果集。

while (resultSet.next()){
	// 表示SQL语句成功执行
}

用完之后要加一条

resultSet.close();

Statement

  1. Statement对象,用于执行静态SQL语句并返回其生成的结果的对象

  2. 在连接建立后,需要对数据库进行访问,执行命令或是SQL语句,可以通过

    Statement (存在SQL注入)

    PreparedStatement (预处理)

    CallableStatement (存储过程)

  3. Statement对象执行SQL语句,存在SQL注入风险

  4. SQL注入是利用某些系统没有对用户输入的数据进行充分的检查,而在用户输入数据中注入非法的SQL语句段或命令,恶意攻击数据库

    用户名:1' or

    密码:or '1'= '1

  5. 要防范SQL注入,只要用PreparedStatement(从Statement扩展而来)取代Statement就可以了

PreparedStatement

  1. PreparedStatement 执行的SQL语句中的参数用问号(?)来表示,调用PreparedStatement 对象的setXxx() 方法来设置这些参数。setXxx() 方法有两个参数,第一个参数是要设置的SQL语句中的参数的索引(从1开始),第二个是设置的SQL语句中的参数的值
  2. 调用executeQuery(),返回ResultSet对象
  3. 调用executeUpdate(),执行更新,包括增、删、修改

预处理好处:

  1. 不再使用+拼接sql语句,减少语法错误
  2. 有效的解决了sql注入问题
  3. 大大减少了编译次数,效率较高

用完之后要加一条

preparedStatement.close();

JDBC API

image-20220122021740305

事务

  1. JDBC程序中当一个Connection对象创建时,默认情况下是自动提交事务:每次执行一个SQL语句时,如果执行成功,就会向数据库自动提交,而不能回滚。
  2. JDBC程序中为了让多个SQL语句作为一个整体执行,需要使用事务。
  3. 调用Connection的setAutoCommit(false) 可以取消自动提交事务。
  4. 在所有的SQL语句都成功执行后,调用Connection的commit()方法提交事务
  5. 在其中某个操作失败或出现异常时,调用Connection的rollback()方法回滚事务

批处理

  1. 当需要成批插入或者更新记录时,可以采用Java的批量更新机制,这一机制允许多条语句一次性提交给数据库批量处理。通常情况下比单独提交处理更有效率。

  2. JDBC的批量处理语句包括下列方法:

    addBatch() 添加需要批量处理的SQL语句或参数

    executeBatch() 执行批量处理语句

    clearBatch() 清空批处理包的语句

  3. JDBC连接MySQL时,如果要使用批处理功能,请在url中加参数

    ?rewriteBatchedStatements=true
    
  4. 批处理往往和PreparedStatement一起搭配使用,可以既减少编译次数,又减少运行次数,效率大大提高

image-20220122023659607

数据库连接池

image-20220122100500780

image-20220122100545426

方式一

//1.创建一个数据源对象
ComboPooledDataSourse comboPooledDataSourse = new ComboPooledDataSourse();

//2.通过配置文件mysql.properties获取相关连接的信息
Properties properties = new Properties();
properties.load(new FileInputStream("src\\mysql.properties"));

//3.读取相关的属性值
String user = properties.getProperty("user");
String password = properties.getProperty("password");
String url = properties.getProperty("url");
String driver = properties.getProperty("driver");

//4. 给数据源ComboPooledDataSourse设置相关的参数
//注意:连接管理是由ComboPooledDataSourse来管理
ComboPooledDataSourse.setDriverClass(driver);
ComboPooledDataSourse.setJdbcUrl(url);
ComboPooledDataSourse.setUser(user);
ComboPooledDataSourse.setPassword(password);

//设置初始化连接数
ComboPooledDataSourse.setInitialPoolSize(10);
//最大连接数
ComboPooledDataSourse.setMaxPoolSize(50);
Connection connection = comboPooledDataSourse.getConnection();

connection.close();

方式二

使用配置文件模板来完成

  1. 将c3p0提供的c3p0.config.xml拷贝到src目录下
  2. 该文件指定了连接数据库和连接池的相关参数
ComboPooledDataSourse comboPooledDataSourse = new ComboPooledDataSourse();
Connection connection = comboPooledDataSourse.getConnection();

德鲁伊

  1. 加入Druid jar包
  2. 加入配置文件 druid.properties,将该文件拷贝到项目的src目录
  3. 创建Properties对象,读取配置文件
Properties properties = new Properties();
properties.load(new FileInputStream("src\\druid.properties"));
  1. 创建一个指定参数的数据库连接池
DataSourse dataSourse = DruidDataSourseFactory.createDataSourse(properties);
Connection connection = dataSourse.getConnection();
Connection.close();

JDBCUtils

private static String user;
    private static String password;
    private static String url;
    private static String driver;

    static {
        Properties properties = new Properties();
        try {
            properties.load(new FileInputStream("src\\mysql.properties"));
            user = properties.getProperty("user");
            password = properties.getProperty("password");
            url = properties.getProperty("url");
            driver = properties.getProperty("driver");
        } catch (IOException e) {
            //在实际开发中,我们可以这样处理
            //1. 将编译异常转成运行异常
            //2. 这是调用者,可以选择捕获该异常,也可以选择默认处理该异常,比较方便
            throw new RuntimeException(e);
        }
    }

    //连接数据库,返回Connection
    public static Connection getConnection() throws SQLException {
        return DriverManager.getConnection(url, user, password);
    }

    public static void close(ResultSet set, Statement statement, Connection connection) throws SQLException {
        if(set != null){
            set.close();
        }
        if(statement != null){
            statement.close();
        }
        if(connection != null){
            connection.close();
        }
    }

用的时候

image-20220122113415896

JDBCUtilsByDruid

private static DataSourse ds;

    static {
        Properties properties = new Properties();
        try {
            properties.load(new FileInputStream("src\\druid.properties"));
            ds = DruidDataSourseFactory.createDataSourse(properties);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static Connection getConnection() {
        return ds.getConnection();
    }

    //关闭连接,在数据库连接池技术中,close()不是真的断掉连接
    //而是把使用的Connection对象放回连接池
    public static void close(ResultSet resultSet, Statement statement, Connection connection) throws SQLException {
        if(resultSet != null){
            resultSet.close();
        }
        if(statement != null){
            statement.close();
        }
        if(connection != null){
            connection.close();
        }
    }

用的时候

image-20220122110806246