JPA / Hibernate: StringClobType deprecated - java

I recently upgraded Spring Boot and with this came a hibernate upgrade. Unfortunately, the entity column #Type(StringClobType) annotation has been deprecated. The documentation tell me I need to switch it to MaterilizedClobType.
Unfortunately this has broken my application.
I'm using PostgreSQL 9.5. The StringClobType annotation created a text type in the database which allowed me to store long text in the field. Unfortunately now, the string literal comes back when Hibernate is expecting some kind of LOB id.
This gives the error: Bad value for type long

The Hibernate #Type value that maps to PG's Text data type is org.hibernate.type.TextType. This is what you should use.
For what it's worth, this a sibling of org.hibernate.type.MaterializedClobType, which maps to CLOB; both are subclasses of org.hibernate.type.AbstractLongStringType.

Related

Hibernate throwing validation exception "wrong column type encountered in column" even when my DDL script and JPA entity are in sync

I am starting my spring container in validate mode
autoddl=validate
I am getting a validation exception like this
Caused by: org.hibernate.tool.schema.spi.SchemaManagementException: Schema-
validation: wrong column type encountered in column [amount] in table [Balance];
found [numeric (Types#NUMERIC)], but expecting [int8 (Types#BIGINT)]
and my DDL script goes like this
CREATE TABLE Balance(stratr VARCHAR(25), histFromDate TIMESTAMP WITHOUT TIME
ZONE,amount numeric(11, 0))
and my attribute in JPA entity goes like this
#Column(name="amount", precision=11, scale=0) //have specified precision and scale
private Long amount ;
where I have used import javax.persistence.Column.Since I have annotated the exact precision and scale, Shouldn't hibernate validate with these info that I have provided through the column annotation? What could have I missed ?
I cannot do the following
#Column(
columnDefinition = "NUMERIC(11,0)"
)
private Long amount;
because I don't know the data store of this JPA entity.
I also tried generating the script by the following property
<prop key="javax.persistence.schema-generation.scripts.action">drop-and-create</prop>
<prop key="javax.persistence.schema-generation.scripts.create-target">./l/create.sql</prop>
<prop key="javax.persistence.schema-generation.scripts.drop-target">./l/drop.sql</prop>
This is also generating as int8 and not numeric(11,0). What can be done to solve this ?
It's really quite difficult to grasp what you're trying to accomplish, but if I understood correctly:
you want to keep your application portable by not fixing the column definition on the entity level to be NUMERIC(11,0), which would make it Postgres-specific
at the same time, you want your column to use NUMERIC(11,0) for Postgres and not INT8 that Hibernate would normally use for a Long in Postgres (and is hoping to find in your schema upon validation)
In short, you want a per-database customization that is not reflected in your entity mapping. The only way to accomplish that is to customize the dialect that Hibernate is using for your version of Postgres. What you need to do is:
determine which dialect version is being selected for your Postgres database (it will be one of the following: PostgresPlusDialect, PostgreSQL81Dialect, PostgreSQL82Dialect, PostgreSQL91Dialect, PostgreSQL92Dialect,PostgreSQL93Dialect, PostgreSQL94Dialect, PostgreSQL95Dialect, PostgreSQL9Dialect)
extend from that class, adding the following definition:
public MyCustomPostgresDialect() {
super();
registerColumnType(Types.BIGINT, "NUMERIC(11, 0)");
}
(If you want to be able to control the precision and scale using #Column(precision = ..., scale = ...), use registerColumnType(Types.BIGINT, "NUMERIC($p, $s)") instead)
add the hibernate.dialect property to persistence.xml, pointing to the fully qualified class name of your custom dialect
Note that this will, of course, affect all Long properties in your data model, not just the specific field in question.
I can think on only reason is because in your entity amount type is Long but in JPA creation script your DDL specified as amount numeric(11, 0) here second param suggest decimal precision.
As you can see java tries to enter data in Long type (ie. 10.0000), similar to BigInt in Database but database does not accept such decimal value being type numeric (11,0)
You should be able to resolve it by either changing your java code to have entity amount type int or change DDL to have scaleInt. ie. NUMERIC(11,5).
However best bet would be to have DECIMAL type for any non Integer type.
http://www.h2database.com/html/datatypes.html#decimal_type

Nulls last in hibernate 3.6 GA and Spring 4

I am using PostgreSQL database with Hibernate and Spring Rest.
I am getting sorted data in Hibernate Criteria from Postman but when data is sorted on descending order the NULL values come first, I believe this may be how PostgreSQL is sending data to Hibernate.
I know in Hibernate 4.2.x and 4.3.x there are ways to implement this using Order as shown below
Criteria criteria = ...;
criteria.addOrder( Order.desc( "name" ).nulls(NullPrecedence.LAST) );
But there is no similar implementation in 3.6 as I was getting compilation when I tried the same.
From Hibernate order by with nulls last I tried setting the Hibernate properties:
hibernate.order_by.default_null_ordering=last
It did not help me.
I am setting it as Hibernate configuration parameter, but it's not working.
I have to modify legacy code which is using Criteria so how can I implement NULLs ordering while using Criteria in Hibernate 3.6?

How to use Hibernate 5.2.10 MySQL JSON support without AttributeConverter or customUserType to map to Java Entity Class?

I am trying to map the MySQL JSON column to Java Entity class. Looking for the cleanest way of doing this.
Upon doing some research found 3 possible ways:
Extending AbstractSingleColumnStandardBasicType
Create a custom UserType
Use an attribute Converter
I used an attribute converter to convert the JSON column from String (as MySQL driver makes it to a String) to my required type - this works with both the Hibernate V4.3.10 and V5.2.10
I tried to find if JSON is natively supported in Hibernate and found the PR https://github.com/hibernate/hibernate-orm/pull/1395, based on the PR looks like it does add JSON mapping to the MySQL Dialect hence letting Hibernate know about the JSON Column.
Does this mean I can use something like this to map to JSON Column in DB ?#Column(name="json_type_column")
Private Object correspondingJsonAttribute;
If I cannot use it like this and need to use one of the above 3 methods, is there a reason I would need to upgrade to get the registerColumnType( Types.JAVA_OBJECT, "json" ); which is part of the PR and is present in Hibernate V5.2.10, Do I get any more features from V5.2.10 that support JSON columns?
I also looked into the corresponding test case to understand how the JSON column mapping is being done https://github.com/hibernate/hibernate-orm/blob/master/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/access/MixedAccessTestTask.java, this uses #Access annotation via property, looks like it sets the corresponding JSON column variable in Entity to Map after converting it from String.
Any help is much appreciated.
Thanks!
Upon doing some research found 3 possible ways:
Extending AbstractSingleColumnStandardBasicType
Create a custom UserType
Use an attribute Converter
AttributeConvertor won't help you for this, but you can still use a custom UserType, or Hibernate Type Descriptors.
Does this mean I can use something like this to map to JSON Column in
DB?
#Column(name="json_type_column") Private Object
correspondingJsonAttribute;
No. The json type is just for JDBC so that Hibernate knows how to handle that JDBC object when setting a parameter on a PreparedStatement or when fetching a ResultSet.
Do I get any more features from V5.2.10 that support JSON columns?
No, but you just need to supply your own JSON type.
You can just use the hibernate-types which is available on Maven Central.
<dependency>
<groupId>com.vladmihalcea</groupId>
<artifactId>hibernate-types-52</artifactId>
<version>${hibernate-types.version}</version>
</dependency>
And use the provided JdonType from Hibernate Types as it works on MySQL, PostgreSQL, Oracle, SQL Server or H2 without doing any modifications.

Hibernate reveng persistence model does not validate

I use Hibernate Reverse Engineering to automatically create classes from a database scheme. DB server is MSSQL 2008. This database is designed by a partner and could potentially change without notice. Thus I'd like to have Hibernate validate the scheme on startup, wich in my opinion should work out of the box. But it doesn't:
org.hibernate.HibernateException: Wrong column type in somedb.dbo.ASVC_S for column SomeCol. Found: decimal, expected: numeric(18,0)
The generated enttity class looks like this:
#Column(name="SomeCol", precision=18)
public BigDecimal getSomeCol() {
return this.someCol;
}
Is my assumption that reveng creates classes that can be validated against the schema wrong? Should I skip validation and hope that during runtime everything's OK? Annotating the classes after generating them or maintaining an entry for each class in my reveng.xml mapping file is not an option - too many classes ;)
hibernate-tools is version 4.0.0-CR1.

Hibernate "Invalid column name" error when using a NamedNativeQuery

I have recently changed an object to have a #OneToMany mapping to another object, with the FetchType.LAZY. But when I try to load a list of these objects using a #NamedNativeQuery, which calls an Oracle function, it throws a java.sql.SQLException: Invalid column name for this new OneToMany mapping. But being marked as LAZY, it shouldn't try to populate this variable should it?
In theory I could change the function to return an empty value for this column (basically a hack), but I would have to roll that out to everywhere that uses a #NamedNativeQuery to populate one of these objects.
This seems like a bug to me. Is there a workaround, something I'm missing or possibly fixed in a later version of Hibernate?
I'm using hibernate-core 3.3.2.GA, hibernate-entitymanager 3.4.0.GA, hibernate-annotations 3.4.0.GA and hibernate-commons-annotations 3.3.0.ga.

Categories

Resources