【发布时间】:2021-11-30 19:11:12
【问题描述】:
在我开始之前,我必须说这是一个工作项目,我不能分享所有细节。在不破坏 NDA 的情况下,我会尽可能多地包括在内。感谢您的理解。
我正在开发与 Oracle 数据库通信的 Quarkus (2.3.0) 应用程序。在其中,我执行了一个存储过程,并且应该得到一个字符串作为响应。
经过一番摆弄,我能够连接到数据库并执行存储过程。但是,响应似乎以某种使用截断的 ascii 编码(丢弃前导零)的方式编码。
606578838769828362103232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232326065788783698295838465848583627975604765788783698295838465848583621032323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323260657883876982839583698462103232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323260657883876982476210323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232604765788387698283958369846210323232323232323232323232323232323232323232323232323232323232323232323232323232323232323260476578838769828362 P>
起初,我假设每个字符代码都是两个数字长。但是,其他响应也包含字符代码大于 100 的字母。
使用2字符代码的假设,我可以解析上面的响应:
<ANSWERS>
<ANWSER_STATUS>OK</ANWSER_STATUS>
<ANSWERS_SET>
<ANSWER/>
</ANSWERS_SET>
</ANSWERS>
经过询问,数据库管理员告诉我数据库使用WE8ISO8859P15编码。
问题
如何让 Quarkus 正确理解 WE8ISO8859P15 编码,以便下面代码中的 resultString 包含响应 XML 而不是一串数字?
代码
application.properties
quarkus.datasource.db-kind=oracle
quarkus.datasource.username=${DB_USERNAME:username}
quarkus.datasource.password=${DB_PASSWORD:password}
quarkus.datasource.jdbc.url=jdbc:oracle:thin:@//${DB_HOST:dbhost}:${DB_PORT:1521}/${DB_NAME:dbname}
DatabaseCommunicator.java
@Singleton
public class DatabaseCommunicator {
@Inject
AgroalDataSource dataSource;
private static final String QUERY = "{ ? = call abc.SOME_WORDS.STORED_PROCEDURE_NAME(?) }";
public Object getDetails(String objectId) {
String resultString;
try (Connection connection = dataSource.getConnection(); CallableStatement statement = connection.prepareCall(QUERY)) {
String queryBody = "<objectId>" + objectId + "</objectId>";
statement.setString(2, queryBody);
statement.registerOutParameter(1, Types.CLOB);
statement.execute();
Clob resultClob = statement.getClob(1);
resultString = readClob(resultClob); // Value of this String is the long number string.
} catch (SQLException | IOException ex) {
throw new DatabaseException("Exception while communicating with database", ex);
}
return resultString;
}
private String readClob(Clob input) throws IOException, SQLException {
InputStream stream = input.getAsciiStream();
StringBuilder buffer = new StringBuilder();
int character = stream.read();
while (character != -1) {
buffer.append(character);
character = stream.read();
}
return buffer.toString();
}
}
pom.xml
[...]
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-agroal</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-jdbc-oracle</artifactId>
</dependency>
<dependency>
<groupId>com.oracle.database.nls</groupId>
<artifactId>orai18n</artifactId>
</dependency>
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc11</artifactId>
</dependency>
[...]
【问题讨论】:
-
应该能够从 'iso-8859-15' 解码到 'utf8'
-
我在
readClob()的第一条语句下方添加了InputStreamReader reader = new InputStreamReader(stream, Charset.forName("ISO-8859-15"));,然后用它代替stream进行阅读。但是,恐怕这仍然会产生相同的数字字符串。 -
我想知道是否可以为 iso-8858-15 使用 ascii 流?
InputStream stream = input.getAsciiStream();如果您知道如何解决此问题,请回答,因为我认为这对其他人有用。 -
还有一个
getCharacterStream();方法可以返回相同的数字字符串。我找不到任何其他返回数据的方法。