我正在尝试使用SessionCustomizer
在EclipseLink中自动生成序列,这些序列遵循特殊的命名约定已存在于数据库中。例如,名为Item
的实体映射到名为ITEMS
的表,该表具有四个字母的别名ITEM
和一个名为ITEM_ID_SEQ
的数据库序列,用于生成唯一ID。
我使用注释作为标记来保存实体类的别名,因为我们也将它用于其他目的:
package jpa.namingsupport;
// imports omitted
@Target(TYPE)
@Retention(RUNTIME)
public @interface Alias {
String name();
}
实体看起来像这样:
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
}
使用正确注册的SessionCustomizer并验证在启动时运行以创建序列并将其添加到实体:
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, "_");
}
}
但是当我运行我的测试时,在保存之前不会从序列中分配ID:
[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]
我的代码中缺少的任何提示和想法?我所看到的是,在生成的insert语句中没有对ITEM_ID列的引用。
答案 0 :(得分:1)
为什么不把@GeneratedValue(strategy = SEQUENCE,generator =“ITME_ID_SEQ”)放在你的id上?
对于你的自定义程序,不要调用descriptor.setSequence(),这应该是初始化。
SQL期望id使用IDENTITY值,您需要为此配置表。如果你想使用SEQUENCE,那么将false传递给新的NativeSequence(name,increment,false)。 H2支持IDENTITY和SEQUENCE,NativeSequence默认使用IDENTITY,false表示SEQUENCE。