我发现了许多将BLOB字段赋值给对象中的一个byte[]变量的示例。如果你知道所有的BLOB字段都很小并且不介意将它们加载到内存中,那么这种方式也许是可以接受的。然而,我有很多大的BLOBs,我更喜欢把它们作为流读取。
我试图将BLOB分配给java.io.InputStream类型的属性,但这并没有起作用。错误消息是“找不到属性inputStream的类型处理程序”(其中“inputStream”是InputStream属性的名称)。
请问有谁能指点我一下正确的方向?谢谢。
这是我处理byte[]的方法,对于InputStream应该也很直接,但我认为您需要保持连接开启(我不知道是否可以通过mybatis实现)。
Add the Oracle JDBC driver to your project, you will need mybatis
dependencies too. If you are using Maven:
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc14</artifactId>
<version>10.2.0.3.0</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.2.1</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.2.3</version>
</dependency>
Add the custom BaseTypeHandler for reading byte[] from Oracle BLOB class:
@MappedTypes(byte[].class)
public class OracleBlobTypeHandler extends BaseTypeHandler<byte[]> {
@Override
public void setNonNullParameter(PreparedStatement preparedStatement, int i, byte[] bytes, JdbcType jdbcType) throws SQLException {
// see setBlobAsBytes method from https://jira.spring.io/secure/attachment/11851/OracleLobHandler.java
try {
if (bytes != null) {
//prepareLob
BLOB blob = BLOB.createTemporary(preparedStatement.getConnection(), true, BLOB.DURATION_SESSION);
//callback.populateLob
OutputStream os = blob.getBinaryOutputStream();
try {
os.write(bytes);
} catch (Exception e) {
throw new SQLException(e);
} finally {
try {
os.close();
} catch (Exception e) {
e.printStackTrace();//ignore
}
}
preparedStatement.setBlob(i, blob);
} else {
preparedStatement.setBlob(i, (Blob) null);
}
} catch (Exception e) {
throw new SQLException(e);
}
}
/** see getBlobAsBytes method from https://jira.spring.io/secure/attachment/11851/OracleLobHandler.java */
private byte[] getBlobAsBytes(BLOB blob) throws SQLException {
//initializeResourcesBeforeRead
if(!blob.isTemporary()) {
blob.open(BLOB.MODE_READONLY);
}
//read
byte[] bytes = blob.getBytes(1L, (int)blob.length());
//releaseResourcesAfterRead
if(blob.isTemporary()) {
blob.freeTemporary();
} else if(blob.isOpen()) {
blob.close();
}
return bytes;
}
@Override
public byte[] getNullableResult(ResultSet resultSet, String columnName) throws SQLException {
try {
//use a custom oracle.sql.BLOB
BLOB blob = (BLOB) resultSet.getBlob(columnName);
return getBlobAsBytes(blob);
} catch (Exception e) {
throw new SQLException(e);
}
}
@Override
public byte[] getNullableResult(ResultSet resultSet, int i) throws SQLException {
try {
//use a custom oracle.sql.BLOB
BLOB blob = (BLOB) resultSet.getBlob(i);
return getBlobAsBytes(blob);
} catch (Exception e) {
throw new SQLException(e);
}
}
@Override
public byte[] getNullableResult(CallableStatement callableStatement, int i) throws SQLException {
try {
//use a custom oracle.sql.BLOB
BLOB blob = (BLOB) callableStatement.getBlob(i);
return getBlobAsBytes(blob);
} catch (Exception e) {
throw new SQLException(e);
}
}
}
Add the type handlers package to mybatis configuration. As you can see, I am using spring-mybatis:
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="typeHandlersPackage" value="package.where.customhandler.is" />
</bean>
And then, you can read byte[] from Oracle BLOBs from Mybatis:
public class Bean {
private byte[] file;
}
interface class Dao {
@Select("select file from some_table where id=#{id}")
Bean getBean(@Param("id") String id);
}
这是对这篇优秀回答的改编:https://stackoverflow.com/a/27522590/2692914。
由于没有预定义的 InputStream 类型处理程序,你可以
1)通过扩展 BaseTypeHandler 并重写其方法来定义自己的自定义类型处理程序。我不确定,但我想你可以返回一个 InputStream 对象。 http://mybatis.github.io/mybatis-3/configuration.html#typeHandlers
2)为了处理 clobs,我个人使用 DBMS_LOB.SUBSTR(myClobColumn, size)。这比 SUBSTR() 快得多,感谢 SO。Performance of SUBSTR on CLOB
我以前遇到过这个问题。你只需要使用 "selectByExampleWithBLOBs"。
databaseStatementMapper.selectByExampleWithBLOBs(selectIn);
这是Mybatis的一个很好的特性,我已经遇到过:))