Ik heb dit niet geprobeerd, maar volgens de api van Hibernate zou dit niet gecompliceerd moeten zijn door een aangepaste implementatie van IdentityGenerator .
De genereermethode krijgt en object waarvoor u de waarde genereert, zodat u het type id-veld kunt controleren en de juiste waarde voor uw primaire sleutel kunt retourneren.
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;
}
}
}
Als je dit hebt, gebruik het dan gewoon als je generatiestrategie:
@MappedSuperclass
public abstract class BaseEntity<T> implements Serializable {
@Id
@GenericGenerator(name="seq_id", strategy="my.package.DynamicGenerator")
protected T id;
}
Voor Hibernate 4 moet u IdentifierGenerator
interface.
Zoals hierboven is geaccepteerd voor Hibernate, zou het nog steeds mogelijk moeten zijn om het op een meer generieke manier te maken voor elke "jpa-compatibele" provider. Volgens JPA api in GeneratedValue annotatie kunt u uw aangepaste generator verstrekken. Dit betekent dat u de naam van uw aangepaste generator kunt opgeven en dat u deze generator voor elke jpa-provider moet implementeren.
Dit zou betekenen dat u BaseEntity moet annoteren met de volgende annotatie
@MappedSuperclass
public abstract class BaseEntity<T> implements Serializable {
@Id
@GeneratedValue(generator="my-custom-generator")
protected T id;
}
Nu moet u een aangepaste generator registreren met de naam "my-custom-generator" voor elke jpa-provider die u wilt gebruiken.
Voor Hibernate wordt dit nors gedaan door @GenericGenerator-annotatie zoals eerder getoond (toevoegen van @GenericGenerator(name="my-custom-generator", strategy="my.package.DynamicGenerator"
naar BaseEntity
klasse op een van beide id
veld of BaseEntity
klasniveau zou voldoende moeten zijn).
In EclipseLink zie ik dat je dit kunt doen via GeneratedValue annotatie en het registreren via 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);
}
}
Elke provider moet een manier bieden om id-generator te registreren, dus u moet een aangepaste generatiestrategie voor elke provider implementeren en registreren als u ze allemaal wilt ondersteunen.