1

我正在尝试使用 FileInputStream 为 File 实现 MyBatis 自定义类型处理程序。

这是我的设置代码:

@MappedJdbcTypes(JdbcType.LONGVARBINARY)
public class FileByteaHandler extends BaseTypeHandler<File> {
  @Override
  public void setNonNullParameter(PreparedStatement ps, int i, File file, JdbcType jdbcType) throws SQLException{
    try {

        FileInputStream  fis = new FileInputStream(file);
        ps.setBinaryStream(1, fis, (int) file.length());           

    } catch(FileNotFoundException ex) {
        Logger.getLogger(FileByteaHandler.class.getName()).log(Level.SEVERE, null, ex);
    }
  }

}

我的问题是:

我不能在这个方法结束时关闭这个 FileInputStream,否则 MyBatis 将无法从中读取数据。事实上,我不知道在哪里可以关闭 FileInputStream。有没有办法在 MyBatis 中执行查询后调用 close()。

提前致谢,

更新

感谢贾兰迪诺的帮助。这是我的这种类型处理程序的代码。希望它可以帮助某人:

@MappedJdbcTypes(JdbcType.LONGVARBINARY)
public class FileByteaHandler extends BaseTypeHandler<File> {

@Override
public void setNonNullParameter(PreparedStatement ps, int i, File file, JdbcType jdbcType) throws SQLException {
    try {
        AutoCloseFileInputStream fis = new AutoCloseFileInputStream(file);
        ps.setBinaryStream(1, fis, (int) file.length());

    } catch(FileNotFoundException ex) {
        Logger.getLogger(FileByteaHandler.class.getName()).log(Level.SEVERE, null, ex);
    }
}

@Override
public File getNullableResult(ResultSet rs, String columnName) throws SQLException {
    File file = null;

    try(InputStream input = rs.getBinaryStream(columnName)) {
        file = getResult(rs, input);
    } catch(IOException e) {
        System.out.println(e.getMessage());
    }
    return file;
}

public File creaetFile() {
    File file = new File("e:/target-file");    //your temp file path
    return file;
}

private File getResult(ResultSet rs, InputStream input) throws SQLException {
    File file = creaetFile();

    try(OutputStream output = new FileOutputStream(file)) {
        int bufSize = 0x8000000;
        byte buf[] = new byte[bufSize];
        int s = 0;
        int tl = 0;

        while( (s = input.read(buf, 0, bufSize)) > 0 ) {
            output.write(buf, 0, s);
            tl += s;
        }
        output.flush();
    } catch(IOException e) {
        System.out.println(e.getMessage());
    }
    return file;
}

@Override
public File getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
    File file = null;

    try(InputStream input = rs.getBinaryStream(columnIndex)) {
        file = getResult(rs, input);
    } catch(IOException e) {
        System.out.println(e.getMessage());
    }

    return file;
}

@Override
public File getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
    throw new SQLException("getNullableResult(CallableStatement cs, int columnIndex) is called");
}

private class AutoCloseFileInputStream extends FileInputStream {

    public AutoCloseFileInputStream(File file) throws FileNotFoundException {
        super(file);
    }

    @Override
    public int read() throws IOException {
        int c = super.read();
        if(available() <= 0) {
            close();
        }
        return c;
    }

    public int read(byte[] b) throws IOException {
        int c = super.read(b);
        if(available() <= 0) {
            close();
        }
        return c;
    }

    public int read(byte[] b, int off, int len) throws IOException {
        int c = super.read(b, off, len);
        if(available() <= 0) {
            close();
        }
        return c;
    }
}
}


    public AutoCloseFileInputStream(File file) throws FileNotFoundException {
        super(file);
    }

    @Override
    public int read() throws IOException {
        int c = super.read();
        if( c == -1 ) {
            close();
        }
        return c;
    }

    public int read(byte[] b) throws IOException {
        int c = super.read(b);
        if( c == -1 ) {
            close();
        }
        return c;
    }

    public int read(byte[] b, int off, int len) throws IOException {
        int c = super.read(b, off, len);
        if(available() <= 0) {
            close();
        }
        return c;
    }
}
4

1 回答 1

1

我不知道在查询执行后关闭流的好方法。

方法一:将文件读入byte[](注意:在jdk 7中可以使用Files.readAllBytes(Paths.get(file.getPath()));)并使用: ps.setBytes(i, bytes);

2:或者创建自己的类继承FileInputStream和覆盖public native int read() throws IOException;方法,当到达文件末尾时,关闭流:

@Override
public int read() throws IOException {
    int c = super.read();
    if(c == -1) {
        super.close();
    }
    return c;
}

也许您也应该覆盖public int read(byte[] b) throws IOException它,这取决于 jdbc 实现。

3:您可以更改您的FileByteaHandler:1)添加FileInputStream字段列表;2) 将打开的 InputStream 放入该列表中setNonNullParameter;3)添加closeStreams()方法,您可以在其中关闭并从列表中删除所有 InputStream。并在调用 mapper 方法后调用此方法:session.getConfiguration().getTypeHandlerRegistry().getMappingTypeHandler(FileByteaHandler.class).closeStreams(); 或使用 mybatis 插件系统运行上述命令。

于 2013-06-14T08:23:33.940 回答