Zdravim vsechny. Ja jsem ve svem projektu potreboval totez, a navic
jsem potreboval pri generovani id provest jeho upravu, abych mohl
slucovat data z vice databazi a vyresil jsem to svou implementaci
generatoru ID.
Tento generator pozna zda je id nastaveno a pokud je ponecha jej, pokud
neni pouzije bud sekvenci (je li podporovana), nebo HILO generovani,
neni li. Nize zasilam ukazku. Jiste nebude pro vas problem toto upravit
pro sve pouziti.
Jaroslav Hurdes
import java.io.Serializable;
import java.util.Properties;
import org.hibernate.HibernateException;
import org.hibernate.Interceptor;
import org.hibernate.MappingException;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.id.Configurable;
import org.hibernate.id.IdentifierGenerationException;
import org.hibernate.id.IdentifierGenerator;
import org.hibernate.id.PersistentIdentifierGenerator;
import org.hibernate.id.SequenceGenerator;
import org.hibernate.id.TableHiLoGenerator;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.type.Type;
/**
* Trida implementujici generator identit pouzitelny
* v distribuovanem prostredi.
*
* @author Jaroslav Hurdes
*/
public class DistributedDbSequenceIdGenerator implements
PersistentIdentifierGenerator, Configurable {
public static final String STRATEGY_NAME =
"cz.hurdes.common.business.data.DistributedDbSequenceIdGenerator";
protected Type identifierType;
protected IdentifierGenerator idGenerator;
protected boolean sequenceGenerator;
/**
* Konfigurace generatoru identit
*/
public void configure(Type type, Properties parameters, Dialect
dialect)
throws MappingException {
identifierType = type;
idGenerator = null;
sequenceGenerator = dialect.supportsSequences();
if(sequenceGenerator) {
idGenerator = new SequenceGenerator();
} else {
idGenerator = new TableHiLoGenerator();
}
if(idGenerator instanceof Configurable) {
((Configurable)idGenerator).configure(type, parameters,
dialect);
}
}
/**
* Generovani klice
*/
public Serializable generate(SessionImplementor sessionImpl, Object
obj)
throws HibernateException {
Serializable assignedId = getAssignedId(sessionImpl, obj);
if(assignedId != null) {
// Pokud je klic zadany, potom jej nechame tak jak je
return assignedId;
} else {
// Vygenerujeme novy klic
Serializable result = idGenerator.generate(sessionImpl, obj);
result = addDbIdentificator(result);
return result;
}
}
/**
* Metoda otestuje, zda je zadan identifikator.
* @param sessionImpl
* @param obj
* @return
*/
private Serializable getAssignedId(SessionImplementor sessionImpl,
Object obj) {
Interceptor interceptor = sessionImpl.getInterceptor();
String entityName = interceptor.getEntityName(obj);
EntityPersister persister =
sessionImpl.getEntityPersister(entityName, obj);
Serializable id = persister.getIdentifier(obj,
sessionImpl.getEntityMode());
return id;
}
/**
* Modifikace vygenerovaneho klice pro pouziti v distribuovanem
prostredi
* podle prislusne databaze
*
* @param key puvodni klic
* @return modifikovany klic
*/
private Serializable addDbIdentificator(Serializable key) {
if(DistributedDbParameters.getParameters().isBaseSetting()) {
return key;
}
Class idClass = identifierType.getReturnedClass();
int multiplier =
DistributedDbParameters.getParameters().getMultiplier();
int databaseId =
DistributedDbParameters.getParameters().getDatabaseId();
if(idClass == Long.class) {
key = (Long)key * multiplier + databaseId;
} else if(idClass == Integer.class) {
key = (Integer)key * multiplier + databaseId;
} else if(idClass == Short.class) {
key = (Short)key * multiplier + databaseId;
} else if(idClass == Short.class) {
key = ((String)key) + databaseId;
} else {
throw new IdentifierGenerationException("This id generator
generates long, " +
"integer, short or
string");
}
return key;
}
public Object generatorKey() {
if(sequenceGenerator) {
return ((SequenceGenerator)idGenerator).generatorKey();
} else {
return ((TableHiLoGenerator)idGenerator).generatorKey();
}
}
public String[] sqlCreateStrings(Dialect dialect) throws
HibernateException {
if(sequenceGenerator) {
return
((SequenceGenerator)idGenerator).sqlCreateStrings(dialect);
} else {
return
((TableHiLoGenerator)idGenerator).sqlCreateStrings(dialect);
}
}
public String[] sqlDropStrings(Dialect dialect) throws
HibernateException {
if(sequenceGenerator) {
return
((SequenceGenerator)idGenerator).sqlDropStrings(dialect);
} else {
return
((TableHiLoGenerator)idGenerator).sqlDropStrings(dialect);
}
}
}
Dne 18.10.2010 19:04, Oto Buchta napsal(a):
Dne 18. října 2010 16:07 "Zdeněk Troníček"<[email protected]> napsal(a):
Vidim dve cesty:
1) SQL: pomoci ALTER TABLE vypnout autoincrement, pokud je zapnuty, pak
vlozit data pomoci INSERT a autoincrement zase zapnout (zkousel jsem to v
MySQL a tam to funguje)
Autoincrement nemám - používám seqenci. SQL jsem se ale právě chtěl vyhnout.
2) Java: pomoci ALTER TABLE vypnout autoincrement, pokud je zapnuty;
zakomentovat anotaci @GeneratedValue a vlozit entity pres JPA; po vlozeni
obnovit anotaci @GeneratedValue a zapnout autoincrement
Jak jsem psal, anotace použít nemohu...
Oto Buchta napsal(a):
Dne 18. října 2010 10:54 "Zdeněk Troníček"<[email protected]>
napsal(a):
Takhle to funguje pro strategy s hodnotou GenerationType.AUTO. Tj. pokud
id prideluje framework (Hibernate, EclipseLink,...), lze mu id
nadiktovat.
Aha, dík za tip. Problém je v tom, že mi hodnota "auto" není
definována pro http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd
- org.hibernate.MappingException: could not interpret id generator
strategy: auto
No a protože mám Hibernate jako JBossí MBeanovou servisu, nemůžu použít
anotaci.
Je toto opravdu jediná možná cesta?
Pak je jeste nutne upravit hodnoty v tabulce SEQUENCE, protoze jinak
mohou
nasledujici em.persist(...) skoncit chybou "duplicitni hodnota
primarniho
klice".
Pokud ovsem id prideluje databaze (GenerationType.IDENTITY nebo
GenerationType.SEQUENCE), tak toto fungovat nebude, protoze sloupec id
muze byt v databazi deklarovan jako autoincrement a pak si pridelovani
hodnot ridi sama databaze.
Z.
--
Zdenek Tronicek
FIT CTU in Prague
Ondra Medek napsal(a):
Ja mam JPA nad Hibernate, a kdyz u entity nastavim setId(...) a pak
em.merge(entity), tak se mi ulozi s tim id, co jsem nastavil. Klice se
generuji jen pro nove entity. Funguje pro HSQLB a Oracle.
2010/10/18 Oto Buchta<[email protected]>:
Chci při instalaci nacpat do DB iniciální data a potřebuji, aby
některé záznamy typů s generovanými primárním klíčem měly
předdefinované hodnoty. Nemůžu ale nikde vygůglit jak na to.
Máte někdo nějakou ideu?
Dík.
--
Oto 'tapik' Buchta, [email protected], http://tapikuv.blogspot.com
--
Ondra Medek
--
Oto 'tapik' Buchta, [email protected], http://tapikuv.blogspot.com