Hello,
We use Hibernate3 and Oracle we are having an issue getting a Blob to update correctly. This means that we have to delete the old blob row, then insert a new row with the "updated blob". Very annoying. Was wondering if anyone else has run into this?
Thanks for any info, -Danny
Here is the mapping:
<class name="vipr.dao.pseudofile.PseudoFileVo" table="VIPR_DOCUMENT_CONTENTS"> <id name="id" type="java.lang.Long"> <column name="ID" precision="22" scale="0" /> <generator class="native" /> </id> <property name="histId" type="java.lang.Long"> <column name="HISTORY_ID" precision="22" scale="0" /> </property> <property name="expirePendingFlag" type="java.lang.String"> <column name="to_be_expired" length="1" /> </property> <property name="effectiveDate" type="java.util.Date"> <column name="EFFECTIVE_DATE" length="7" /> </property> <property name="expirationDate" type="java.util.Date"> <column name="EXPIRATION_DATE" length="7" /> </property> <property name="modifiedBy" type="java.lang.Long"> <column name="MODIFIED_BY" precision="22" scale="0" not-null="true" /> </property> <property name="modifiedDate" type="java.util.Date"> <column name="MODIFIED_DATE" length="7" not-null="true" /> </property> <property name="fileSize" type="java.lang.Long"> <column name="OBJECT_SIZE" precision="22" scale="0" not-null="true" /> </property> <many-to-one name="fileTypeLuVo" class="vipr.dao.filetype.FileTypeVo" fetch="select"> <column name="FILE_TYPE_ID" precision="22" scale="0" /> </many-to-one> <property name="originalFileName" type="java.lang.String"> <column name="ORIGINAL_FILE_NAME" length="200" not-null="true" /> </property> <property name="contents" type="java.sql.Blob"> <column name="DATA_OBJECT" not-null="true" /> </property> </class>
The data base create statement looks like:
CREATE TABLE VIPR_DOCUMENT_CONTENTS( ID NUMBER NOT NULL, FILE_TYPE_ID NUMBER, ORIGINAL_FILE_NAME VARCHAR2(200), DATA_OBJECT BLOB NOT NULL, OBJECT_SIZE NUMBER, MODIFIED_BY NUMBER NOT NULL, MODIFIED_DATE DATE NOT NULL, EFFECTIVE_DATE DATE, EXPIRATION_DATE DATE, HISTORY_ID NUMBER(12, 0), TO_BE_EXPIRED CHAR(1), CONSTRAINT VDCC_PK_DOCUMENT_CONTENTS PRIMARY KEY (ID) USING INDEX LOGGING ) LOGGING
Below is the code for the simple unit test that is failing. Basically the test fails, because even though the Blob has changed from 100,000 bytes to the updated value of 200 bytes. The contents of the blob is still the character "1" rather than "2". So, file size changes, but the contents doesn't.
public void test_updateBlob() { PseudoFileVo pFileVo = createPseudoFileVo(); pFileVo.setOriginalFileName("Test#1"); HibernateSessionFactory.getSession().beginTransaction(); HibernateSessionFactory.getSession().save(pFileVo); HibernateSessionFactory.getSession().getTransaction().commit();
PseudoFileVo savedPseudoFileVo = (PseudoFileVo) HibernateSessionFactory.getSession(application).get("PseudoFileVo", pFileVo.getId()); byte[] originalBytes = BlobUtil.getByteArray(savedPseudoFileVo.getContents()); assertEquals('1', (char) originalBytes[0]); assertEquals(NUM_BYTES, originalBytes.length);
savedPseudoFileVo.setContents(makeBlob(200, '2')); savedPseudoFileVo.setOriginalFileName("Updated Test#1"); HibernateSessionFactory.getSession().save(pFileVo); HibernateSessionFactory.getSession().getTransaction().commit();
savedPseudoFileVo = (PseudoFileVo) HibernateSessionFactory.getSession(application).get("PseudoFileVo", pFileVo.getId()); byte[] newBytes = BlobUtil.getByteArray(savedPseudoFileVo.getContents()); assertEquals("Updated Test#1", savedPseudoFileVo.getOriginalFileName()); assertEquals(200, newBytes.length); FAILS HERE===> assertEquals('2', (char) originalBytes[0]); }
public static Blob makeBlob(int numBytes, char theChar) { byte[] testBytes = new byte[numBytes]; for (int i = 0; i < testBytes.length; i++) { testBytes[i] = (byte) theChar; } return Hibernate.createBlob(testBytes); }
From the class BlobUtil:
public static byte[] getByteArray(Blob blob) { try { if (blob != null) { InputStream inputStream = blob.getBinaryStream(); int index = 0; int bytesRead = 0; byte[] oneByte = new byte[1]; int byteLength = (int) blob.length(); byte[] newContents = new byte[byteLength]; do { bytesRead = inputStream.read(oneByte); if (bytesRead > 0 && index < byteLength) { newContents[index++] = oneByte[0]; } } while (bytesRead > 0); return newContents; } else { return null; } } catch (SQLException sqle) { log.error("A SQLException was thrown retrieving a blob from the database", sqle); throw new LoggingRuntimeException("Error occurred reading byte array from DB.", sqle); } catch (IOException ioe) { log.error("An IOException was thrown retrieving a blob from the database", ioe); throw new LoggingRuntimeException("Error occurred reading byte array from DB.", ioe); } }
|