Read image stored as blob, directly into byte[] using springdata - java

I have an image stored in an Oracle database and I'm using spring data to retrieve the image.
#Query("SELECT c.binaryContent from ContentEntity c join c.ParentContentEntities pce where pce.SpecificEntity.id = :id and pce.contentType.id = 11")
byte [] getImageBinaryContent(#Param("id") Long id);
#Lob
#Column(name = "BINARY_CONTENT")
private byte [] binaryContent;
byte[] testImageArray = serviceLayer.getImageBinaryContent(id) RETURNS NULL
Tested individually this query works. It finds content but when the call is made to getImageBinaryContent passing in an id, I get nothing back, just null result. If I change the return type to blob, I successfully get a blob back.
Why can't I read a blob into a byte array directly? My searches have shown examples of getting the blob returned, and then converting the blob with an inputstream into a byte array, but it seems like I should just be able to do this directly.

Related

How to insert image to Sqlite in android? and get for profile [duplicate]

This question already has answers here:
How to store image in SQLite database
(6 answers)
Closed 3 years ago.
I have an app it can get image from my phone gallery but how I can store that image into SQLite database and get that image for user profile from the SQLite database.
In order to store an image in the SQLite database you have to use "blob".
Examples:
Storing an image
public void insertImg(int id , Bitmap img ) {
byte[] data = getBitmapAsByteArray(img); // this is a function
insertStatement_logo.bindLong(1, id);
insertStatement_logo.bindBlob(2, data);
insertStatement_logo.executeInsert();
insertStatement_logo.clearBindings() ;
}
public static byte[] getBitmapAsByteArray(Bitmap bitmap) {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
bitmap.compress(CompressFormat.PNG, 0, outputStream);
return outputStream.toByteArray();
}
Retrieving an image
public Bitmap getImage(int i){
String qu = "select img from table where feedid=" + i ;
Cursor cur = db.rawQuery(qu, null);
if (cur.moveToFirst()){
byte[] imgByte = cur.getBlob(0);
cur.close();
return BitmapFactory.decodeByteArray(imgByte, 0, imgByte.length);
}
if (cur != null && !cur.isClosed()) {
cur.close();
}
return null;
}
I suggest you to follow this tutorial
You can store the image as a blob
create your table this way
"CREATE TABLE TABLE_NAME_HERE (lastname TEXT, gender TEXT, signature BLOB)"
declare your person class as
public String Lastname;
public String Gender;
public byte[] Signature;
get the image as and convert to byte array
byte[] signatureByte = //get the image byte array here
add to db as
SQLiteDatabase db = OpenDb();
ContentValues values = new ContentValues();
values.put(KEY_LAST_NAME, person.Lastname);
values.put(KEY_GENDER, person.Gender);
values.put(KEY_SIGNATURE, person.Signature);
db.insert(TABLE_NAME_HERE, null, values);
retrieve as
SQLiteDatabase db = OpenDb();
Cursor cursor = db.rawQuery("SELECT * FROM " + TABLE_NAME_HERE, null);
if (cursor.moveToFirst()) {
Person person = new Person();
person.Lastname = cursor.getString(cursor.getColumnIndex(KEY_LAST_NAME));
person.Gender = cursor.getString(cursor.getColumnIndex(KEY_GENDER));
person.Signature = cursor.getBlob(cursor.getColumnIndex(KEY_SIGNATURE));
return person;
}
display as
signature.setImageBitmap(BitmapFactory.decodeByteArray(person.Signature, 0, person.Signature.length))
Alternatively, you can store the image in your application folder and store a reference to it in you db. that way you can retrieve it.
Your first issue you should consider is whether or not you should be saving images in the database.
Generally storing images it is not a good idea.
For Android storing and retrieving large images say over 100KB can be problematic. Under such a size (perhaps larger) SQLite can actually be quite efficient 35% Faster Than The Filesystem(Note that this document is relatively old)).
Unless you devise alternatives to the standard Android SDK then the absolute maximum size of an image that can be retrieved is under 2MB. That is due to a CursorWindow (a buffer for the returned rows) being only 2MB.
In short if any image to be stored is nearing 2MB or is 2MB or larger then you will not be able to retrieve it without complicating matters. Such a method is explained in this Q and A, How to use images in Android SQLite that are larger than the limitations of a CursorWindow? Note this method is not recommended.
What is recommended is that images are saved to disk and that the path (or enough of the path to uniquely identify the full path to the image) is instead stored. Thus you retrieve that path from the database and then retrieve the image from the extracted path.
The Answer at How can I insert image in a sqlite database. Demonstrates both this methodology and also of saving smaller images (100k or less) in the database (taking advantage of 35% Faster Than The Filesystem).

How to save a UUID as binary(16) in java

I have a table TestTable with columns ID as binary(16) and name as varchar(50)
I've been trying to store an ordered UUID as PK like in this article Store UUID in an optimized way
I see the UUID is saved in database as HEX (blob)
So I want to save this ID from java but I am getting this error
Data truncation: Data too long for column 'ID' at row 1
I am currently using the library sql2o to interact with mysql
So basically this is my code
String suuid = UUID.randomUUID().toString();
String partial_id = suuid.substring(14,18) + suuid.substring(9, 13) + suuid.substring(0, 8) + suuid.substring(19, 23) + suuid.substring(24)
String final_id = String.format("%040x", new BigInteger(1, partial_id.getBytes()));
con.createQuery("INSERT INTO TestTable(ID, Name) VALUES(:id, :name)")
.addParameter("id", final_id)
.addParameter("name", "test1").executeUpdate();
The partial id should be something like this 11d8eebc58e0a7d796690800200c9a66
I tried this statement in mysql without issue
insert into testtable(id, name) values(UNHEX(CONCAT(SUBSTR(uuid(), 15, 4),SUBSTR(uuid(), 10, 4),SUBSTR(uuid(), 1, 8),SUBSTR(uuid(), 20, 4),SUBSTR(uuid(), 25))), 'Test2');
But I got the same error when I remove the unhex function. So how can I send the correct ID from Java to mysql?
UPDATE
I solved my problem inspired on the answer of David Ehrmann. But in my case I used the HexUtils from tomcat to transform my sorted UUID string into bytes[]:
byte[] final_id = HexUtils.fromHexString(partial_id);
Try storing it as bytes:
UUID uuid = UUID.randomUUID();
byte[] uuidBytes = new byte[16];
ByteBuffer.wrap(uuidBytes)
.order(ByteOrder.BIG_ENDIAN)
.putLong(uuid.getMostSignificantBits())
.putLong(uuid.getLeastSignificantBits());
con.createQuery("INSERT INTO TestTable(ID, Name) VALUES(:id, :name)")
.addParameter("id", uuidBytes)
.addParameter("name", "test1").executeUpdate();
A bit of an explanation: your table is using BINARY(16), so serializing UUID as its raw bytes is a really straightforward approach. UUIDs are essentially 128-bit ints with a few reserved bits, so this code writes it out as a big-endian 128-bit int. The ByteBuffer is just an easy way to turn two longs into a byte array.
Now in practice, all the conversion effort and headaches won't be worth the 20 bytes you save per row.

getting hibernate exception when i upload image

my controller class is
#RequestMapping(value = "/profilePictureUpload", method = RequestMethod.POST)
public String handleFormUpload(#RequestParam("fileExtension") String fileExtension, #RequestParam("file") MultipartFile file,HttpServletRequest request) {
logger.info("In add profile Picture Upload");
String mediaResponse=null;;
try {
String token = request.getHeader("authToken");
System.out.println("+++++++++++++++token+++++++++++++++++++"+token );
User user = userDao.findUserByAuthToken(token);
System.out.println("+++++++++++++++USER+++++++++++++++++++"+user );
System.out.println("+++++++++++++++file.getBytes()+++++++++++++++++++"+file.getBytes() );
if (user != null) {
Physician physicain=physicainDao.findPhysicianById(user.getPhysicianId().getPhysicianId());
String fileStoragPath=userOriginalServerPath+"/"+physicain.getPhysicianId();
File file1=new File(fileStoragPath);
file1.mkdirs();
String filePath=fileStoragPath+"/"+physicain.getPhysicianId()+System.currentTimeMillis()+fileExtension;
FileOutputStream fileOuputStream =new FileOutputStream(filePath);
fileOuputStream.write(file.getBytes());
fileOuputStream.close();
/**
* Creating thumbnail for media upload
*/
File thumbnailPath=new File(userThumbnailFilePath+physicain.getPhysicianId());
thumbnailPath.mkdirs();
String thumbnail_path=physicain.getPhysicianId()+"/"+physicain.getPhysicianId()+System.currentTimeMillis()+fileExtension;
Thumbnails.of(new File(filePath)).size(75, 75).toFile(new File(userThumbnailFilePath+thumbnail_path));
physicain.setProfileImage("MedikmUserPicture/thumbnail/"+thumbnail_path);
physicainDao.update(physicain);
mediaResponse="MedikmUserPicture/thumbnail/"+thumbnail_path;
}else{
mediaResponse=MedikmConstants.USER_INVALID_AUTHENTICATION__MESSAGE;
}
System.out.println("================mediaResponse============"+mediaResponse);
return mediaResponse;
}
catch(Exception ex){
ex.printStackTrace();
logger.error("Error in media tag Method :"+ex);
return mediaResponse=MedikmConstants.USER_INVALID_AUTHENTICATION__MESSAGE;
}
}
and by uploading image getting hibernate exception like
org.hibernate.exception.DataException: Could not execute JDBC batch update
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:102)
image is getting upload successfully but don't know why i am getting this exception field name of physician class is i mapped
#Column(name = "Profile_Image")
private String profileImage;
please help me to get me out from this exception.
The Profile_Image sholud be either TINYBLOB,BLOB,MEDIUMBLOB,LONGBLOB
Depending on your needs, as:
TINYBLOB: maximum length of 255 bytes
BLOB: maximum length of 65,535 bytes
MEDIUMBLOB: maximum length of 16,777,215 bytes
LONGBLOB: maximum length of 4,294,967,295 bytes
So you have to update your Profile_Image column
example: if you set your column MEDIUMBLOB it's mapping should be :-
#Lob
#Column(name="Profile_Image",columnDefinition="mediumblob")
private byte[] profileImage;
Note : i got this error while saving a very big image and my data type was Blob and i was using mysql Packet for query is too large . You can change this value on the server by setting the max_allowed_packet variable.
after some searching i found that
You must increase this value if you are using large BLOB columns or
long strings. It should be as big as the largest BLOB you want to use.
The protocol limit for max_allowed_packet is 1GB. The value should be
a multiple of 1024; nonmultiples are rounded down to the nearest
multiple.
so i found SET GLOBAL max_allowed_packet = 1024*1024*number of MB
i.e.
SET GLOBAL max_allowed_packet = 1024*1024*14
this will set the max size of allowed packet 14 GB,make sure you restart MySQL for change to take effect
See this and this full examples to save image in hibernate

ORA-06553 wrong arguments with java function in Oracle with Blob

I am trying to implement a function in Oracle 11g which calls a java class to decrypt Blob image information.
Everything seems valid, but I get a ORA-06553 PLS-306 "wrong number or types of arguments"
The function takes a blob and returns a blob so I don't see where the error is coming from.
PL/SQL function:
create or replace
function decrypt_image return blob as
language JAVA name 'Imageutil.decryptBlobImage (java.sqlBlob) return java.sqlBlob';
Java function:
public class Imageutil
public static java.sql.Blob decryptBlobImage (java.sql.Blob img) throws Exception {
try {
int len = (int)img.length();
byte[] imagearray = img.getBytes(1, len);
byte[] decrypted = Encryptor.decryptBinary(imagearray);
Blob retval = new SerialBlob(decrypted);
return retval;
} catch (SQLException ex) {
ex.printStackTrace();
throw new Exception("Error handling blob",ex);
}
}
}
The data is in a table:
temp_image(id number, image blob, decrypted blob);
I am trying to
update temp_image set decrypted = decrypt_image(image);
When I get the error. An Oracle trc file is generated each time, but the there doesn't appear to be an error:
========= Dump for error ORA 1110 (no incident) ========
----- DDE Action: 'DB_STRUCTURE_INTEGRITY_CHECK' (Async) -----
(it then does an integrity check of the database).
The function works, the original data is a long raw, and I can take a hex dump of the data and decrypt it fine. The test table was loaded by a to_lob() function on the original long raw data.
You seem to have java.sqlBlob instead of java.sql.Blob in the PL/SQL declaration; but you also aren't supplying an argument for your function inthat declaraion:
create or replace
function decrypt_image (original_blob blob) return blob as
language JAVA name 'Imageutil.decryptBlobImage (java.sql.Blob) return java.sql.Blob';
Woth your version the PL/SQL function doesn't take an argument, so when you call it as decrypt_image(image) you are passing the wrong number of arguments - it is expecting none but you pass one.

`InvalidQueryException: cannot parse '[B#50908fa9' as hex bytes` using Datastax Java driver

I am trying to insert byte array into Blob data type in my Cassandra table.. I am using Datastax Java driver. Below is my code -
for (Map.Entry<String, byte[]> entry : attributes.entrySet()) {
System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());
String cql = "insert into test_data (user_id, name, value) values ('"+userId+"', '"+entry.getKey()+"', '"+entry.getValue()+"');";
System.out.println(cql);
CassandraDatastaxConnection.getInstance();
CassandraDatastaxConnection.getSession().execute(cql);
}
And this is the exception I am getting back -
InvalidQueryException: cannot parse '[B#50908fa9' as hex bytes
I guess the problem is, the way I am making my above cql.. Something is missing for sure...
I have created the table like this -
create table test_data (user_id text, name text, value blob, primary key (user_id, name));
Can anybody help me? Thanks...
The problem is that when you append the byte array to the String it calls toString on the byte[] which prints the unhelpful pointer you are seeing. You need to manually convert it to a String for your data type. In your case you are using a blob, so you need to convert to a hex string.
This question has code for converting the byte[] to String:
How to convert a byte array to a hex string in Java?
You can use one of those functions and prepend '0x' to it. Then you should have a valid String for your blob.

Categories