Mybatis自定义类型处理程序:在执行查询后调用FileInputStream.close()

时间:2013-06-14 04:16:43

标签: jdbc mybatis

我正在尝试使用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()。

提前致谢,

更新

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

@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;
    }
}

1 个答案:

答案 0 :(得分: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插件系统运行以上命令。