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