我正在尝试使用mybatis从Oracle数据库中检索BLOB列的内容。有一个表'Demo',其中包含BLOB类型的列'binfile'。我想选择BLOB列并将其显示为字节数组/原始二进制数据。我正在使用Oracle瘦JDBC驱动程序。
mybatis映射器中的查询如下所示:
<mapper namespace="Oracle" >
...
<select id="SelectBinary" resultType="hashmap">
SELECT binfile from mpdemo.Demo
</select>
</mapper>
如果我这样做,我得到的结果如下:
BINFILE: "oracle.sql.BLOB@5d67eb18"
如果我这样做:
<select id="SelectBinaryDup" resultType="hashmap">
SELECT utl_raw.cast_to_varchar2(dbms_lob.substr(binfile)) from mpdemo.Demo
</select>
我显然得到一个错误,说原始变量说'PL / SQL:数字或值错误:原始变量长度太长',因为图像远远超过100 kB,因为SQL中的VARCHAR2变量只能支持2000个字节
有解决方法吗?
我想过编写一个存储过程,它逐块读取BLOB列并将输出写入文件。但是该文件将保存在数据库服务器上,我无法检索它。
答案 0 :(得分:2)
您可以直接使用BLOB,执行import oracle.sql.BLOB;
示例:
BLOB blob = (BLOB)map.get("binfile");
//one way: as array
byte[] bytes = blob.getBytes(1L, (int)blob.length());
System.out.println(new String(bytes)); //use for text data
System.out.println(Arrays.toString(bytes));
//another way: as stream
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("data.bin"));
InputStream is = blob.binaryStreamValue();
int b = -1;
while ((b = is.read()) != -1) {
bos.write(b);
}
bos.close();
答案 1 :(得分:0)
您是否尝试将字段映射到jdbcType = LONGVARBINARY?
答案 2 :(得分:0)
就我而言,我必须实施custom BaseTypeHandler to support Oracle BLOB conversion to byte[] for Mybatis。
将Oracle JDBC驱动程序添加到项目中,您也需要mybatis
个依赖项。如果您使用的是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>
添加custom BaseTypeHandler for reading byte[] from Oracle BLOB类:
@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);
}
}
}
将类型处理程序包添加到mybatis配置中。如你所见,我正在使用spring-mybatis:
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="typeHandlersPackage" value="package.where.customhandler.is" />
</bean>
然后,您可以从Mybatis 的Oracle BLOB中读取byte []:
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。