CLOB not saving on ORACLE (with JPA, eclipselink) - java

I'm working on a project in which I have a class with this attribute:
#Column(name="XMLDATA", columnDefinition="CLOB NOT NULL") #Lob #Basic(fetch=FetchType.LAZY)
#Getter #Setter private String _xmlData;
In the database, the column type for that attribute is CLOB.
I'm running the application on weblogic 11gR1 (10.3.5), using Oracle database (11gR2), JPA and eclipselink as JPA Provider. The problem I have is that everytime I save a registry on the database, the clob is the only field that is not saved.
But if I don't put the #lob annotation, then it works fine.
In the logs, I can see that first it uses an "insert" sentence to insert all the data except for the clob, and then it uses a "select for update" sentence to insert the clob data, I don't know if this may be part of the problem.
Thank you.

For the proper management of the blobs (JPA + Oracle) you must specify the following properties of eclipselink :
property name="eclipselink.target-database"
value= "org.eclipse.persistence.platform.database.oracle.Oracle11Platform"
It seems that JPA sometimes cannot detect the correct version of Oracle Database platform

I've searched a lot for this answer, until I realized that if you are using EclipseLink, at least 2.5.2 version, you don't have to use "#Column(name="XMLDATA", columnDefinition="CLOB NOT NULL") #Lob #Basic(fetch=FetchType.LAZY)". Just do this:
#Column(name = "XML_DATA")
private String _xmlData;
EclipseLink will know how to handle the CLOB column.

Related

How do I Insert JSON-formatted string to a H2 database using Hibernate?

I have a PostgresSQL production database, but I'm trying to run some of my automated tests against H2 in-memory. I'm trying to persist JSON formatted data to a table but while I'm able to write the data with no complaints, I get conversion exceptions when I read them back. I have no problem doing this in the production Postgres database.
The object I'm persisting is structured similar to the following:
#Entity
public class Record {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#Column(columnDefinition = "jsonb")
#Convert(converter = PersonalInfoConverter.class)
private PersonalInfo personalInfo;
public Record() {}
public Record(PersonalInfo personalInfo) {
this.personalInfo = personalInfo;
}
}
The PersonalInfoConverter just uses a Jackson ObjectMapper to de/serialise the object from/to a String (pretty standard stuff with writeValueAsString, and readValue). To get jsonb to work with H2, I used this trick, which basically sets jsonb as an alias for H2's JSON.
I kept running into conversion errors when reading records from the database, until I stumbled upon this question, which linked to a further discussion on Github about inserting JSON formatted strings into H2 tables. It sounds like to be able to get this to work properly, I need to specifically annotate the string inserted into the H2 database. I assumed that, if this were the case, then Hibernate should have handled this properly itself, but it didn't seem like it works out of the box. How do I configure my code to get this to work?
In the meantime, I'm working around this issue by using jsonb as an alias to H2's text type instead:
CREATE TYPE "JSONB" as text;
I've created a project to demonstrate the issue.
Hibernate does not know about the "JSON" SQL data type and how it needs to be handled. Just use text like you do now, that's totally fine. AFAIU the JSON data type in H2 is just like a domain type with validation i.e. you could replace it with TEXT CHECK is_json(..), so there is not much value in using that particular data type. You could tell hibernate to use #ColumnTransformer to append this FORMAT JSON, but then you'd have issues with PostgreSQL again. Overall, this cross database testing with proprietary features that Hibernate does not abstract over is simply a mess. I would suggest you simply drop H2 and use PostgreSQL with fsync=off for testing which is quite fast already.

Spring CrudRepository not saving more than 32,000 characters

I am trying to save an entity using Springs crud repository (repo.save(Entity)) to my sql db - for some reason though when the entity is saved, the entity's variables/payloads are cut off at 32,000 characters in the db. Is there a limit that is causing this? (The column in my SQL db is type LONGTEXT - max of ~4million characters).
Solved it with annotating the column with #Lob, and specifying as columnDefinition = "LONGTEXT"

Spring Boot application doesn't create schemas for JPA #Table annotation

I want to have tables located in different database schemas. But unfortunately, I can't achieve this with Spring Boot. Here steps to reproduce it.
Create a new Spring Boot project on http://start.spring.io version 2.0.5 (with derby and PostgreSQL dependencies)
Create simple entity
#Entity
#Table(name = "my_table")
public class MyTable {
#Id Integer id;
}
Add only next property to the application.properties with value 'update' or 'create' (if you try 'create-drop' then you get another error described here: https://github.com/spring-projects/spring-boot/issues/7706#issuecomment-268798059). Now Derby datasource will be used by default.
spring.jpa.hibernate.ddl-auto=create
Run a generated test or main class. Be sure all works fine.
Modify the entity, add attribute schema to the #Table annotation. Now the entity looks like:
#Entity
#Table(name = "my_table", schema = "my_schema")
public class MyTable {
#Id Integer id;
}
Run a test (or main class). This time I get an error while Spring Boot initialization process "java.sql.SQLSyntaxErrorException: Schema 'MY_SCHEMA' does not exist":
Full log listing is available here: https://gist.github.com/asaushkin/8d767c92b2e7025dd359f7be43eefdd6
Check on PostgreSQL. This error reproduces on a PostgreSQL instance too. Without the 'schema' attribute Spring Boot app runs perfect, but as soon as this attribute appears on the #Table annotation the exceptions are thrown.
Full log is here: https://gist.github.com/asaushkin/dd0d677964556bf943c4f013d4785372
My question is: why are schemas not created by Spring Boot?
These options can't resolve this issue too:
spring.jpa.properties.javax.persistence.schema-generation.create-database-schemas=true
spring.jpa.properties.hibernate.hbm2dll.create_namespaces=true
Links
https://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/Hibernate_User_Guide.html#configurations-hbmddl
https://docs.spring.io/spring-boot/docs/current/reference/html/howto-data-access.html#howto-configure-jpa-properties
Update (11 March 2019):
I've just check the current behavior of the issue. I wonder, but currently with Derby driver all works fine and the table is created with the specified schema. But in PostgreSQL an error continues exists.
Generated SQL (for PostgreSQL) is:
create table my_schema.my_table (id int4 not null, primary key (id))
Check that are you specifying the database dialect in the application.properties file or not for more check this thread.
Unable to get spring boot to automatically create database schema
I had the same problem with PostgreSQL and JPA (ERROR o.h.e.jdbc.spi.SqlExceptionHelper - ERROR: relation "schema.table" does not exist) and I figured out this solution.
In your entities classes, add escape characters \", between database element´s name. For instance:
Use this form:
#Table(name = "\"USUARIO\"", schema="\"INVENTARIODB\"")
Rather than a typical way
#Table(name = "USUARIO", schema="INVENTARIODB")
The same applies for columns names
#Column(name = "\"ID\"", nullable = false, updatable = false)
private Long id;
Rather than
#Column(name = "ID", nullable = false, updatable = false)
private Long id;
UPDATE:
I discovered the reason that was causing the problem. I used Valentina Studio to create my DB, if I use capital letters (MYTABLE), instead lower-case letters (mytable) to create my tables, I had to use double quotes inside SQL statements. This is because PostgreSQL is case sensitive. If you can´t change your database then use my last solution. Also is a good idea to enable spring.jpa.show-sql=true property, so you can see hibernate´s queries and know what´s going on.
Rename spring.jpa.properties.javax.persistence.schema-generation.create-database-schemas to spring.jpa.properties.javax.persistence.create-database-schemas. In other words, remove '.schema-generation'.
I just had the same problem not with PostgreSQL but H2 - schemas weren't being created. But, as I've discovered, the problem is not with H2 (or, likely, PostgreSQL) but, rather, Hibernate (it deviates from the standard, regarding that nomenclature). That likely means that this solution will work for you too.

IntelliJ persistence tool type mapping

I have a PostgreSQL database schema. And I am trying to generate JPA entities from that schema in IntelliJ with the integrated persistence tool. Everything works fine, except the mapping of timestamps.
The persistence tool is trying to map the PostgreSQL TIMESTAMP data type to java.lang.Object or java.io.Serializable. I can't change the mapping to LocalDateTime, String or anything else.
Is there any way to set the correct mapping types?
UPDATE:
I get the following exception:
SchemaManagementException: Schema-validation: wrong column type encountered in column [timestamp] in table [ProcessEvent]; found [timestamptz (Types#TIMESTAMP)], but expecting [bytea (Types#VARBINARY)]
Have you used the proper annotation for the attribute?
#Entity
public class Employee {
...
#Basic
#Temporal(DATE)
private Calendar startDate;
...
}
Please see: https://en.wikibooks.org/wiki/Java_Persistence/Basic_Attributes#Temporal.2C_Dates.2C_Times.2C_Timestamps_and_Calendars

Is there a way to disable Hibernate optimistic locking?

I have an entity:
#Entity
public class VersionedDo {
#Version
#Column(name = "version")
private int version;
...
}
I want to update this entity without version increment in the some cases. Is there any way to do it without direct SQL update?
From Hibernate documentation :
Your application is forbidden from altering the version number set by Hibernate.
To artificially increase the version number, see the documentation for properties LockModeType.OPTIMISTIC_FORCE_INCREMENT or LockModeType.PESSIMISTIC_FORCE_INCREMENTcheck in the Hibernate Entity Manager reference documentation.
Therefore, using Hibernate, I guess you cannot force a version field to keep its original value when updating. You can only do the opposite.
You'll have to use a classic SQL query and don't forget to "refresh" your Hibernate object if needed.

Categories