代码:

package com.weiyu;

import com.weiyu.utils.BMP2PNGUtils;

import java.io.InputStream;
import java.sql.*;

/**
 * 连接数据库,BMP 转换为 PNG 测试
 */
public class BMP2PNG4DatabaseTest {
    public static void main(String[] args) {
        String connectionUrl = "jdbc:sqlserver://127.0.0.1:1433;databaseName=JMCDC";
        String username = "sa";
        String password = "Sinmia123";
        try (
                // 连接数据库 SQL Server 2008 R2
                Connection connection = DriverManager.getConnection(connectionUrl, username, password);
                // 创建会话(类似图形化工具中的新建查询),用于执行 sql 语句
                Statement statement = connection.createStatement();
                // 结果集
                ResultSet resultSet = statement.executeQuery("""
                    select emp_ID as userName, emp_SignPicture as signPicture from Employee
                    inner join ACCOUNT on acc_Account = emp_ID
                    where acc_Valid = 1 and emp_SignPicture is not null""");
        ) {
            // 遍历结果集
            while (resultSet.next()) {
                // 获取用户名(账号)
                String userName = resultSet.getString("userName");
                // 获取签名图片 Blob
                Blob signPicture = resultSet.getBlob("signPicture");

                // 将 Blob(bmp格式的)转换成 png
                if (signPicture != null) {
                    try (InputStream inputStream = signPicture.getBinaryStream()) {
                        String pngFilePath = "D:/test/png/" + userName + ".png";

                        // BMP 转 PNG,直接调用转换工具的方法
                        BMP2PNGUtils.convertBMPStreamToPNG(inputStream, pngFilePath);
                        System.out.println("已转换PNG文件: " + pngFilePath);
                    } catch (Exception e) {
                        System.err.println("转换用户 " + userName + " 的图片时出错: " + e.getMessage());
                    }
                } else {
                    System.out.println("用户 " + userName + " 没有签名图片");
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

try() 里面的内容会先执行

具体执行顺序如下:

执行顺序分析

java

try (
    Connection connection = DriverManager.getConnection(connectionUrl, username, password);  // 1. 先执行
    Statement statement = connection.createStatement();  // 2. 再执行
    ResultSet resultSet = statement.executeQuery("SQL查询");  // 3. 最后执行
) {
    // 4. 然后才执行try块内的代码
    while (resultSet.next()) {
        // 处理结果集
    }
} catch (Exception e) {
    e.printStackTrace();
}

具体执行流程:

  1. 按顺序执行 try() 中的初始化语句

    • DriverManager.getConnection() - 建立数据库连接

    • connection.createStatement() - 创建Statement对象

    • statement.executeQuery() - 执行SQL查询,返回ResultSet

  2. 然后执行 try 块内的代码

    • 遍历ResultSet

    • 处理每条记录

  3. 最后自动关闭资源(try-with-resources特性):

    • 关闭ResultSet

    • 关闭Statement

    • 关闭Connection

    • 相反顺序关闭

关键点:

  • try()中的代码确实先于try块内的代码执行

  • 这是Java 7引入的try-with-resources语法,用于自动资源管理

  • 所有在try()中声明的资源都会在try块结束后自动调用close()方法

这种写法比传统的try-catch-finally更加简洁安全,避免了资源泄漏的问题。

这是 Java 的 try-with-resources 语法特性:

java

try (资源声明1; 资源声明2; ...) {
    // 业务逻辑代码
}

资源关闭顺序:

当 try 块执行完毕后,资源会自动按照声明的相反顺序关闭

  1. 先关闭 ResultSet resultSet

  2. 然后关闭 Statement statement

  3. 最后关闭 Connection connection

与传统写法的对比:

java

// 传统写法(需要手动关闭)
Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;
try {
    connection = DriverManager.getConnection(...);
    statement = connection.createStatement();
    resultSet = statement.executeQuery(...);
    // 业务逻辑
} finally {
    // 手动关闭资源
    if (resultSet != null) resultSet.close();
    if (statement != null) statement.close();
    if (connection != null) connection.close();
}

// try-with-resources(自动关闭)
try (Connection connection = DriverManager.getConnection(...);
     Statement statement = connection.createStatement();
     ResultSet resultSet = statement.executeQuery(...)) {
    // 业务逻辑
}

所以您的代码中,数据库连接和查询确实是在进入 while 循环之前就已经完成了。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐