出现java.io.NotSerializableException错误。

本文探讨了在JAVA程序中如何使用Struct一次性传递多条数据给Oracle存储过程的方法,并讨论了如何利用Collection变量进行数据表的插入或更新操作。此外,还介绍了在Oracle中操作Collection类型变量的具体步骤。在单元测试(UT)过程中遇到的问题及解决方案也有涉及。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近参与了使用JAVA语言开发的项目,开发环境是MyEclipse + WebLogic。

自己也发了几个帖子介绍了一下使用到的一些技术。

如何在JAVA程序中使用Struct一次传入多条数据给Oracle的存储过程。

如何以Collection变量作为数据源来向数据表中插入数据,或者更新数据。

如何在Oracle中修改Collection类型的变量。

如何在Oracle中向Collection类型的变量中逐条插入数据。

但是在进行UT的时候下面的代码无法通过。

StructDescriptor st  =   new  StructDescriptor( " DEPARTMENT_TYPE " ,dbConn);

出现的错误是:

Caused by: java.rmi.MarshalException: error marshalling return; nested exception is: 
    java.io.NotSerializableException: oracle.jdbc.driver.T4CConnection
    at weblogic.rjvm.ResponseImpl.unmarshalReturn(ResponseImpl.java:195)

出现这样问题的原因都是有对象没有进行序列化。我们出现这个问题的现象是:进行UT时程序无法运行,但是从JSP页面进行调用就没有问题。所以分析的结果是我们写的项目架构中用于UT的部分没有继承序列化或者Struct本身没有继承序列化。

参考:

http://forums.bea.com/thread.jspa?messageID=600034901&tstart=0
http://forums.bea.com/thread.jspa?messageID=400006195
http://e-docs.bea.com/wls/docs81/jdbc/thirdparty.html#1043705
http://e-docs.bea.com/wls/docs81/jdbc/programming.html#1054307
//******************************************************************************************
To obtain a connection for a JDBC client, use a Java Naming and Directory Interface (JDNI) lookup to locate the DataSource object, as shown in the following code fragment.
Note: When using a JDBC connection in a client-side application, the exact same JDBC driver classes must be in the CLASSPATH on both the server and the client. If the driver classes do not match, you may see java.rmi.UnmarshalException exceptions.
//******************************************************************************************

### Java 中关于 Redisson 的 NotSerializableException 解决方案 `java.io.NotSerializableException` 是一种常见的序列化异常,通常发生在尝试将未实现 `Serializable` 接口的对象进行序列化时。对于 Redisson 中的 `RedissonPermitExpirableSemaphore` 类型对象引发此异常的情况,以下是可能的原因及其解决方案。 #### 原因分析 1. **Redisson 对象本身不可序列化** 如果你在分布式环境中使用 Redisson 提供的功能(如信号量),而这些功能依赖于某些内部状态或上下文数据,则可能会因为这些数据未被标记为可序列化而导致异常[^3]。 2. **嵌套对象未实现 Serializable** 即使 `RedissonPermitExpirableSemaphore` 实现了 `Serializable`,但如果其成员变量中有未实现该接口的对象实例,也会触发 `NotSerializableException` 异常[^5]。 3. **闭包捕获外部变量** 在 Spark 或其他分布式计算框架中,如果通过 lambda 表达式或其他方式传递了一个包含复杂对象图的函数到远程节点执行,那么整个对象树都需要满足序列化条件。任何部分缺失都会导致失败[^4]。 #### 解决方案 为了处理上述问题,可以采取以下措施: 1. **确认目标类是否完全支持序列化** 验证所有涉及的对象都显式声明实现了 `java.io.Serializable` 接口,并且没有任何字段违反这一原则。例如: ```java public class MyCustomClass implements Serializable { private static final long serialVersionUID = 1L; // Ensure all fields are either transient or serializable themselves. private String name; private int age; // Getters and setters omitted for brevity. @Override public String toString() { return "MyCustomClass{" + "name='" + name + '\'' + ", age=" + age + '}'; } } ``` 2. **利用 Transient 关键字忽略特定属性** 若存在无法修改源码或者确实不需要保存的状态信息,可以通过将其定义成 `transient` 来跳过它们的序列化进程[^1]: ```java public class MyClassWithTransientField implements Serializable { private static final long serialVersionUID = 1L; private String importantData; private transient Object nonSerializableObject; // Constructors, getters/setters etc... } ``` 3. **自定义 writeObject 和 readObject 方法** 当默认机制不足以解决问题时,还可以重载这两个特殊方法来自定义行为[^2]: ```java private void writeObject(java.io.ObjectOutputStream out) throws IOException { out.defaultWriteObject(); // Custom serialization logic here if necessary. } private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); // Re-initialize any transient field after deserialization. } ``` 4. **替换为更轻便的数据结构 (推荐用于分布式场景)** 考虑到性能因素以及兼容性需求,在实际开发过程中建议尽可能采用简单的 POJOs 并配合 JSON 序列器比如 Jackson/Gson 进行转换而不是直接操作二进制流。 5. **针对 Redisson 特定情况调整配置** - 使用 RLock/RCountDownLatch 等替代品代替原生锁; - 将业务逻辑拆分至无状态的服务端组件调用而非随任务广播给各个工作节点; --- ### 示例代码片段 假设我们正在调试一个基于 Redisson 的限流模块遇到此类错误,下面是修正后的版本之一: ```java import org.redisson.api.RSemaphoreAsync; import org.redisson.api.RedissonClient; import java.io.Serializable; public class RateLimitedService implements Serializable { private static final long serialVersionUID = 1L; private transient RSemaphoreAsync semaphore; public RateLimitedService(RedissonClient redisson){ this.semaphore = redisson.get SemaphoreAsync("rate_limit_key"); } public boolean tryAcquire(){ return CompletableFuture.supplyAsync(() -> semaphore.tryAcquire()).join(); } } ``` 在此例子中我们将原始类型的引用设为了瞬态 (`transient`) ,从而避免不必要的序列化开销同时也规避掉了潜在的风险点。 ---
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值