GeneratedValue with oracle and hibernate does not work - oracle

I am facing an issue with the GeneratedValue annotation in my project with Oracle XE database. The value simply does not get generated - I keep getting the error when trying to insert rows in the table with the autogenerated field.
"Caused by: java.sql.SQLIntegrityConstraintViolationException: ORA-01400: cannot insert NULL into ("SYSTEM"."T_VAPP"."VAPPID")"
The exact same code works with Derby or MySQL but I need to make it work with Oracle and it seems to ignore whatever I put in the generated field definition. I tried using GenerationType.TABLE, GenerationType.SEQUENCE but the same error persists. I also verified using Oracle SQL developer that none of the sequences defined in the code are being created. What do I miss here?
#Entity
#Table(name = "T_vApp")
#RooJavaBean
#RooToString
#RooJpaActiveRecord(identifierColumn = "vAppId", identifierField = "id", table = "T_vApp")
public class VLabApplication {
#Id
#GeneratedValue(strategy=GenerationType.AUTO, generator="my_entity_seq_gen")
#SequenceGenerator(name="my_entity_seq_gen", sequenceName="MY_ENTITY_SEQ")
#Column(name = "vAppId" )
private Long id;

GenerationType.AUTO is correct --- this will ensure that your code works for oracle as well as mysql (without the need to change your code). I use it like this and never had any problems.
Try removing the #Roo magic, generate setters/getters and see if this helps. BTW, I usually annotate the getters. I don't think this is the problem, but you can always try if everything else fails.
My guess is some problem between roo and hibernate (I've never used nor read about roo, so it is really a guess).

I suspect it may be getting confused because you're telling it in two places what the identifier field is. Plus you're telling it both with a #Table and the argument inside the #RooJpaActiveRecord annotation. You should probably remove all the arguments from the #RooJpaActiveRecord annotation on the class. Leave the #Id and #Column annotations on the class "id" member and the #Table annotation on the class.
Alternately, you may need to switch to a custom generator class that does the right thing based on which database.

You used GenerationType.AUTO instead of GenerationType.SEQUENCE

Related

#Column annotation doesn't change nullability when I change nullable property from false to true

By mistake I sit the #Column annotation property to false while my intention was to set it to true.
#Column(nullable = false)
private String title;
I tried to change the property to true after the table was created but It doesn't get changed in my table. Even though I have the following lines in my application.properties file:
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
Now when I try to create a new record I gett this error:
SQL Error: 1048, SQLState: 23000
Column 'title' cannot be null
I know that I can change nullability manually through phpMyAdmin but I'm wondering why the column annotation property doesn't work after the table is created.
From: How does spring.jpa.hibernate.ddl-auto property exactly work in Spring?
The update operation for example will attempt to add new columns, constraints, etc but will never remove a column or constraint that may have existed previously but no longer does as part of the object model from a prior run.
In general, the schema generation tool is mostly for prototyping, testing and validation. Incremental scripts using dedicated tools are a better solution for production.
There is also a note about this in the documentation:
Although the automatic schema generation is very useful for testing and prototyping purposes, in a production environment, it’s much more flexible to manage the schema using incremental migration scripts.
I'm not overly familiar with these type of tools but, to give you an example, Liquibase is just the first one that comes to mind.

Use of Hibernate when constraints are not defined

We have a requirement to redesign one application but without doing any modification on the database.
The current code uses plain jdbc to query data. We are planning to implement hibernate instead as part of the redesign.
The problem is the current database doesn't have any constraints present at the database level.
For example if there are two entities Course and Review. The current database doesn't have any mapping between them.
Now in this case if I implement hibernate and try to have #OneToMany between Course and Review, without having those constraints in the database, will that work out fine?
1 To stop hibernate from changing you scheme set parameter
spring.jpa.hibernate.ddl-auto = none
81.2 Initialize a Database Using Hibernate
2 Set GeneratedValue strategies to use existing sequences
#SequenceGenerator(name="my_seq", sequenceName="my_seq", allocationSize = 1)
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "my_seq")
private Long id;
This way Hibernate will change nothing in your schema. It will not create any sequences, tables, foreign keys, constraints e.t.c. Just use existing structure and fall if something wrong with it )
If there is no cascading from Course to Reviews and you delete Course the delete will go through without any complaints. With constraint present, DB would have complained about existing child records(Review in this case).
So special care needs to be taken specifying the cascade.

How to manage unique Ids with Hibernate and Flyway?

Here is a snippet of my entity class
#Entity
public class User {
#Id
#GeneratedValue
private long id;
private String firstName;
private String lastName;
When using (Spring Boot + Hibernate) Spring Boot setups schema automatically including sequences like one below
Hibernate: create sequence hibernate_sequence start with 1 increment by 1
But I am using Flyway 5.0.7 to setup my schema. And in this case I get the error below, which means sequence is not getting created.
Sequence "HIBERNATE_SEQUENCE" not found; SQL statement
I was able to fix this by creating sequence using flyway script like below
create sequence HIBERNATE_SEQUENCE start with 1001;
But now this sequence is used to generate Ids for all entities which I do not want. I want each entity to have its separate sequence.
Is it possible to create sequences using Hibernate when using Flyway? Otherwise it is not practical to manually create sequences for all entities which can be in hundreds.
Any alternative approach to handle this?
Flyway is a DB migration tool, and it does not know of any DDL/DML changes unless you tell it so (via new scripts in the locations property).
If Hibernate handles some of these changes (the sequences in your case) Flyway won't know about it and will use whatever sequence it already has knowledge about.
The normal thing to do is letting Flyway know of your changes, which includes a new sequence for a new entity for instance, just like you would do for the schema itself of your entity. My personal advice is to manage all your schema changes in one place, so if you are using Flyway, then let it be in charge of all of it.

Pageable sorting not working for Spring Data JPA when using named queries

I got to grips with using Spring Data JPA however I stumbled upon an issue, searched all the net but still didn't find an answer. I got the repository working and even the paging and sorting. However, it seems that when I do the same, but specifying a named query in the #Query annotation, rather than letting Spring generate the query at runtime, the sortable part of the Pageable object is completely ignored. I can confirm this as the query generated by Hibernate does not have an "ORDER BY" clause in the latter case.
public interface TransactionRepository extends JpaRepository<Transaction, Long>
{
#Query(name = "Transaction.findParentTransactionsByStatus", countName = "Transaction.findCountParentTransactionsByStatus")
public Page<Transaction> findParentTransactionsByStatus(#Param(value = "status") TransactionStatus status, Pageable pageable);
Any ideas?
Can you post the actual HQL from your named query Transaction.findParentTransactionsByStatus?
The reason I am asking is, I encountered this same issue and it was because I had an extra end parenthesis ")" in my HQL. For some reason, it was being accepted as a valid HQL, but when passing the sort via Pageable, it was not including the sort column. My solution was to remove that extra parenthesis and it worked

Postgresql and Spring Roo Binding serial type for ID

I am having trouble using the Postgresql serial type in Spring Roo. What I want is to have the an auto-incrementing id column which will work with the auto generated entity classes in Roo.
The Postgresql sequences, which are generated with the default way of doing things in Spring Roo, work fine within the spring application. But sometimes I have to manually insert rows in the database using sql. (the sequences dont seem to work properly when I do an INSERT INTO... statement). If I could use serial type, then manual INSERTS are easy.
For example I have an office entity and and employee entity. There is a many-to-one relationship between employees and offices.
Here is my class for the Office entity.
#RooJavaBean
#RooToString
#RooJpaActiveRecord
public class Office {
#Id
#Column(name="officeid", columnDefinition = "serial")
#Generated(GenerationTime.INSERT)
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long officeid;
/**
* Office Name
*/
#NotNull
#Size(max = 100)
private String name;
}
While this does work when my test inserts an office record, it fails when an employee record is inserted since the officeid foreign key value is null. (I guess it needs to flush between the office insert and the employee insert, but the auto-generate tests dont seem to do that.)
So what is the proper annotations to use to tell Roo (and hibernate/jpa) to use the serial data type, and also to work properly with inserts and relationships within the spring application?
Roo generates default JPA annotations, you must customize and setup them as needed. Note Roo guarantees your changes won't be modified.

Resources