Reputation: 757
I am trying to map my domain objects to use the new Oracle 12c identity type primary keys, AKA auto-increment in some other systems.
Hibernate 4 does not have Oracle12cDialect, it only has Oracle10gDialect.
Oracle10gDialect has a method called supportsIdentityColumns() whitch is hard coded to return false, so mapping my GORM domain object with generator:"identity" results in an error saying that the Oracle10gDialect does not support identity generator.
I cannot use the GORM select generator because I do not have a secondary unique key and I cannot use a Hibernate generated key because then Hibernate and other (external) inserts into the tables would generate overlapping keys.
Example of Existing Oracle 12c DDL:
create table person (
id number(10,0) generated by default as identity,
version number(10,0) not null,
home_address_id number(10,0),
name varchar(255) not null,
primary key (id)
);
GORM Object:
class Person {
String name
Address homeAddress
static mapping = {
id column: 'person_key', generator: 'identity'
}
static constraints = {
homeAddress nullable: true
}
}
In Memory DB Result (Works Perfect):
Hibernate: create table person (person_key bigint generated by default as identity, version bigint not null, home_address_id bigint, name varchar(255) not null, primary key (person_key))
Hibernate: alter table person add constraint FK_bemy93e8a8i6nknj4n21m6fub foreign key (home_address_id) references address
Hibernate: insert into person (person_key, version, home_address_id, name) values (null, ?, ?, ?)
Oracle DB Result (Broken):
org.hibernate.MappingException: org.hibernate.dialect.Oracle10gDialect does not support identity key generation
How do I get Grails 3.0.9 to work with the above Oracle table definition?
Upvotes: 1
Views: 796
Reputation: 757
Hibernate 4 can not be configured to use Oracle 12c identity key generation.
Creating a custom Oracle12cDialect did not allow us to use identity key generation. It requires additional support in Hibernate 4 that is not there.
What does work is sticking with the Oracle10gDialect and using generator: 'sequence-identity' and then naming the sequence like this:
static mapping = {
id column: 'person_key', generator: 'sequence-identity', params:[sequence:'person_seq']
}
This virtually achieves the same result other than creating the tables with the identity key word in the DDL. Even if we had been able to get the identity keyword in the table definition, Oracle would simply have created its own sequence in the background to use every time a record was inserted. Using sequence-identity rather than sequence, also avoids the double DB call to insert a new row. With identity-sequence the insert DML is a single call like this:
insert into person (person_key, version, home_address_id, name) values (person_seq.nextval, ?, ?, ?)
With generator: 'sequence' new record inserts become two DB calls like this:
select person_seq.nextval from dual;
insert into person (person_key, version, home_address_id, name) values (?, ?, ?, ?)
So the only downside that I see for 'identity-sequence' over 'identity' is simply that Oracle will not automatically keep track of which sequence to use for which table and automatically use it when no key value is provided in the insert statement. But even that could probably be handled by a before insert trigger, at which point you might be almost exactly where you would be anyway if Hibernate 4 had supported generator: identity.
Upvotes: 1
Reputation: 9443
Hibernate 5 does have an Oracle 12c Dialect, specifically adding "identity" support: org.hibernate.dialect.Oracle12cDialect. So either use Hibernate 5, or write a custom 12c-based Dialect for Hibernate 4.
Upvotes: 0