KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > oracle > toplink > essentials > internal > indirection > QueryBasedValueHolder


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the "License"). You may not use this file except
5  * in compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * glassfish/bootstrap/legal/CDDLv1.0.txt or
9  * https://glassfish.dev.java.net/public/CDDLv1.0.html.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * HEADER in each file and include the License file at
15  * glassfish/bootstrap/legal/CDDLv1.0.txt. If applicable,
16  * add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your
18  * own identifying information: Portions Copyright [yyyy]
19  * [name of copyright owner]
20  */

21 // Copyright (c) 1998, 2006, Oracle. All rights reserved.
22
package oracle.toplink.essentials.internal.indirection;
23
24 import oracle.toplink.essentials.queryframework.*;
25 import oracle.toplink.essentials.exceptions.*;
26 import oracle.toplink.essentials.internal.sessions.AbstractRecord;
27 import oracle.toplink.essentials.internal.sessions.AbstractSession;
28
29 /**
30  * QueryBasedValueHolder wraps a database-stored object and
31  * implements behavior to access it. The object is read from
32  * the database by invoking a user-specified query.
33  *
34  * @see ObjectLevelReadQuery
35  * @author Dorin Sandu
36  */

37 public class QueryBasedValueHolder extends DatabaseValueHolder {
38
39     /**
40      * Stores the query to be executed.
41      */

42     protected transient ReadQuery query;
43
44     /**
45      * Store the uow identity so that it can be used to determine new transaction logic
46      */

47     /**
48      * Initialize the query-based value holder.
49      */

50     public QueryBasedValueHolder(ReadQuery query, AbstractRecord row, AbstractSession session) {
51         this.row = row;
52         this.session = session;
53
54         // Make sure not to put a ClientSession or IsolatedClientSession in
55
// the shared cache (indirectly).
56
// Skip this if unitOfWork, for we use session.isUnitOfWork() to implement
57
// isTransactionalValueholder(), saving us from needing a boolean instance variable.
58
// If unitOfWork this safety measure is deferred until merge time with
59
// releaseWrappedValuehHolder.
60
// Note that if isolated session & query will return itself, which is safe
61
// for if isolated it will not go in the shared cache.
62
if (!session.isUnitOfWork()) {
63             this.session = session.getRootSession(query);
64         }
65         this.query = query;
66     }
67
68     /**
69      * Return the query.
70      */

71     protected ReadQuery getQuery() {
72         return query;
73     }
74
75     protected Object JavaDoc instantiate() throws DatabaseException {
76         return instantiate(getSession());
77     }
78
79     /**
80      * Instantiate the object by executing the query on the session.
81      */

82     protected Object JavaDoc instantiate(AbstractSession session) throws DatabaseException {
83         if (session == null){
84             throw ValidationException.instantiatingValueholderWithNullSession();
85         }
86         return session.executeQuery(getQuery(), getRow());
87     }
88
89     /**
90      * Triggers UnitOfWork valueholders directly without triggering the wrapped
91      * valueholder (this).
92      * <p>
93      * When in transaction and/or for pessimistic locking the UnitOfWorkValueHolder
94      * needs to be triggered directly without triggering the wrapped valueholder.
95      * However only the wrapped valueholder knows how to trigger the indirection,
96      * i.e. it may be a batchValueHolder, and it stores all the info like the row
97      * and the query.
98      * Note: This method is not thread-safe. It must be used in a synchronizaed manner
99      */

100     public Object JavaDoc instantiateForUnitOfWorkValueHolder(UnitOfWorkValueHolder unitOfWorkValueHolder) {
101         return instantiate(unitOfWorkValueHolder.getUnitOfWork());
102     }
103
104     /**
105      * Releases a wrapped valueholder privately owned by a particular unit of work.
106      * <p>
107      * When unit of work clones are built directly from rows no object in the shared
108      * cache points to this valueholder, so it can store the unit of work as its
109      * session. However once that UnitOfWork commits and the valueholder is merged
110      * into the shared cache, the session needs to be reset to the root session, ie.
111      * the server session.
112      */

113     public void releaseWrappedValueHolder() {
114         AbstractSession session = getSession();
115         if ((session != null) && session.isUnitOfWork()) {
116             setSession(session.getRootSession(query));
117         }
118     }
119
120     /**
121      * Reset all the fields that are not needed after instantiation.
122      */

123     protected void resetFields() {
124         super.resetFields();
125         setQuery(null);
126     }
127
128     /**
129      * Set the query.
130      */

131     protected void setQuery(ReadQuery theQuery) {
132         query = theQuery;
133     }
134
135     /**
136      * INTERNAL:
137      * Answers if this valueholder is a pessimistic locking one. Such valueholders
138      * are special in that they can be triggered multiple times by different
139      * UnitsOfWork. Each time a lock query will be issued. Hence even if
140      * instantiated it may have to be instantiated again, and once instantatiated
141      * all fields can not be reset.
142      * <p>
143      * Since locks will be issued each time this valueholder is triggered,
144      * triggering this directly on the session in auto commit mode will generate
145      * an exception. This only UnitOfWorkValueHolder's wrapping this can trigger
146      * it.
147      * Note: This method is not thread-safe. It must be used in a synchronizaed manner
148      */

149     public boolean isPessimisticLockingValueHolder() {
150         // Get the easy checks out of the way first.
151
if ((getQuery() == null) || !getQuery().isObjectLevelReadQuery()) {
152             return false;
153         }
154         ObjectLevelReadQuery query = (ObjectLevelReadQuery)getQuery();
155
156         // Note even if the reference class is not locked, but the valueholder query
157
// has joined attributes, then this may count as a lock query.
158
// This means it is possible to trigger a valueholder to get an object which
159
// is not to be pess. locked and get an exception for triggering it on the
160
// session outside a transaction.
161
return query.isLockQuery(getSession());
162     }
163 }
164
Popular Tags