java - 无法使用 JPA 将 null 持久化到 oracle BLOB

标签 java jpa oracle11g blob openjpa

我正在尝试使用 JPA (EclipseLink 2.3.x) 将图像 Byte[] 和调度程序 TimerHandle 持久保存到 oracle 11g 数据库

当属性的值不为 null 时,JPA 能够将 Byte[]/TimerHandle 持久保存到数据库,但是当这些属性为 null 时,它会给出此异常。

Caused by: java.lang.ClassCastException: oracle.sql.BLOB incompatible with oracle.sql.BLOB
    at oracle.jdbc.driver.OraclePreparedStatement.setBlob(OraclePreparedStatement.java:6663)
    at oracle.jdbc.driver.OraclePreparedStatementWrapper.setBlob(OraclePreparedStatementWrapper.java:128)
    at org.apache.openjpa.lib.jdbc.DelegatingPreparedStatement.setBlob(DelegatingPreparedStatement.java:387)
    at org.apache.openjpa.lib.jdbc.LoggingConnectionDecorator$LoggingConnection$LoggingPreparedStatement.setBlob(LoggingConnectionDecorator.java:1499)
    at org.apache.openjpa.lib.jdbc.DelegatingPreparedStatement.setBlob(DelegatingPreparedStatement.java:387)
    at org.apache.openjpa.jdbc.sql.OracleDictionary.setNull(OracleDictionary.java:633)
    at org.apache.openjpa.jdbc.sql.DBDictionary.setTyped(DBDictionary.java:1285)
    at org.apache.openjpa.jdbc.sql.RowImpl.flush(RowImpl.java:896)
    at org.apache.openjpa.jdbc.sql.RowImpl.flush(RowImpl.java:856)
    at org.apache.openjpa.jdbc.kernel.PreparedStatementManagerImpl.flushAndUpdate(PreparedStatementManagerImpl.java:117)
    at org.apache.openjpa.jdbc.kernel.BatchingPreparedStatementManagerImpl.batchOrExecuteRow(BatchingPreparedStatementManagerImpl.java:99)
    at org.apache.openjpa.jdbc.kernel.BatchingPreparedStatementManagerImpl.flushAndUpdate(BatchingPreparedStatementManagerImpl.java:83)
    at com.ibm.ws.persistence.jdbc.kernel.PreparedStatementManagerImpl.flushAndUpdate(PreparedStatementManagerImpl.java:63)
    at org.apache.openjpa.jdbc.kernel.PreparedStatementManagerImpl.flushInternal(PreparedStatementManagerImpl.java:100)
    at org.apache.openjpa.jdbc.kernel.PreparedStatementManagerImpl.flush(PreparedStatementManagerImpl.java:88)
    at org.apache.openjpa.jdbc.kernel.ConstraintUpdateManager.flush(ConstraintUpdateManager.java:550)
    at org.apache.openjpa.jdbc.kernel.ConstraintUpdateManager.flush(ConstraintUpdateManager.java:106)
    at org.apache.openjpa.jdbc.kernel.BatchingConstraintUpdateManager.flush(BatchingConstraintUpdateManager.java:59)
    at org.apache.openjpa.jdbc.kernel.AbstractUpdateManager.flush(AbstractUpdateManager.java:105)
    at org.apache.openjpa.jdbc.kernel.AbstractUpdateManager.flush(AbstractUpdateManager.java:78)
    at org.apache.openjpa.jdbc.kernel.JDBCStoreManager.flush(JDBCStoreManager.java:737)
    at org.apache.openjpa.kernel.DelegatingStoreManager.flush(DelegatingStoreManager.java:131)
    at org.apache.openjpa.kernel.BrokerImpl.flush(BrokerImpl.java:2178)
    at org.apache.openjpa.kernel.BrokerImpl.flushSafe(BrokerImpl.java:2076)
    at org.apache.openjpa.kernel.BrokerImpl.flush(BrokerImpl.java:1847)
    ... 70 more

我该如何解决这个问题,以便 null 可以作为数据库中的 (null) 持久保存到数据库中?

最佳答案

我找到了部分解决方案... 遇到此问题时,请使用普通的 oracle.sql.BLOB 而不是映射到 BLOB 的任何其他类。

@Entity
public class FileStorage implements Serializable {
    @Id
    private Long fileId;
    @Lob
    //private byte[] fileData; replaced this line with the line below.
    private oracle.sql.BLOB fileData;
    //Getter and setter
}

public class WorkingClass{
    private EntityManager em;
    public foo(){
        FileStorage f = new FileStorage();
        f.setFileData(BLOB.getEmptyBLOB());
        //f.getFileData().setBytes(someByteArrayData);
        em.persist(f);
    }
}

public class ErrorClass{
    private EntityManager em;
    public foo(){
        FileStorage f = new FileStorage();
        f.setFileData();
        //fail when the line below is commented
        //f.setFileData(someByteArrayData);
        em.persist(f);
    }
}

但是现在问题困扰着TimerHandle。使用 ObjectOutputStream/ObjectInputStream 手动序列化和反序列化后,计时器似乎没有正确序列化,导致 NoSuchObjectLocalException 当我调用 ((TimerHandle ) o).getTimer() 即使我确认计时器仍在运行(调用不断输出消息的 @Timeout 方法)。

关于java - 无法使用 JPA 将 null 持久化到 oracle BLOB,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18521400/

相关文章:

java - 迁移前的 Flyway 回调

oracle11g - 甲骨文 : Create unique index but ignore NULLs

java - 在 DAO 实现类中实现默认的 JPA findAll 方法

sql - Oracle错误 "inconsistent datatypes: expected CHAR got LONG"

oracle - 如何在oracle中的同一数据库上创建完整模式的副本

java - CompletableFuture 强制重用线程

java - 在应用程序启动之前配置@MockBean 组件

java - 如何从 Java 中没有扩展名的文件中读取?

java - 在持久化、Hibernate、Spring 数据之前获取生成的实体 Id

hibernate - Hibernate使用flushMode = AUTO查询要慢得多,直到调用clear()为止