我有一个Oracle策略,有一点我想停止处理并向Oracle JDBC支持的Hibernate返回一个有意义的错误。
在我的政策中,当发现某个错误时,我会执行以下操作:
RAISE_APPLICATION_ERROR( -20001, 'Unauthorized' );
注意消息可以是任何内容,这只是一个例子。
这样就可以了,策略会停止执行,同时还会调用SQL调用并返回调用函数(IE Hibernate)。
在JDBC驱动程序中,虽然我的代码和错误已从异常信息中删除:
]] ServletException的根本原因。 org.hibernate.exception.GenericJDBCException:无法解压缩 ResultSet at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:54) 在 org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:126) 在 org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:112) 在 org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:91) 在org.hibernate.loader.Loader.getResultSet(Loader.java:2066) 截断。请参阅日志文件以获取完整的堆栈跟踪引起的: java.sql.SQLException:ORA-28112:无法执行策略函数
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:450)at at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:399)at at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:1059)at at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:522)at at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:257)截断。看到 完整堆栈跟踪的日志文件
深入探讨JDBC驱动程序我的-20001错误和单词" Unauthorized"不再被人看见。有没有办法向调用程序返回有意义的错误?或者,似乎是"策略编组",将所有异常并重新包装成另一个错误?
这是向调用程序返回正确失败的最佳方法,还是有更好的方法?
我不想返回任何结果,因为这意味着一切正常,我想要返回正确的错误。
更新 使用来自@ a1ex07的异常捕获器,我发现错误确实已经消失,并且所有存在一个"进程策略"错误的地方。确切的堆栈跟踪如下:
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:450)at at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:399)at at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:1059)at at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:522)at at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:257)at at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:587)at at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:225) 在 oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:53) 在 oracle.jdbc.driver.T4CPreparedStatement.executeForDescribe(T4CPreparedStatement.java:774) 在 oracle.jdbc.driver.OracleStatement.executeMaybeDescribe(OracleStatement.java:925) 在 oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1111) 在 oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:4798) 在 oracle.jdbc.driver.OraclePreparedStatement.executeQuery(OraclePreparedStatement.java:4845) 在 oracle.jdbc.driver.OraclePreparedStatementWrapper.executeQuery(OraclePreparedStatementWrapper.java:1501) 在 weblogic.jdbc.wrapper.PreparedStatement.executeQuery(PreparedStatement.java:144) 在 org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:82)
此时:
oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:450)
仍然没有我的-20001或文字的迹象。看起来驱动程序会完全删除我的异常并用它自己的平淡替换它。
更新 调用Hibernate代码如下:
public List<Tag> findBy(Long termId, String tagName) {
try {
Criteria criteria = sessionFactory.getCurrentSession().createCriteria(Tag.class)
.createAlias("tagTerms", "tagTerms");
if (tagName != null) {
criteria.add(Restrictions.eq("tagName", tagName));
}
//termId not used yet
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)
return criteria.list();
} catch (RuntimeException re) {
//SQL error is from the oracle policy and not anything else.
log.error("get failed ", re);
throw re;
}
}
标签是标准的Hibernate实体。
我目前还原为使用空结果集至少不会导致一般SQL错误。我感觉这是不可能的,因为错误只是没有传回给调用程序。
希望社区能在这里提供帮助。
答案 0 :(得分:0)
我认为问题不在于Oracle,而在于如何从Hibernate抛出的异常中检索错误代码。 exception.getCause()
或exception.getCause().getCause()
应包含RAISE_APPLICATION_ERROR
的错误代码。例如,您的异常处理程序(Java示例)可能看起来像
public void handleSQLException(Exception e) throws ECustomException
{
SQLException se = null;
if (null != e.getCause() )
{
if (e.getCause() instanceof SQLException )
{
se = (SQLException)e.getCause();
}
if (null != e.getCause().getCause() && e.getCause().getCause() instanceof SQLException )
{
se = (SQLException)e.getCause().getCause();
}
}
if (null != se)
{
int eCode = se.getErrorCode();
if (eCode >0)
{
eCode = -eCode;
}
switch (eCode)
{
case -20001 :
throw new EInvalidPolicy(se);
--handling other defined other error codes
default :
throw new RuntimeException(e);
}
}
else
{
throw new RuntimeException(e);
}
}