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

クエリの実行後にストリームを閉じる良い方法がわかりません。

方法 1: ファイルをバイト [] まで読み取り (注: 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: 変更できます: 1)フィールドFileByteaHandlerのリストを追加します。FileInputStream2) 開いた InputStream をそのリストに入れsetNonNullParameterます。3)closeStreams()リストからすべての InputStream を閉じて削除するメソッドを追加します。そして、マッパー メソッドを呼び出した後にこのメソッドを呼び出します。session.getConfiguration().getTypeHandlerRegistry().getMappingTypeHandler(FileByteaHandler.class).closeStreams(); または、mybatis プラグイン システムを使用して上記のコマンドを実行します。

于 2013-06-14T08:23:33.940 に答える