You are viewing a plain text version of this content. The canonical link for it is here.
Posted to ojb-user@db.apache.org by Armin Waibel <ar...@code-au-lait.de> on 2003/09/20 16:29:41 UTC
Re: ODMG_Storing new object afer deleting one with ms sql 2000, LockNotGrantedException
Hi Ralf,
sorry for late reply.
Identity columns are evil!! ;-)
The problem is that OJB has its own Identity-object
concept (see Identity.java class). This allows OJB to
generate unique identity-objects for any given persistence
capable class instance BEFORE the object was stored to
database using the SequenceManager - that's the crux of
the matter.
I checked in a workaround for storing-problems
using odmg-api and SequenceManagerNativeImpl.
regards,
Armin
----- Original Message -----
From: <r....@orgacard.de>
To: <oj...@db.apache.org>
Sent: Thursday, September 11, 2003 3:30 PM
Subject: ODMG_Storing new object afer deleting one with ms sql 2000,
LockNotGrantedException
> Hallo,
>
> I'm using db-ojb-1.0.rc4 with Microsoft SQL Server 2000.
> Look at my OJB.properties file.
> repositoryFile=repository.xml
> useSerializedRepository=false
> serializedRepositoryPath=.
>
PersistenceBrokerFactoryClass=org.apache.ojb.broker.core.PersistenceBrok
erFactoryDefaultImpl
>
PersistenceBrokerClass=org.apache.ojb.broker.core.PersistenceBrokerImpl
> maxActive=100
> maxIdle=-1
> maxWait=2000
> timeBetweenEvictionRunsMillis=-1
> minEvictableIdleTimeMillis=1000000
> whenExhaustedAction=0
>
ConnectionFactoryClass=org.apache.ojb.broker.accesslayer.ConnectionFacto
ryPooledImpl
>
ConnectionManagerClass=org.apache.ojb.broker.accesslayer.ConnectionManag
erImpl
>
SqlGeneratorClass=org.apache.ojb.broker.accesslayer.sql.SqlGeneratorDefa
ultImpl
>
StatementManagerClass=org.apache.ojb.broker.accesslayer.StatementManager
>
StatementsForClassClass=org.apache.ojb.broker.accesslayer.StatementsForC
lassImpl
> JdbcAccessClass=org.apache.ojb.broker.accesslayer.JdbcAccessImpl
> ObjectCacheClass=org.apache.ojb.broker.cache.ObjectCacheEmptyImpl
> LockManagerClass=org.apache.ojb.odmg.locking.LockManagerDefaultImpl
> LockMapClass=org.apache.ojb.odmg.locking.InMemoryLockMapImpl
> LockTimeout=60000
> ImplicitLocking=true
> LockAssociations=WRITE
>
OqlCollectionClass=org.apache.ojb.broker.util.collections.ManageableArra
yList
> SqlInLimit=200
>
PersistentFieldClass=org.apache.ojb.broker.metadata.fieldaccess.Persiste
ntFieldIntrospectorImpl
> OJBTxManagerClass=org.apache.ojb.odmg.LocalTxManager
>
JTATransactionManagerClass=org.apache.ojb.odmg.transaction.JBossTransact
ionManagerFactory
>
> The id fields are identity columns. I'm using the plattform
myMsSQLServer. This class extends the PlatformMsSQLServerImpl, so
getting the last id works with the SequenceManagerNativeImpl.
> public class PlatformmyMsSQLServerImpl extends PlatformMsSQLServerImpl
> {
> private static final String LAST_INSERT = "SELECT
IDENT_CURRENT(''{0}'') ";
> public String getLastInsertIdentityQuery(String tableName)
> {
> String msg = LAST_INSERT;
> Object[] arguments = { tableName.toUpperCase() };
> msg = MessageFormat.format( msg, arguments );
> return msg;
> }
> }
>
> If i use the PlatformMsSQLServerImpl the following exception occurs.
> java.lang.UnsupportedOperationException: This feature is not supported
by this implementation
> at
org.apache.ojb.broker.platforms.PlatformDefaultImpl.getLastInsertIdentit
yQuery(Unknown Source)
> at
org.apache.ojb.broker.util.sequence.SequenceManagerNativeImpl.lastInsert
Select(Unknown Source)
> at
org.apache.ojb.broker.util.sequence.SequenceManagerNativeImpl.getLastIns
ert(Unknown Source)
> at
org.apache.ojb.broker.util.sequence.SequenceManagerNativeImpl.afterStore
(Unknown Source)
> at org.apache.ojb.broker.core.PersistenceBrokerImpl.storeToDb(Unknown
Source)
> at org.apache.ojb.broker.core.PersistenceBrokerImpl.store(Unknown
Source)
> at org.apache.ojb.broker.core.PersistenceBrokerImpl.store(Unknown
Source)
> at
org.apache.ojb.broker.core.DelegatingPersistenceBroker.store(Unknown
Source)
> at
org.apache.ojb.broker.core.DelegatingPersistenceBroker.store(Unknown
Source)
> at org.apache.ojb.odmg.states.StateNewDirty.commit(Unknown Source)
> at org.apache.ojb.odmg.ObjectEnvelopeTable.commitAllEnvelopes(Unknown
Source)
> at org.apache.ojb.odmg.ObjectEnvelopeTable.commit(Unknown Source)
> at org.apache.ojb.odmg.TransactionImpl.doCommitOnObjects(Unknown
Source)
> at org.apache.ojb.odmg.TransactionImpl.prepare(Unknown Source)
> at org.apache.ojb.odmg.TransactionImpl.commit(Unknown Source)
>
> Look at the repository
> <jdbc-connection-descriptor
> jcd-alias="mydb"
> default-connection="true"
> platform="myMsSQLServer"
> jdbc-level="2.0"
> driver="com.microsoft.jdbc.sqlserver.SQLServerDriver"
> protocol="jdbc"
> subprotocol="microsoft:sqlserver"
> dbalias="//localhost:1433;DatabaseName=test;SelectMethod=cursor"
> username="user"
> password="pwd"
> eager-release="false"
> batch-mode="false"
> useAutoCommit="1"
> ignoreAutoCommitExceptions="false"
> >
> <sequence-manager
className="org.apache.ojb.broker.util.sequence.SequenceManagerNativeImpl
">
> </sequence-manager>
> </jdbc-connection-descriptor>
>
> <class-descriptor
> class="bo.Dislike"
> table="ABNEIG"
> >
> <field-descriptor id="1"
> name="id"
> column="abid"
> jdbc-type="INTEGER"
> primarykey="true"
> autoincrement="true"
> access="readonly"
> />
> <field-descriptor id="2"
> name="description"
> column="bez"
> jdbc-type="VARCHAR"
>
conversion="org.apache.ojb.broker.accesslayer.conversions.BlankString2Nu
llFieldConversion"
> access="readwrite"
> />
> <field-descriptor id="3"
> name="shortdescription"
> column="kbez"
> jdbc-type="VARCHAR"
>
conversion="org.apache.ojb.broker.accesslayer.conversions.BlankString2Nu
llFieldConversion"
> access="readwrite"
> />
> </class-descriptor>
>
> The value objects id is initialized with -1. After the insert is done,
the object has the right id.
>
> If I use Dlist
(OqlCollectionClass=org.apache.ojb.odmg.collections.DListImpl) I get the
exception:
> java.lang.NullPointerException
> at
org.apache.ojb.broker.util.sequence.AbstractSequenceManager.getUniqueVal
ue(Unknown Source)
> at org.apache.ojb.odmg.collections.DListImpl.generateNewId(Unknown
Source)
> at org.apache.ojb.odmg.collections.DListImpl.getId(Unknown Source)
> at org.apache.ojb.odmg.collections.DListEntry.<init>(Unknown Source)
> at org.apache.ojb.odmg.collections.DListImpl.ojbAdd(Unknown Source)
> at
org.apache.ojb.broker.core.PersistenceBrokerImpl.getCollectionByQuery(Un
known Source)
> at
org.apache.ojb.broker.core.PersistenceBrokerImpl.getCollectionByQuery(Un
known Source)
> at
org.apache.ojb.broker.core.PersistenceBrokerImpl.getCollectionByQuery(Un
known Source)
> at
org.apache.ojb.broker.core.DelegatingPersistenceBroker.getCollectionByQu
ery(Unknown Source)
> at
org.apache.ojb.broker.core.DelegatingPersistenceBroker.getCollectionByQu
ery(Unknown Source)
> at org.apache.ojb.odmg.oql.OQLQueryImpl.execute(Unknown Source)
>
> So, I switched to ManageableArrayList
(OqlCollectionClass=org.apache.ojb.broker.util.collections.ManageableArr
ayList).
> I get one exception in section "file://creating new object after
deleting" process instruction tx.lock(dislike, TransactionImpl.WRITE).
> org.odmg.LockNotGrantedException: Can not lock bo.Dislike@2fb0af [-1]
for WRITE
> at org.apache.ojb.odmg.TransactionImpl.lock(Unknown Source)
>
> Explain the two used objects in this test case.
> Dislike
> The object stores in database, with additional methods. This object
extends DislikeValue. Giving the value in the constructor of this
object, all values are copied to this object.
>
> DislikeValue
> The getter and setter for the table.
>
> Here is the test case.
> package test;
> import junit.framework.TestCase;
> import org.apache.ojb.broker.util.collections.ManageableArrayList;
> import org.apache.ojb.odmg.OJB;
> import org.apache.ojb.odmg.TransactionImpl;
> import org.odmg.Database;
> import org.odmg.Implementation;
> import org.odmg.ODMGException;
> import org.odmg.OQLQuery;
> import org.odmg.Transaction;
> import bo.Dislike;
> import vo.DislikeValue;
>
> public class OJBTest extends TestCase
> {
> private static Implementation myOdmg = null;
> private static Database myDb = null;
>
> public OJBTest(String arg0)
> {
> super(arg0);
> }
>
> public static void main(String[] args)
> {
> junit.swingui.TestRunner.run(DislikeFactoryTest.class);
> }
>
> protected void setUp() throws Exception
> {
> super.setUp();
> }
>
> protected void tearDown() throws Exception
> {
> super.tearDown();
> }
>
> final public void testODMGAccess() {
> if ( myOdmg == null )
> myOdmg = OJB.getInstance();
> // get odmg facade instance
> if ( myDb == null ) {
> myDb = myOdmg.newDatabase();
> file://open database
> try
> {
> myDb.open( "mydb", Database.OPEN_READ_WRITE );
> System.out.println( "myDb.open=" + myDb );
> }
> catch (ODMGException ex)
> {
> ex.printStackTrace();
> }
> }
> if ( myDb == null )
> assertTrue( "database not opened", false );
>
> DislikeValue value = new DislikeValue();
> value.setDescription( "TestEntry" );
> value.setShortdescription( "TestEntry" );
> Dislike dislike = null;
> Transaction tx = null;
> try {
> file://creating new database object
> dislike = new Dislike( value );
> file://open transaction
> tx = myOdmg.newTransaction();
> tx.begin();
> file://acquire write lock on new object
> tx.lock(dislike, TransactionImpl.WRITE);
> file://commiting transaction
> tx.commit();
> } catch( Exception lnge ) {
> lnge.printStackTrace();
> file://rollback the transaction
> tx.abort();
> }
> file://check for id > 0
> if ( dislike.getId() < 1 )
> assertTrue( "id is not set. id=" + dislike.getId(), false );
> file://save id
> int id = dislike.getId();
> file://edit
> file://getting object from database
> String oqlQuery = "select del from " +
> Dislike.class.getName() +
> " where id = " + id;
> dislike = null;
> try {
> OQLQuery query = myOdmg.newOQLQuery();
> query.create(oqlQuery);
> file://DList result = (DList) query.execute();
> ManageableArrayList result = (ManageableArrayList)query.execute();
> dislike = (Dislike) result.get(0);
> file://open transaction
> tx = myOdmg.newTransaction();
> tx.begin();
> file://acquire write lock on new object
> tx.lock( dislike, TransactionImpl.WRITE );
> value.setDescription( "Test" );
> value.setShortdescription( "Test" );
> file://commiting transaction
> tx.commit();
> } catch( Exception lnge ) {
> lnge.printStackTrace();
> file://rollback the transaction
> tx.abort();
> }
> file://check for presence
> if ( dislike == null )
> assertTrue( "dislike not found. id=" + id, false );
> file://delete
> try {
> file://open transaction
> tx = myOdmg.newTransaction();
> tx.begin();
> myDb.deletePersistent( dislike );
> file://commiting transaction
> tx.commit();
> } catch( Exception lnge ) {
> lnge.printStackTrace();
> file://rollback the transaction
> tx.abort();
> }
> file://check for delete
> try {
> OQLQuery query = myOdmg.newOQLQuery();
> query.create(oqlQuery);
> file://DList result = (DList) query.execute();
> ManageableArrayList result = (ManageableArrayList)query.execute();
> if ( result.size() > 0 )
> dislike = (Dislike) result.get(0);
> else
> dislike = null;
> } catch( Exception lnge ) {
> lnge.printStackTrace();
> }
> if ( dislike != null )
> assertTrue( "dislike not deleted. id=" + id, false );
> file://storing new one
> value = new DislikeValue();
> value.setDescription( "TestEntry" );
> value.setShortdescription( "TestEntry" );
> file://creating new object after deleting
> try {
> file://creating new database object
> dislike = new Dislike( value );
> file://open transaction
> tx = myOdmg.newTransaction();
> tx.begin();
> file://acquire write lock on new object
> tx.lock(dislike, TransactionImpl.WRITE);
> file://commiting transaction
> tx.commit();
> } catch( Exception lnge ) {
> lnge.printStackTrace();
> file://rollback the transaction
> tx.abort();
> }
> file://check for id > 0
> if ( dislike.getId() < 1 )
> assertTrue( "id is not set. id=" + dislike.getId(), false );
> file://delete
> try {
> file://open transaction
> tx = myOdmg.newTransaction();
> tx.begin();
> myDb.deletePersistent( dislike );
> file://commiting transaction
> tx.commit();
> } catch( Exception lnge ) {
> file://rollback the transaction
> tx.abort();
> lnge.printStackTrace();
> }
> file://check for delete
> try {
> OQLQuery query = myOdmg.newOQLQuery();
> query.create(oqlQuery);
> file://DList result = (DList) query.execute();
> ManageableArrayList result = (ManageableArrayList)query.execute();
> if ( result.size() > 0 )
> dislike = (Dislike) result.get(0);
> else
> dislike = null;
> } catch( Exception lnge ) {
> lnge.printStackTrace();
> }
> assertTrue( "dislike not deleted. id=" + id, false );
> }
> file://second test
> final public void testODMGStoreTwice() {
> if ( myDb == null )
> assertTrue( "database not opened", false );
> DislikeValue value = new DislikeValue();
> value.setDescription( "TestEntry1" );
> value.setShortdescription( "TestEntry1" );
> Dislike dislike1 = null;
> Transaction tx = null;
> try {
> dislike1 = new Dislike( value );
> tx = myOdmg.newTransaction();
> tx.begin();
> tx.lock(dislike1, TransactionImpl.WRITE);
> tx.commit();
> } catch( Exception lnge ) {
> lnge.printStackTrace();
> tx.abort();
> }
> if ( dislike1.getId() < 1 )
> assertTrue( "id is not set. id=" + dislike1.getId(), false );
> value = new DislikeValue();
> value.setDescription( "TestEntry2" );
> value.setShortdescription( "TestEntry2" );
> Dislike dislike2 = null;
> tx = null;
> try {
> dislike2 = new Dislike( value );
> tx = myOdmg.newTransaction();
> tx.begin();
> tx.lock(dislike2, TransactionImpl.WRITE);
> tx.commit();
> } catch( Exception lnge ) {
> lnge.printStackTrace();
> tx.abort();
> }
> if ( dislike2.getId() < 1 )
> assertTrue( "id is not set. id=" + dislike2.getId(), false );
> }
> }
>
> I've integrated an second test case for storing two objects
(testODMGStoreTwice). During process the lock method of the second
object the exception is thrown.
> org.odmg.LockNotGrantedException: Can not lock bo.Dislike@c18a4c [-1]
for WRITE
> at org.apache.ojb.odmg.TransactionImpl.lock(Unknown Source)
> at test.OJBTest.testODMGStoreTwice(OJBTest.java:129)
> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.jav
a:39)
> at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessor
Impl.java:25)
> at java.lang.reflect.Method.invoke(Method.java:324)
>
> If I use another cache implementation, e. g.
ObjectCacheClass=org.apache.ojb.broker.cache.ObjectCacheDefaultImpl, the
same exceptiona are thrown in the two test cases.
>
> When I'm using the SequenceManagerNextValImpl, all seems to be all
right, but the value of the id is not updated. It is allways -1. I've to
set the id after reading the id from database with the setId() methode,
otherwise deleting of this objects is not possible.
> <sequence-manager
className="org.apache.ojb.broker.util.sequence.SequenceManagerNextValImp
l">
> <attribute attribute-name="autoNaming"
attribute-value="true"/>
> </sequence-manager>
>
> Does everyone has experience using MS Access Database with counter
fields? I think it's the same problem like ms sql server, with database
generated ids using a data type.
>
> Thanks for suggestions.
> Ralf
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: ojb-user-unsubscribe@db.apache.org
> For additional commands, e-mail: ojb-user-help@db.apache.org
>
>
---------------------------------------------------------------------
To unsubscribe, e-mail: ojb-user-unsubscribe@db.apache.org
For additional commands, e-mail: ojb-user-help@db.apache.org