简体   繁体   中英

Reading a `BLOB` via JDBC takes too long

When I read an image from database, it appears in the JLabel immediately, but it takes too much time to complete streaming the BLOB from the DB.

public byte[] selectImage(int Id) throws SQLException {
    ResultSet res=null;
    int c=0;

    try {
        Class.forName(driver);
        con = DriverManager.getConnection(connectionURL);
    } catch (SQLException ex) {
        Logger.getLogger(Connect.class.getName()).log(Level.SEVERE, null, ex);
    } catch (ClassNotFoundException ex) {
        Logger.getLogger(Connect.class.getName()).log(Level.SEVERE, null, ex);
    }

    System.out.println(con.getAutoCommit());

    statement = con.createStatement() ;
    res = statement.executeQuery("SELECT PHOTO FROM CUSTOMER where ID="+Id) ;

    while(res.next() && (res!=null)) {
        Blob bodyOut = res.getBlob("PHOTO");
        int length = (int) bodyOut.length();
        System.out.println("   Body Size = "+length);
        imageBytes = bodyOut.getBytes(1, length);
        bodyOut.free(); 
    }

    return imageBytes;
}

Consider storing the image outside of the database. Only store enough info in the DB to let you find the file (either on the filesystem, or from an HTTP server, or however you're storing it now that it's not in the DB). Binary data isn't really the use case that an RDBMS is optimized to handle.

Also, your code has some serious problems:

  1. The biggest problem is probably the security flaw you get by failing to use bind variables, aka a PreparedStatement in Java. This is SQL injection 101.

  2. you're using raw JDBC. Raw JDBC is tedious and easy to mess up. For instance, you aren't closing your ResultSet or your Connection , not to mention the statement variable, which should definitely be local. And when you do start closing them, you should do it in a finally block to make sure it always happens, even if there is an error.

  3. If you happen to get more than one result from your query—I'm guessing you shouldn't, but just in case—you will only know if you happen to look at STDOUT , and you'll just get the last image. Your while loop is probably better expressed as an if to indicate that you only expect and/or care about the first result. If you care if there is more than one results, you should probably use an if instead of a while, then add a subsequent if (rs.next()) throw new MyAppropriatelyNamedException; so you know that there is something unexpected going on.

  4. The null check for res is worthless. By the time you execute the check, the rs.next() statement will have already thrown a NullPointerException . You should probably just delete the check.

  5. Why are you using the logging framework, only to turn around and use System.out.println to output some debugging info?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM