Bruce Snyder wrote:
Christian Schuhegger wrote:
i've already had a look at: http://www.castor.org/key-generator.html but the key generator i would be interested in does not yet exist.
i would like to have a key generator that creates keys only if the key is not yet given in the object, e.g. if there is an id of type Integer, if the id is null then the key generator should create one and otherwise just use the given Integer as the key.
can anybody tell me how to achieve that?
thanks a lot for any infos!!
Christian,
You're correct that there are no key generators that provide this functionality. Care to contribute one?
Writing a key generator is not too difficult. Implement the KeyGeneratorFactory interface (http://www.castor.org/javadoc/org/exolab/castor/persist/spi/KeyGeneratorFactory.html), give the new key generator a unique name, list the new key generator in the castor.properties file as part of the org.exolab.castor.jdo.keyGeneratorFactories property.
actually the problem turned out to be much more complex than initially expected. as far as i have seen all current key generators are "global", e.g. they don't refer to data already in the object like if the object id is already existing.
currently my implementation relies on a modification of the SQLEngine, LockEngine and ClassMolder. especially my modification of the LockEngine i am not sure about? i removed the check for
newentry != null
this was necessary, because if i first try to look in the database if an object with that id already exists and then if it does not exist i create it the "lock cache" already contains the newentry and the exception was thrown.
i hand over the current identity of the object to the key generator by putting the identity into the prop collection:
prop.put("identity", identity);
it would be nice if somebody of the experts could have a look and tell me if you see some major problems with this attempt to implement such a MAXOrKeep key generator?
i put the patch to castor at:
http://cvs.sourceforge.net/viewcvs.py/ojts/OpenJavaTradingSystem/patches/
version 1.3 is the right one. (the anonymous cvs access needs some time to synchronize with the developer cvs version). this patch also contains other modifications i needed for my project.
the key generator can be found at: http://cvs.sourceforge.net/viewcvs.py/ojts/OpenJavaTradingSystem/src/net/sf/ojts/castor/persist/keygen/ as soon as the anonymous cvs has catched up with the developer cvs. -- Christian Schuhegger http://www.el-chef.de/
diff -rcNbB -x CVS castor-0.9.5.3-src-orig/src/main/org/exolab/castor/jdo/engine/SQLEngine.java castor-0.9.5.3-src/src/main/org/exolab/castor/jdo/engine/SQLEngine.java
*** castor-0.9.5.3-src-orig/src/main/org/exolab/castor/jdo/engine/SQLEngine.java 2004-02-13 22:37:18.000000000 +0100
--- castor-0.9.5.3-src/src/main/org/exolab/castor/jdo/engine/SQLEngine.java 2005-05-08 21:53:17.000000000 +0200
***************
*** 482,489 ****
*
* Result key will be in java type.
*/
! private Object generateKey( Database database, Object conn, PreparedStatement stmt ) throws PersistenceException {
! Object identity;
Connection connection;
Properties prop = null;
--- 482,488 ----
*
* Result key will be in java type.
*/
! private Object generateKey( Database database, Object conn, PreparedStatement stmt, Object identity ) throws PersistenceException {
Connection connection;
Properties prop = null;
***************
*** 493,505 ****
connection = getSeparateConnection( database );
}
- if (stmt != null) {
prop = new Properties();
prop.put("insertStatement", stmt);
}
synchronized (connection) {
! identity = _keyGen.generateKey( connection, _clsDesc.getTableName(),
! _ids[0].name, prop );
}
if ( identity == null )
--- 492,505 ----
connection = getSeparateConnection( database );
}
prop = new Properties();
+ if(null != identity)
+ prop.put("identity", identity);
+ if (stmt != null) {
prop.put("insertStatement", stmt);
}
synchronized (connection) {
! identity = _keyGen.generateKey( connection, _clsDesc.getTableName(), _ids[0].name, prop );
}
if ( identity == null )
***************
*** 529,535 ****
// Generate key before INSERT
else if ( _keyGen != null && _keyGen.getStyle() == KeyGenerator.BEFORE_INSERT )
! identity = generateKey( database, conn, null ); // genKey return identity in JDO type
if ( _keyGen != null && _keyGen.getStyle() == KeyGenerator.DURING_INSERT )
--- 529,535 ----
// Generate key before INSERT
else if ( _keyGen != null && _keyGen.getStyle() == KeyGenerator.BEFORE_INSERT )
! identity = generateKey( database, conn, null, identity ); // genKey return identity in JDO type
if ( _keyGen != null && _keyGen.getStyle() == KeyGenerator.DURING_INSERT )
***************
*** 614,620 ****
// Generate key after INSERT
if ( _keyGen != null && _keyGen.getStyle() == KeyGenerator.AFTER_INSERT ) {
! identity = generateKey( database, conn, stmt );
}
return identity;
--- 614,620 ----
// Generate key after INSERT
if ( _keyGen != null && _keyGen.getStyle() == KeyGenerator.AFTER_INSERT ) {
! identity = generateKey( database, conn, stmt, identity );
}
return identity;
diff -rcNbB -x CVS castor-0.9.5.3-src-orig/src/main/org/exolab/castor/persist/ClassMolder.java castor-0.9.5.3-src/src/main/org/exolab/castor/persist/ClassMolder.java
*** castor-0.9.5.3-src-orig/src/main/org/exolab/castor/persist/ClassMolder.java 2004-02-13 22:12:04.000000000 +0100
--- castor-0.9.5.3-src/src/main/org/exolab/castor/persist/ClassMolder.java 2005-05-08 21:49:34.000000000 +0200
***************
*** 909,916 ****
}
// ask Persistent to create the object into the persistence storage
! createdId = _persistence.create(tx.getDatabase(), (Connection)tx.getConnection(oid.getLockEngine()),
! fields, ids );
if ( createdId == null )
throw new PersistenceException("Identity can't be created!");
--- 909,916 ----
}
// ask Persistent to create the object into the persistence storage
! Object initids = getActualIdentity(tx, object);
! createdId = _persistence.create(tx.getDatabase(), (Connection)tx.getConnection(oid.getLockEngine()), fields, initids );
if ( createdId == null )
throw new PersistenceException("Identity can't be created!");
diff -rcNbB -x CVS castor-0.9.5.3-src-orig/src/main/org/exolab/castor/persist/LockEngine.java castor-0.9.5.3-src/src/main/org/exolab/castor/persist/LockEngine.java
*** castor-0.9.5.3-src-orig/src/main/org/exolab/castor/persist/LockEngine.java 2004-02-13 22:08:28.000000000 +0100
--- castor-0.9.5.3-src/src/main/org/exolab/castor/persist/LockEngine.java 2005-05-08 22:29:26.000000000 +0200
***************
*** 1308,1315 ****
throw new LockNotGrantedException("Lock to be renamed is not own exclusively by transaction!");
if ( entry.isEntered() )
throw new LockNotGrantedException("Lock to be renamed is being acquired by another transaction!");
! if ( newentry != null )
! throw new LockNotGrantedException("Lock is already existed for the new oid.");
entry = (ObjectLock) locks.remove( orgoid );
entry.setOID( newoid );
--- 1308,1318 ----
throw new LockNotGrantedException("Lock to be renamed is not own exclusively by transaction!");
if ( entry.isEntered() )
throw new LockNotGrantedException("Lock to be renamed is being acquired by another transaction!");
! if ( newentry != null ) {
! locks.remove( newentry );
! newentry = null;
! //throw new LockNotGrantedException("Lock is already existed for the new oid.");
! }
entry = (ObjectLock) locks.remove( orgoid );
entry.setOID( newoid );

