EclipseLink/JPA: Specify length of byte array - java

I have the following definition:
#Column(name = "password", length = 80)
byte[] password;
When I use EclipseLink to create the tables (mysql) I get a table with a longblob. A tinyblob would suffice.
How do I have to specify the length?
I know that I could add a columnDefinition but I'd like to keep it database/sql agnostic.

If you want specific type for blob column, columnDefinition should be used. Problem with length is that it is only for strings. This is also told in API.

Related

How to prevent password re-generating?

I use Hibernate annotation to encrypt password
#ColumnTransformer(write = "crypt(?, gen_salt(...))")
private String password;
But after updating the entity I see in logs that password re-generated.
password=crypt('$2a$...
How to prevent this field from another encryption while saving the object?
Two possible solutions here, my guess is you should go for the second:
Either you need the clear password for some reason, and then you should use a "decrypt" statement on table read, see example 73 in section 2.3.19.
Or you only need to check if the user has sent the right password, and should use a hash function and not encryption. See the difference between hash and encryption, and when to use each.
Use that configuration
#Column(name = "password", nullable = false, updatable = false)

How do I convert a column of large objects to long text?

I'm using Spring Boot with Hibernate, JPA and PostgreSQL. I'm wanting to convert database large objects into text content. Previously I was defining my long text in my JPA entity as #Lob:
#Lob
String description;
I then discovered that often problems are created using #Lob's and decided to rather change them to:
#Type(type="org.hibernate.type.StringClobType")
String description;
Which is represented in the database as a text type. Unfortunately, now the reference numbers (oid's) of the previous large objects are stored in my rows instead of the actual content. For example:
id | description
---------------------
1 | 463784 <- This is a reference to the object rather than the content
instead of:
id | description
---------------------
1 | Once upon a time, in a galaxy...
My question is now that we have thousands of rows of data in the database, how do I write a function or perform a query to replace the large object id with the actual text content stored in the large object?
Special thanks to #BohuslavBurghardt for pointing me to this answer. For your convenience:
UPDATE table_name SET column_name = lo_get(cast(column_name as bigint))
I needed some additional conversion:
UPDATE table_name SET text_no_lob = convert_from(lo_get(text::oid), 'UTF8');
I had the same problem with Spring, Postgres and JPA (Hibernate). I had a payload field that was like below
#NotBlank
#Column(name = "PAYLOAD")
private String payload;
I wanted to change the data type to text to support large data. So I used #Lob and I got the same error. To resolve that I first changed my field in my Entity like below:
#NotBlank
#Column(name = "PAYLOAD")
#Lob
#Type(type = "org.hibernate.type.TextType")
private String payload;
And because my data in this column was some scalar(Number) I have changed it to normal text with below command in Postgres:
UPDATE MYTABLE SET PAYLOAD = lo_get(cast(PAYLOAD as bigint))
Thanks a lot #Sipder.

How to storage a file into a Database as byte[] with Hibernate?

I want to storage a file into a database table as byte[]. Now I have a question concerning storing a byte[] into a postgres database table with Hibernate. I have this implementation in my Entity class:
#Column
private byte[] bytes;
In my database table it shows the datatype byte for the byte[].
Now I can see plaintext in this column (in my case the name of the file, which I want to store in the database). For each byte it will repeat the name of the file in the database column. But why?
Is a another Hibernate annotation necessary?
Thanks for help!
Greetz
Marwief
You must annotate the field with #Lob.
Note: If the column is autogenerated, you might think of setting the column definition with an additional annotation (e.g for MYSQL):
#Column(columnDefinition="LONGBLOB")//or VARBINARY(128) if you need a smaller limit
#Column(columnDefinition = "LONGBLOB")
private byte[] bytes;
Domain
import javax.persistence.Lob;
#Lob
private byte[] image;
Repository layer
byte[] image = getImageAsBytes();
domain.setImage(image);
entityManager.save(domain);
It should work, atleast it works for us. No special magic

JBoss6 JPA: Entity with #Lob results in GenericJDBCException

I have a simple EntityBean with a #Lob annotation. If I delete this annotation I get no errors on JBossAS 6.0.0.Final and MySQL5. But if I annotate it with #Lob (because mt contains about 100 to 5000 characters in my case) I get errors in my testing environment if I persist the entity.
without #Lob: mt is mapped to VARCHAR
with #Lob: mt is mapped to LONGTEXT (this is what I want, but I get errors)
This my entity:
#Entity
#Table(name = "Description")
public class Description implements Serializable
{
public static final long serialVersionUID=1;
#Id #GeneratedValue(strategy=GenerationType.IDENTITY)
private long id;
#Lob
private String mt;
} // ... getter/setter
The error are here:
...
Caused by: org.hibernate.exception.GenericJDBCException: could not insert
[my.Description]
...
Caused by: java.sql.SQLException: Connection is not associated with a managed
connection.org.jboss.resource.adapter.jdbc.jdk6.WrappedConnectionJDK6#3e4dd
...
I really don't know why I get this (reproduceable) error. The environment seems to be ok, many other tests are passed and it even works without the #Lob annotation.
This question is related to JPA: how do I persist a String into a database field, type MYSQL Text, where the usage of #Lob for JPA/MySQL is the accepted answer.
Update 1 The error above is OS specific. On a W7 machine I have no problems with #Lob, with OSX Lion always the error. I will try to update MySQL and the driver.
Update 2 The proposed workaround by Kimi with #Column(columnDefinition = "longtext") works fine, even on OSX. In both cases MySQL creates the same column: LONGTEXT.
Update 3 I updated MySQL to mysql-5.5.17-osx10.6-x86_64 and the connector to mysql-connector-java-5.1.18. Still the same error.
There is no need to annotate a String property with #Lob. Just set the column length with #Column(length = 10000).
EDIT:
Moreover, you can always set the length to your database specific maximum value, as well as define the column type with the columndefinition setting to whichever suits your needs.
For example, if you're using MySQL 5.0.3 or later, the maximum amount of data that can be stored in each data type is as follows:
VARCHAR: 65,535 bytes (~64Kb, 21,844 UTF-8 encoded characters)
TEXT: 65,535 bytes (~64Kb, 21,844 UTF-8 encoded characters)
MEDIUMTEXT: 16,777,215 bytes (~16Mb, ~5.5 million UTF-8 encoded characters)
LONGTEXT: 4,294,967,295 bytes (~4GB, ~1.4 billion UTF-8 encoded characters).
As i understand it, #Lob just sets the column type and length depending on the underlying database.
Another way that worked for me is to update launch configuration of jBoss with
-Dhibernate.jdbc.use_streams_for_binary=true
I'm running jBoss6 with MySQL5

How to fetch length of a blob field with JPQL?

I have a JPA entity with a blob field in it. I want to write a JPQL query to fetch the length of the entity's blob (I don't want to load the blob into the memory).
For instance, in Oracle, I can use the following SQL query:
SELECT length(blob_field) FROM my_table WHERE id = ?
How can I fetch the blob's length with JPQL?
You cannot. JPQL length-function counts numbers of characters in string, and number of bytes in blob doesn't fit to that definition.
But, you can use length for attributes that are persisted as CLOB (char/Characters array or String as Java type).
//can use length function for CLOBs:
#Lob char[] a;
#Lob Character b;
#Lob String c;
//can not use length function for BLOBs:
#Lob byte[] d;
#Lob Byte e;
#Lob Serializable f;
If using EclipseLink you can use the "FUNC" function in JPQL to define a database function.
See,
http://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Basic_JPA_Development/Querying/Support_for_Native_Database_Functions

Categories