You are viewing a plain text version of this content. The canonical link for it is here.
Posted to ojb-dev@db.apache.org by ol...@apache.org on 2003/06/17 00:47:27 UTC
cvs commit: db-ojb/src/java/org/apache/ojb/otm/swizzle CopySwizzling.java Swizzling.java
olegnitz 2003/06/16 15:47:27
Modified: src/java/org/apache/ojb/otm OTMConnection.java
src/java/org/apache/ojb/otm/core BaseConnection.java
ConcreteEditingContext.java RequestContext.java
src/java/org/apache/ojb/otm/lock IsolationFactory.java
src/java/org/apache/ojb/otm/swizzle CopySwizzling.java
Swizzling.java
Log:
Implemented getIteratorByQuery() and invalidate() in OTMConnection
Revision Changes Path
1.5 +54 -16 db-ojb/src/java/org/apache/ojb/otm/OTMConnection.java
Index: OTMConnection.java
===================================================================
RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/otm/OTMConnection.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- OTMConnection.java 9 Jun 2003 18:55:26 -0000 1.4
+++ OTMConnection.java 16 Jun 2003 22:47:26 -0000 1.5
@@ -54,8 +54,10 @@
* <http://www.apache.org/>.
*/
+import java.util.Iterator;
import org.apache.ojb.broker.Identity;
import org.apache.ojb.broker.metadata.ClassDescriptor;
+import org.apache.ojb.broker.query.Query;
import org.apache.ojb.otm.lock.LockingException;
/**
@@ -69,20 +71,16 @@
/**
*
+ * Make the given object persistent by inserting it into the database.
+ * Also read locks the object (OTM will automatically lock
+ * it for write on transaction commit if the object will appear
+ * to be modified).
*
- *
- */
- public void invalidate(Identity oid);
-
- /**
- *
- * Make the given object persistent by inserting it into the database.
- *
- * @param object the object to be made persistent
+ * @param object the object to be made persistent
*
*/
public void makePersistent(Object object)
- throws LockingException;
+ throws LockingException;
/**
*
@@ -93,7 +91,7 @@
*
*/
public void deletePersistent(Object obj)
- throws LockingException;
+ throws LockingException;
/**
*
@@ -104,12 +102,13 @@
*
*/
public void lockForWrite(Object object)
- throws LockingException;
+ throws LockingException;
/**
*
* Get the object with the given Identity from the persistent store. By default, the fetch is
- * for read.
+ * for read. (OTM will automatically lock it for write on transaction commit
+ * if the object will appear to be modified).
*
* @param oid the Identity of the object to fetch
* @return the object from the persistent store.
@@ -118,7 +117,7 @@
*
*/
public Object getObjectByIdentity(Identity oid)
- throws LockingException;
+ throws LockingException;
/**
*
@@ -126,12 +125,38 @@
*
* @param oid the Identity of the object to fetch
* @param lock the lock that need to be acquired on the object
- * @return the object from the persistent store.
+ * Possible values are:
+ * LockType.NO_LOCK (aka read only) - changes to the object will not be written to database;
+ * LockType.READ_LOCK (aka optimistic lock) - changes to the object will be written to the database,
+ * in this case the lock will be automatically upgraded to the write lock on transaction commit;
+ * LockType.WRITE_LOCK (aka pessimistic lock) - changes to the object will be written to the database.
+ *
+ * @return the object from the persistent store.
* @throws LockingException thrown by the LockManager to avoid a deadlock.
*
*/
public Object getObjectByIdentity(Identity oid, int lock)
- throws LockingException;
+ throws LockingException;
+
+ /**
+ * @param query The query to execute
+ * @return an Iterator that iterates Objects of class c if calling the .next()
+ * method. The returned objects are locked for read.
+ */
+ public Iterator getIteratorByQuery(Query query);
+
+ /**
+ * @param query The query to execute
+ * @param lock the lock that need to be acquired on the object
+ * Possible values are:
+ * LockType.NO_LOCK (aka read only) - changes to the object will not be written to database;
+ * LockType.READ_LOCK (aka optimistic lock) - changes to the object will be written to the database,
+ * in this case the lock will be automatically upgraded to the write lock on transaction commit;
+ * LockType.WRITE_LOCK (aka pessimistic lock) - changes to the object will be written to the database.
+ * @return an Iterator that iterates Objects of class c if calling the .next()
+ * method. The returned objects are locked with the given lock value.
+ */
+ public Iterator getIteratorByQuery(Query query, int lock);
/**
* Get the identity of the object
@@ -152,4 +177,17 @@
*
*/
public EditingContext getEditingContext();
+
+ /**
+ * In the case if the program need to change the objects
+ * via direct JDBC call, it should first call invalidate()
+ * for the object, which will lock the object for write
+ * and tell OJB OTM that it must be re-read from the database,
+ * only after that you shold perform JDBC operation.
+ * NOTE: it is not recommended to use read-uncommitted isolation
+ * if you want this feature to work correctly.
+ */
+ public void invalidate(Identity oid)
+ throws LockingException;
+
}
1.10 +95 -44 db-ojb/src/java/org/apache/ojb/otm/core/BaseConnection.java
Index: BaseConnection.java
===================================================================
RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/otm/core/BaseConnection.java,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- BaseConnection.java 16 Jun 2003 16:17:56 -0000 1.9
+++ BaseConnection.java 16 Jun 2003 22:47:26 -0000 1.10
@@ -54,15 +54,19 @@
* <http://www.apache.org/>.
*/
+import java.util.Iterator;
import org.apache.ojb.broker.Identity;
import org.apache.ojb.broker.PBKey;
import org.apache.ojb.broker.PersistenceBroker;
+import org.apache.ojb.broker.accesslayer.OJBIterator;
import org.apache.ojb.broker.cache.ObjectCache;
-import org.apache.ojb.broker.metadata.ClassDescriptor;
import org.apache.ojb.broker.core.PersistenceBrokerImpl;
import org.apache.ojb.broker.core.PersistenceBrokerFactoryFactory;
+import org.apache.ojb.broker.metadata.ClassDescriptor;
+import org.apache.ojb.broker.query.Query;
import org.apache.ojb.otm.EditingContext;
import org.apache.ojb.otm.OTMConnection;
+import org.apache.ojb.otm.lock.LockManager;
import org.apache.ojb.otm.lock.LockType;
import org.apache.ojb.otm.lock.LockingException;
@@ -78,7 +82,7 @@
{
private PersistenceBroker _kernel;
- private Transaction _transaction;
+ private Transaction _tx;
private RequestContext _requestContext;
private ConcreteEditingContext _editingContext;
@@ -103,22 +107,22 @@
{
_editingContext = null;
}
- else if (_transaction != null)
+ else if (_tx != null)
{
throw new IllegalStateException(
"OTMConnection is already bound to the transactaction "
- + _transaction);
+ + _tx);
}
else
{
_editingContext = new ConcreteEditingContext(transaction, _kernel);
}
- _transaction = transaction;
+ _tx = transaction;
}
public Transaction getTransaction()
{
- return _transaction;
+ return _tx;
}
@@ -134,23 +138,8 @@
{
Object object;
- establishContext(lock);
-
- try
- {
- try
- {
- object = getKernelBroker().getObjectByIdentity(oid);
- }
- catch (LockingPassthruException lockingPassthruException)
- {
- throw lockingPassthruException.getLockingException();
- }
- }
- finally
- {
- releaseContext();
- }
+ object = _kernel.getObjectByIdentity(oid);
+ _editingContext.insert(oid, object, lock);
return object;
}
@@ -164,6 +153,33 @@
}
/**
+ * @param query The query to execute
+ * @return an Iterator that iterates Objects of class c if calling the .next()
+ * method. The returned objects are locked for read.
+ */
+ public Iterator getIteratorByQuery(Query query)
+ {
+ return getIteratorByQuery(query, LockType.READ_LOCK);
+ }
+
+ /**
+ * @param query The query to execute
+ * @param lock the lock that need to be acquired on the object
+ * Possible values are:
+ * LockType.NO_LOCK (aka read only) - changes to the object will not be written to database;
+ * LockType.READ_LOCK (aka optimistic lock) - changes to the object will be written to the database,
+ * in this case the lock will be automatically upgraded to the write lock on transaction commit;
+ * LockType.WRITE_LOCK (aka pessimistic lock) - changes to the object will be written to the database.
+ * @return an Iterator that iterates Objects of class c if calling the .next()
+ * method. The returned objects are locked with the given lock value.
+ */
+ public Iterator getIteratorByQuery(Query query, int lock)
+ {
+ return new LockingIterator(_kernel.getIteratorByQuery(query), lock);
+ }
+
+
+ /**
* Get the identity of the object
* @param object The object
* @return the identity of the object
@@ -187,7 +203,16 @@
* @see org.apache.ojb.otm.OTMConnection#invalidate(Identity)
*/
public void invalidate(Identity oid)
+ throws LockingException
{
+ LockManager lockManager = LockManager.getInstance();
+
+ // lock for write and mark as invalidated in the editing context
+ _editingContext.insert(oid, null, LockType.WRITE_LOCK);
+
+ // remove from the cache
+ _tx.getKit().getGlobalCache().evict(oid);
+
}
/**
@@ -246,7 +271,7 @@
* Prepare for a commit. As part of a two phase commit protocol of the transaction.
*
*/
- public abstract void transactionPrepare()
+ public abstract void transactionPrepare()
throws TransactionException;
/**
@@ -283,26 +308,6 @@
///////////////////////////////////////
- // Private Operations
- ///////////////////////////////////////
-
- private void establishContext(int lock)
- {
- if (_requestContext.isInUse())
- {
- throw new ConnectionException(
- "Cannot use a connection concurrently across multiple threads");
- }
- _requestContext.establishContext(lock);
- }
-
-
- private void releaseContext ()
- {
- _requestContext.releaseContext();
- }
-
- ///////////////////////////////////////
// Inner classes
///////////////////////////////////////
@@ -318,6 +323,52 @@
public void setObjectCache(ObjectCache cache)
{
objectCache = cache;
+ }
+ }
+
+ private class LockingIterator implements Iterator
+ {
+ private final Iterator _it;
+ private final int _lock;
+
+ LockingIterator(Iterator it, int lock)
+ {
+ _it = it;
+ _lock = lock;
+ }
+
+ public boolean hasNext()
+ {
+ boolean res = _it.hasNext();
+
+ // once the result set is finished, close it
+ if (!res && (_it instanceof OJBIterator))
+ {
+ ((OJBIterator) _it).releaseDbResources();
+ }
+
+ return res;
+ }
+
+ public Object next()
+ {
+ Object object;
+
+ object = _it.next();
+ try
+ {
+ _editingContext.insert(getIdentity(object), object, _lock);
+ }
+ catch (LockingException ex)
+ {
+ throw new LockingPassthruException(ex);
+ }
+ return object;
+ }
+
+ public void remove()
+ {
+ throw new UnsupportedOperationException();
}
}
}
1.13 +14 -23 db-ojb/src/java/org/apache/ojb/otm/core/ConcreteEditingContext.java
Index: ConcreteEditingContext.java
===================================================================
RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/otm/core/ConcreteEditingContext.java,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -r1.12 -r1.13
--- ConcreteEditingContext.java 16 Jun 2003 16:17:56 -0000 1.12
+++ ConcreteEditingContext.java 16 Jun 2003 22:47:26 -0000 1.13
@@ -163,12 +163,13 @@
LockManager lockManager = LockManager.getInstance();
Swizzling swizzlingStrategy = kit.getSwizzlingStrategy();
- // A similar or the same object is present in the context
+ // A similar or the same object is present in the context
Object oldObj = entry.object;
+
if (swizzlingStrategy.isSameInstance(oldObj, newObj))
{
- // The object in context is the same object attempted an insert on
- // Ensure we have the correct lock level
+ // The object in context is the same object attempted an insert on
+ // Ensure we have the correct lock level
lockManager.ensureLock(oid, _tx, lock, _pb);
}
else
@@ -178,13 +179,13 @@
entry.object = swizzlingStrategy.swizzle(newObj, oldObj, _pb);
}
}
-
+
if (!_order.contains(oid)) {
_order.add(oid);
// perform automatic read lock for all reachable objects
// if the inserted object is materialized
- if (kit.isImplicitLockingUsed())
+ if ((newObj != null) && kit.isImplicitLockingUsed())
{
IndirectionHandler handler = getIndirectionHandler(newObj);
@@ -232,23 +233,6 @@
return (entry == null ? null : entry.object);
}
- public Object getFromGlobalCache(Identity oid, int lock)
- throws LockingException
- {
- Object object = _tx.getKit().getGlobalCache().lookup(oid);
-
- if (object != null)
- {
- ContextEntry entry = (ContextEntry) _objects.get(oid);
-
- if (entry == null)
- {
- insertInternal(oid, object, lock);
- }
- }
-
- return object;
- }
//////////////////////////////////////////
// MaterializationListener interface
@@ -328,7 +312,14 @@
Identity oid = lockOrder[i];
ContextEntry entry = (ContextEntry) _objects.get(oid);
State state = entry.state;
- IndirectionHandler handler = getIndirectionHandler(entry.object);
+ IndirectionHandler handler;
+
+ if (entry.object == null) // invalidated
+ {
+ continue;
+ }
+
+ handler = getIndirectionHandler(entry.object);
if (handler == null || handler.alreadyMaterialized())
{
1.11 +9 -75 db-ojb/src/java/org/apache/ojb/otm/core/RequestContext.java
Index: RequestContext.java
===================================================================
RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/otm/core/RequestContext.java,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- RequestContext.java 16 Jun 2003 16:17:56 -0000 1.10
+++ RequestContext.java 16 Jun 2003 22:47:26 -0000 1.11
@@ -71,64 +71,13 @@
public class RequestContext
implements ObjectCache
{
- private BaseConnection _connection;
- private int _requestedLockType;
- private boolean _inUse;
+ private BaseConnection _conn;
- public RequestContext(BaseConnection connection)
+ public RequestContext(BaseConnection conn)
{
- _connection = connection;
- _inUse = false;
+ _conn = conn;
}
-
- /**
- *
- * Returns the connection.
- *
- * @return the connection in context
- *
- */
- public BaseConnection getConnection()
- {
- return _connection;
- }
-
- /**
- *
- * Returns the requestedLockType.
- *
- * @return the requested Lock type
- *
- */
- public int getRequestedLockType()
- {
- return _requestedLockType;
- }
-
- /**
- *
- * Establish that the RequestContext is in use.
- *
- * @param requestedLockType The requestedLockType to set
- */
- public void establishContext(int requestedLockType)
- {
- _requestedLockType = requestedLockType;
- _inUse = true;
- }
-
- public void releaseContext()
- {
- _inUse = false;
- }
-
- public boolean isInUse ()
- {
- return _inUse;
- }
-
-
//////////////////////////////////////////////
// ObjectCache protocol
//////////////////////////////////////////////
@@ -138,7 +87,7 @@
*/
public void cache(Identity oid, Object obj)
{
- OTMKit kit = _connection.getTransaction().getKit();
+ OTMKit kit = _conn.getTransaction().getKit();
kit.getGlobalCache().cache(oid, obj);
}
@@ -147,8 +96,8 @@
*/
public void clear()
{
- OTMKit kit = _connection.getTransaction().getKit();
- kit.getGlobalCache().evictAll();
+ OTMKit kit = _conn.getTransaction().getKit();
+ kit.getGlobalCache().evictAll();
}
/**
@@ -156,23 +105,8 @@
*/
public Object lookup(Identity oid)
{
- int lock = LockType.NO_LOCK;
- ConcreteEditingContext editingContext =
- (ConcreteEditingContext) _connection.getEditingContext();
-
- if (_inUse)
- {
- lock = _requestedLockType;
- }
-
- try
- {
- return editingContext.getFromGlobalCache(oid, lock);
- }
- catch (LockingException ex)
- {
- throw new LockingPassthruException(ex);
- }
+ OTMKit kit = _conn.getTransaction().getKit();
+ return kit.getGlobalCache().lookup(oid);
}
/**
@@ -180,7 +114,7 @@
*/
public void remove (Identity oid)
{
- OTMKit kit = _connection.getTransaction().getKit();
+ OTMKit kit = _conn.getTransaction().getKit();
kit.getGlobalCache().evict(oid);
}
}
1.9 +1 -1 db-ojb/src/java/org/apache/ojb/otm/lock/IsolationFactory.java
Index: IsolationFactory.java
===================================================================
RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/otm/lock/IsolationFactory.java,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- IsolationFactory.java 12 Jun 2003 17:28:13 -0000 1.8
+++ IsolationFactory.java 16 Jun 2003 22:47:27 -0000 1.9
@@ -108,7 +108,7 @@
break;
case IsolationLevels.IL_READ_COMMITTED:
- isolation = READ_UNCOMMITTED_ISOLATION;
+ isolation = READ_COMMITTED_ISOLATION;
break;
case IsolationLevels.IL_REPEATABLE_READ:
1.2 +5 -0 db-ojb/src/java/org/apache/ojb/otm/swizzle/CopySwizzling.java
Index: CopySwizzling.java
===================================================================
RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/otm/swizzle/CopySwizzling.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- CopySwizzling.java 12 Jun 2003 23:41:52 -0000 1.1
+++ CopySwizzling.java 16 Jun 2003 22:47:27 -0000 1.2
@@ -20,6 +20,11 @@
*/
public Object swizzle(Object newObj, Object oldObj, PersistenceBroker pb)
{
+ if (newObj == null) // invalidating
+ {
+ return null;
+ }
+
if (oldObj == null)
{
return newObj;
1.3 +8 -6 db-ojb/src/java/org/apache/ojb/otm/swizzle/Swizzling.java
Index: Swizzling.java
===================================================================
RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/otm/swizzle/Swizzling.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- Swizzling.java 12 Jun 2003 23:40:52 -0000 1.2
+++ Swizzling.java 16 Jun 2003 22:47:27 -0000 1.3
@@ -15,13 +15,15 @@
/**
*
- * Swizzle object references
+ * Swizzle object references.
*
- * @param newObj the object being inserted into the EditingContext
- * @param oldObj the object present in the EditingContext
- * @param pb the PersistenceBroker that is used to get
- * persistent class info
- * @return the Swizzled Object
+ * @param newObj the object being inserted into the EditingContext,
+ * is null if the object is being invalidated
+ * @param oldObj the object present in the EditingContext,
+ * is null if no object is present
+ * @param pb the PersistenceBroker that is used to get
+ * persistent class info
+ * @return the Swizzled Object
*
*/
public Object swizzle(Object newObj, Object oldObj, PersistenceBroker pb);