有效处理java.sql.SQLException:ORA-04068

时间:2015-12-17 16:18:03

标签: java oracle plsql

我得到了以下例外:

Caused by: java.sql.SQLException: ORA-04068: existing state of packages has been discarded
ORA-04061: existing state of package body "PACKAGE_A" has been invalidated
ORA-04065: not executed, altered or dropped package body "PACKAGE_A"
ORA-06508: PL/SQL: could not find program unit being called: "PACKAGE_A"

版本:

Java 1.7.x and oracle 11.4.x

根本原因: PACKAGE_A具有全局变量声明的状态。包装规格(不是主体)已经重新编译并且已经重新编译。内部调用PACKAGE_B的java服务调用PACKAGE_A抛出此异常,直到我们重新启动这些服务。

我知道状态不应该出现包规范。但我正在寻找可行的解决方案 ,而无需在JAVA中进行代码更改

我找到了关于这个主题的其他SE问题的两个解决方案。

选项1:

Defining packages with `PRAGMA SERIALLY_REUSABLE` 

选项2:

exec DBMS_SESSION.RESET_PACKAGE
exec DBMS_SESSION.MODIFY_PACKAGE_STATE( DBMS_SESSION.REINITIALIZE) 

选项3:

从包中删除全局变量。

如果我没有永远使用选项3,那么使用选项1&的缺点是什么?选项2?

这些选项会导致数据库的性能开销吗? 选项3是否提供了最佳解决方案?

1 个答案:

答案 0 :(得分:1)

这是Oracle的标准行为,因为它将包的编译实例保存在每个会话的会话内存中。由于所有包状态在会话中都是有效的(即包变量在两个数据库会话中可以具有不同的值),因此包变量值也会绑定到会话。

现在,如果您更改了包,Oracle必须为所有会话重新加载包。到现在为止还挺好。但是,当您更改代码时,包变量会丢失。这就像在代码更改后停止并重新启动应用程序 - 变量会丢失。

这个优雅的例外表明现在包变量正在丢失。

根据您使用包变量的方式,这可能会导致您的应用程序出现问题 - 因此例外。

但在现实生活中,使用所有包变量以便按需初始化(例如使用plsql表进行oldschool缓存),并且没有人应该保留持久数据(例如,购物车的内容)包变量中的网店应用程序。实际上,包变量 - 虽然看起来是持久的 - 应被视为瞬态,并且在调用之间具有乐观的持久性

如果您可以遵守此规则,那么您可以非常轻松地处理此异常:

  • 不要改变包裹代码:)好吧,开玩笑
  • 在获得此异常时,只需重新运行失败的pl / sql调用。

即:

  • 调用addCustomer(?,?,?)
  • 你有一个java.sql.SQLException:ORA-04068
  • 现在再次调用相同的addCustomer(?,?,?)