Не съм пробвал това, но според API на Hibernate това не трябва да се усложнява чрез създаване на персонализирана реализация на IdentityGenerator .
Това е метод за генериране, получава и обект, за който генерирате стойността, за да можете да проверите типа на полето id и да върнете подходяща стойност за своя първичен ключ.
public class DynamicGenerator implements IdentityGenerator
public Serializable generate(SessionImplementor session, Object object)
throws HibernateException {
if (shouldUseAutoincrementStartegy(object)) { // basing on object detect if this should be autoincrement or not, for example inspect the type of id field by using reflection - if the type is Integer use IdentityGenerator, otherwise another generator
return new IdentityGenerator().generate(seession, object)
} else { // else if (shouldUseTextKey)
String textKey = generateKey(session, object); // generate key for your object
// you can of course connect to database here and execute statements if you need:
// Connection connection = session.connection();
// PreparedStatement ps = connection.prepareStatement("SELECT nextkey from text_keys_table");
// (...)
return textKey;
}
}
}
Ако имате това, просто го използвайте като стратегия за генериране:
@MappedSuperclass
public abstract class BaseEntity<T> implements Serializable {
@Id
@GenericGenerator(name="seq_id", strategy="my.package.DynamicGenerator")
protected T id;
}
За Hibernate 4 трябва да внедрите IdentifierGenerator
интерфейс.
Както е прието по-горе за Hibernate, все още трябва да е възможно да се създаде по по-общ начин за всеки доставчик, съвместим с jpa. Според JPA api в GeneratedValue анотация, която можете да предоставите своя персонализиран генератор. Това означава, че можете да предоставите името на вашия персонализиран генератор и трябва да внедрите този генератор за всеки доставчик на jpa.
Това би означавало, че трябва да анотирате BaseEntity със следната анотация
@MappedSuperclass
public abstract class BaseEntity<T> implements Serializable {
@Id
@GeneratedValue(generator="my-custom-generator")
protected T id;
}
Сега трябва да регистрирате персонализиран генератор с име "my-custom-generator" за всеки доставчик на jpa, който искате да използвате.
За хибернация това се извършва грубо от анотацията @GenericGenerator, както е показано по-горе (добавя се @GenericGenerator(name="my-custom-generator", strategy="my.package.DynamicGenerator"
към BaseEntity
клас на id
поле или BaseEntity
нивото на класа трябва да е достатъчно).
В EclipseLink виждам, че можете да направите това чрез GeneratedValue анотация и регистрирането й чрез SessionCustomizer:
properties.put(PersistenceUnitProperties.SESSION_CUSTOMIZER,
"my.custom.CustomIdGenerator");
public class CustomIdGenerator extends Sequence implements SessionCustomizer {
@Override
public Object getGeneratedValue(Accessor accessor,
AbstractSession writeSession, String seqName) {
return "Id"; // generate the id
}
@Override
public Vector getGeneratedVector(Accessor accessor,
AbstractSession writeSession, String seqName, int size) {
return null;
}
@Override
protected void onConnect() {
}
@Override
protected void onDisconnect() {
}
@Override
public boolean shouldAcquireValueAfterInsert() {
return false;
}
@Override
public boolean shouldOverrideExistingValue(String seqName,
Object existingValue) {
return ((String) existingValue).isEmpty();
}
@Override
public boolean shouldUseTransaction() {
return false;
}
@Override
public boolean shouldUsePreallocation() {
return false;
}
public void customize(Session session) throws Exception {
CustomIdGenerator sequence = new CustomIdGenerator ("my-custom-generator");
session.getLogin().addSequence(sequence);
}
}
Всеки доставчик трябва да даде начин за регистриране на генератор на идентификационни номера, така че ще трябва да приложите и регистрирате персонализирана стратегия за генериране за всеки от доставчика, ако искате да поддържате всички тях.