I am working on a Java application, that should do CRUD operations (using Hibernate 4.3.8) on two different databases with the same database schema. There is a MySQL (version 5.1.73) and an Oracle (11g Express Edition Release 11.2.0.2.0 - 64bit) database.
Java classes with JPA annotations were generated from the database tables with Hibernate Code Generation.
The problem is that we now have the need to use auto primary key generation and MySQL uses GenerationType.IDENTITY and Oracle uses GenerationType.SEQUENCE. Furthermore, we need the ability to manually set primary key by ourself in some rare cases.
The followig code in the annotated class works with auto key generation for both databases but fails, if a primary key is self set.
@GeneratedValue(strategy=GenerationType.AUTO, generator="sequence_generator")
@SequenceGenerator(name="sequence_generator", sequenceName="SEQUENCE1")
@Column(name = "id", unique = true, nullable = false)
public Integer getId() {
return this.id;
}
Without the @GeneratedValue and @SequenceGenerator annotations it is possible to set the primary key manually, but auto generation doesn't work.
Even if you used
GenerationType.AUTO
without any SEQUENCE specific parameter, you wouldn't be able to save assigned identifiers.There are some workarounds if you are willing to make some compromises:
One way would be to switch to the assigned identifiers. You can use UUID identifiers, which work for both MySQL and Oracle and you can also assign the values manually.
Another way is to use a custom table generator.
First you define an Identifiable interface:
Then you extend the table generator:
This generator is able to mix assigned identifiers with synthetic generated ones:
generating the following statements:
For Oracle, you can combine the SEQUENCE and the assigned generators. In short, considering the following generator:
You can map it to your entities as follows:
All the code is available on GitHub and works like a charm.