convert byte array to java.sql.Clob - java

Is there any way to convert a byte array into java.sql.Clob ?
I am having this type of issue...
getHibernateTemplate().save(object)
Where object is having a field private Clob docData; and the similar is mapped into oracle table as CLOB
This docData clob is getting formed from somewhere in my java code like Hibernate.createClob(someString)
I tried to save it with type="clob" but getting cann't cast com.sun.proxy$Proxy124 to oracle.sql.CLOB. I have tried many ways to remove this Proxy but finally failed.
So I have decided to go like byte[] data = IOUtils.toByteArray(docData.getCharacterStream()); / byte[] data = IOUtils.toByteArray(docData.getAsciiStream()) and saving it as type="binary" but I am getting Caused by: java.sql.BatchUpdateException: ORA-01461: can bind a LONG value only for insert into a LONG column.
So now I want to create as a Clob from byte[].
Any help welcome.
Note earlier I was using Hibernate 3.3 and it was working fine without any such byte array conversion and etc...now I have upgraded to Hibernate 3.6.10 and getting this issue.

I'm using this method to create Blobs:
org.hibernate.engine.jdbc.NonContextualLobCreator.NonContextualLobCreator.INSTANCE.createBlob( buffer )
where buffer is an array of bytes.
There are 2 similar methods for creating CLOBs:
NonContextualLobCreator.INSTANCE.createClob( reader, length )
NonContextualLobCreator.INSTANCE.createClob( string )
Pick the one that fits better with your data.

Your error message says
cann't cast com.sun.proxy$Proxy124 to oracle.sql.CLOB
In the rest of your text you are referring to java.sql.Clob Check your imports, you might be using the clob from the oracle.sql package instead of the java.sql package somewhere.

Well, issue is resolved. I kept the java data type as 'Clob' only and made the hibernate mapping like type="string". Issue got resolved since my digital sign data does not contain more than 2 MB (that java string max supports).

Related

Reading MEDIUMBLOB from MySQL in java

This is for the first time I am working with the Blob data types.
I am storing the image files in MEDIUMBLOB datatype in MySQL database. Now, I want to retrieve it using a JAVA application.
So far, I found tutorials making use of com.mysql.jdbc.Blob.
I tried,
Blob imgAsBlob = resultset.getBlob("image");
byte[] imgAsBytes = imgAsBlob.getBytes(1, (int) imgAsBlob.length());
but I get an error at imgAsBlob.getBytes(1, (int) imgAsBlob.length()) because the second argument is larger (46352) than the BLOB's length:
java.sql.SQLException: "pos" + "length" arguments cannot be larger than the BLOB's length.
Is there any other way than getBlob() method or any other class than com.mysql.jdbc.Blob which I can use?
Thanks.

Error passing java byte array as ColdFusion query parameter: mismatched input 'struct' expecting RIGHTPAREN

I am trying to convert some CF (version 10) code that was embedded inside a .cfm file into a function of a component as part of a Framework 1 application. The component is in script syntax, and the original code is in tag syntax. I didn't write the original code, and since I am still learning ColdFusion I am only trying to replicate the original code rather than re-write it.
The function reads in a file from the client and chops it up into pieces and stores the pieces in Java ByteArrays. It then makes as many queries as needed to store the byte arrays in a database. I have successfully converted everything up until the actual insertion query.
The problem I'm having is converting this portion of code, mainly the line with #objBuffer.Array()#:
<cfquery name="insertFile" datasource="#Datasource#">
INSERT INTO wt_file (file_data,file_name,file_type,file_part,rec_id)
VALUES (
<cfqueryparam value="#objBuffer.Array()#" cfsqltype="CF_SQL_blob">,
<cfqueryparam value="#rc.fileName#" cfsqltype="cf_sql_varchar">,
<cfqueryparam value="#rc.fileType#" cfsqltype="cf_sql_varchar">,
<cfqueryparam value="#i#" cfsqltype="cf_sql_varchar">,
<cfqueryparam value="#rc.rec_id#" cfsqltype="cf_sql_varchar">)
</cfquery>
objBuffer.Array() is calling the Java method Array() on a java ByteBuffer object. When i try to do the same in script syntax like this:
fileQuery = new Query(
name="insertFile",
datasource = Datasource,
sql = "INSERT INTO wt_file
(file_data, file_name, file_type, file_part, rec_id)
VALUES (:data, :name, :type, :part, :recid)");
fileQuery.addParam(name="data", value = objBuffer.Array(), cfsqltype="CF_SQL_blob");
fileQuery.addParam(name="name", value = rc.fileName, cfsqltype="cf_sql_varchar");
fileQuery.addParam(name="type", value=rc.fileType, cfsqltype="cf_sql_varchar");
fileQuery.addParam(name="part", value=i, cfsqltype="cf_sql_varchar");
fileQuery.addParam(name="recid", value=rc.rec_id, cfsqltype="cf_sql_varchar");
/*execute query*/
fileQuery.execute();
In this syntax, the objBuffer.Array() call breaks the entire function. I have tried calling it before the parameter and passing it via a variable, but it doesn't matter where I call it. I get the same results.
The error message eclipse is giving me is not very helpful, but I'll post it anyway:
mismatched input 'struct' expecting RIGHTPAREN
0cfml.parsing.cfscript.CFParseException
null struct 137org.antlr.runtime.NoViableAltException
null function 52org.antlr.runtime.NoViableAltException
missing SEMICOLON at '(' 0cfml.parsing.cfscript.CFParseException
null function 52org.antlr.runtime.NoViableAltException
Because I am merely converting code, I am sure the is a better way to do this. I am sure there is a way to do this without using java classes but if there is a way to make this work too it would be great. Any help would be appreciated.
Thanks.

Converting cassandra blob type to string

I have an old column family which has a column named "value" which was defined as a blob data type. This column usually holds two numbers separated with an underscore, like "421_2".
When im using the python datastax driver and execute the query, the results return with that field parsed as a string:
In [21]: session.execute(q)
Out[21]:
[Row(column1=4776015, value='145_0'),
Row(column1=4891778, value='114_0'),
Row(column1=4891780, value='195_0'),
Row(column1=4893662, value='105_0'),
Row(column1=4893664, value='115_0'),
Row(column1=4898493, value='168_0'),
Row(column1=4945162, value='148_0'),
Row(column1=4945163, value='131_0'),
Row(column1=4945168, value='125_0'),
Row(column1=4945169, value='211_0'),
Row(column1=4998426, value='463_0')]
When I use the java driver I get a com.datastax.driver.core.Row object back. When I try to read the value field by, for example, row.getString("value") I get the expected InvalidTypeException: Column value is of type blob. Seems like the only way to read the field is via row.getBytes("value") and then I get back an java.nio.HeapByteBuffer object.
Problem is, I cant seem to convert this object to string in an easy fashion. Googling yielded two answers from 2012 that suggest the following:
String string_value = new String(result.getBytes("value"), "UTF-8");
But such a String constructor doesn't seems to exist anymore.
So, my questions are:
How do I convert HeapByteBuffer into string?
How come the python driver converted the blob easily and the java one did not?
Side Note:
I could debug the python driver, but currently that seems too much work for something that should be trivial. (and the fact that no one asked about it suggests Im missing something simple here..)
Another easier way is to change the CQL statement.
select column1, blobastext(value) from YourTable where key = xxx
The second column would be type of String.
You can also get direct access to the Java driver's serializers. This way you don't have to deal with low-level details, and it also works for other types.
Driver 2.0.x:
String s = (String)DataType.text().deserialize(byteBuffer);
Driver 2.1.x:
ProtocolVersion protocolVersion = cluster.getConfiguration().getProtocolOptions().getProtocolVersion();
String s = (String)DataType.text().deserialize(byteBuffer, protocolVersion);
Driver 2.2.x:
ProtocolVersion protocolVersion = cluster.getConfiguration().getProtocolOptions().getProtocolVersion();
String s = TypeCodec.VarcharCodec.instance.deserialize(byteBuffer, protocolVersion);
For version 3.1.4 of the datastax java driver the following will convert a blob to a string:
ProtocolVersion proto = cluster.getConfiguration().getProtocolOptions().getProtocolVersion();
String deserialize = TypeCodec.varchar().deserialize(row.getBytes(i), proto);
1.) Converting from byte buffer in Java is discussed in this answer.
2.) Assuming you're using Python 2, it's coming back as a string in Python because str is the binary type.

com.ibm.db2.jcc.am.SqlException: [jcc][10120][11936][4.14.88] Invalid operation: Lob is closed. ERRORCODE=-4470, SQLSTATE=null

In our application we are having a simple POJO class that has a Clob attribute within it.
I am having issue in getting the String representation of that Clob entity.
Say I have already queried and cached the result in the POJO object, now I am trying to get the String value of the Clob as below.
int aLength = (int)myPojo.getClobField().length();
String aStringValue = myPojo.getClobField().getSubString(1L, aLength);
But the above execution gives me the error,
com.ibm.db2.jcc.am.SqlException: [jcc][10120][11936][4.14.88] Invalid operation: Lob is closed. ERRORCODE=-4470, SQLSTATE=null
Am I missing something?
This issue can be solved by adding progressiveStreaming=2; argument to the connection url
The fully specified Connection URL is to be given as below:
jdbc:db2://localhost:50000/SAMPLE:progressiveStreaming=2;
In case you have exception on that parameter add the following to it or add any one or combinations of these parameters to fix it:
jdbc:db2://localhost:50000/SAMPLE:driverType=4;fullyMaterializeLobData=true;fullyMaterializeInputStreams=true;progressiveStreaming=2;progresssiveLocators=2;
It is preferred to use db2jcc4.jar
The Clob Java object is not a copy of the CLOB value stored in the database. It is a locator (pointer), which becomes invalid after the result set is closed. You'll need to copy CLOB contents while processing the result set.
For hibernate users , when mapping to a database Lob type (BLOB or CLOB) the field should be annotated #Lob and no need to keep the copy , you can directely convert it in to character array like
(java.sql.Clob)payload.field1 bodyText = clobTest.getCharacterStream()
targetString = org.apache.commons.io.IOUtils.toString(bodyText)
int length=targetString.length();
payload.PAYLOADHEADERS=targetString
return payload
Make sure you have added progressiveStreaming=2; in your data-source configuration properties.

Hibernate createSqlQuery without getting the blob data from database - "NumberFormatException" on query.list()

Shortly ..I have a web app that queries an Oracle database and displays the result on a page. The problem is that I get a NumberFormatException when retrieving the data with query.list(), this happens only on some tabels. I`ve searched and found out that this is happening because some of my tabels contains BLOB and CLOB data so ..
Is there any way I can tell hibernate to search on my DB with createSqlQuery(sqlString) without retrieving the BLOB and CLOB data from my DB ?
Here is a part of my code :
Query query = session.createSQLQuery(sqlQuery).setFetchSize( Integer.valueOf(nrOfLines) );
query.setResultTransformer(AliasToEntityMapResultTransformer.INSTANCE);
final List<Map<String, String>> resultQueryList = query.list();
NumberFormatException stacktrace:
{java.lang.NumberFormatException#2747}Method threw java.lang.NumberFormatException' exception.
detailMessage = {java.lang.String#2875} "For input string: "4294967295""
cause = {java.lang.NumberFormatException#2747}"java.lang.NumberFormatException: For input string: "4294967295""
{java.lang.StackTraceElement#2751} "java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)"
{java.lang.StackTraceElement#2752} "java.lang.Integer.parseInt(Integer.java:495)"
{java.lang.StackTraceElement#2753} "java.lang.Integer.parseInt(Integer.java:527)"
{java.lang.StackTraceElement#2754} "oracle.jdbc.driver.OracleResultSetMetaData.getPrecisionOracleResultSetMetaData.java:303)"
{java.lang.StackTraceElement#2755} "org.hibernate.loader.custom.CustomLoader$Metadata.getHibernateType(CustomLoader.java:581)"
{java.lang.StackTraceElement#2756} "org.hibernate.loader.custom.CustomLoader$ScalarResultColumnProcessor.performDiscovery(CustomLoader.java:508)"
{java.lang.StackTraceElement#2757} "org.hibernate.loader.custom.CustomLoader.autoDiscoverTypes(CustomLoader.java:524)"
{java.lang.StackTraceElement#2758} "org.hibernate.loader.Loader.getResultSet(Loader.java:1821)"
{java.lang.StackTraceElement#2759} "org.hibernate.loader.Loader.doQuery(Loader.java:697)" .......
I`ve searched a lot but found only how to read blob and clob data from DB... and what I want is exacly the opposite.
Finally found out a way to do it. I followed this article http://alessandromigliaccio.blogspot.ro/2010/11/javalangnumberformatexception-for-input.html and added to tomcat 7 the option -Doracledatabasemetadata.get_lob_precision=false
Variables that your are declaring, are holding larger values than the data types declared. You should use double or long for the same. that might resolve your problem.

Categories

Resources