I am trying to use a SessionCustomizer
to automatically generate Sequences in EclipseLink which already exist in the database following a special naming convention. For example an entity called Item
is mapped to a table called ITEMS
which has a four letter alias ITEM
and a database sequence called ITEM_ID_SEQ
for unique ID generation.
I am using an annotation as a marker to hold the alias name on the entity class because we are using it for other purposes, too:
package jpa.namingsupport;
// imports omitted
@Target(TYPE)
@Retention(RUNTIME)
public @interface Alias {
String name();
}
Entities look like this:
package jpa.entities;
// imports omitted
@Entity
@Table(name = "ITEMS")
@Alias(name = "ITEM")
public class Item {
@Id
private Long id;
@Version
private Long version;
private String name;
// setters and getters omitted
}
Using a SessionCustomizer registered correctly and verified running on startup to create and add the Sequences to the entities:
package jpa.namingsupport;
// imports omitted
public class AliasCustomizer implements SessionCustomizer {
@Override
public void customize(Session session) throws Exception {
Map<Class, ClassDescriptor> entities = session.getDescriptors();
for (Class entity : entities.keySet()) {
customizeSequence(aliasNameFor(entity), entities.get(entity), session);
}
}
private String aliasNameFor(Class entity) {
Alias alias = (Alias) entity.getAnnotation(Alias.class);
return alias.name();
}
private void customizeSequence(String alias, ClassDescriptor descriptor, Session session) {
NativeSequence sequence = new NativeSequence(underscores(alias, "ID", "SEQ"), 1);
session.getLogin().addSequence(sequence);
descriptor.setSequenceNumberName(sequence.getName());
descriptor.setSequenceNumberField(descriptor.getPrimaryKeyFields().get(0));
descriptor.setSequence(sequence);
}
private String underscores(String... parts) {
return StringUtils.arrayToDelimitedString(parts, "_");
}
}
But when I am running my tests the ID is not assigned from the Sequence before saving:
[EL Warning]: 2013-07-14 20:32:32.571--UnitOfWork(1908148255)--Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: org.h2.jdbc.JdbcSQLException: NULL nicht zulässig für Feld "ITEM_ID"
NULL not allowed for column "ITEM_ID"; SQL statement:
INSERT INTO ITEMS (ITEM_NAME, ITEM_VERSION) VALUES (?, ?) [23502-172]
Any hints and ideas what I am missing in my code? What I am seeing is that there is no reference to the ITEM_ID column in the generated insert statement.
Why don't you just put @GeneratedValue(strategy=SEQUENCE, generator="ITME_ID_SEQ") on your id?
For your customizer, don't call descriptor.setSequence(), this should be done be initializaiton.
The SQL is expecting the id to being using an IDENTITY value, you need to configure your table for this. If you want to use SEQUENCE instead, then pass false into new NativeSequence(name, increment, false). H2 supports both IDENTITY and SEQUENCE, and NativeSequence defaults to using IDENTITY, false means SEQUENCE.