KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > ejb > plugins > cmp > jdbc > JDBCLoadEntityCommand


1 /*
2 * JBoss, Home of Professional Open Source
3 * Copyright 2005, JBoss Inc., and individual contributors as indicated
4 * by the @authors tag. See the copyright.txt in the distribution for a
5 * full listing of individual contributors.
6 *
7 * This is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation; either version 2.1 of
10 * the License, or (at your option) any later version.
11 *
12 * This software is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this software; if not, write to the Free
19 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21 */

22 package org.jboss.ejb.plugins.cmp.jdbc;
23
24 import java.sql.Connection JavaDoc;
25 import java.sql.PreparedStatement JavaDoc;
26 import java.sql.ResultSet JavaDoc;
27 import java.util.List JavaDoc;
28 import javax.ejb.EJBException JavaDoc;
29 import javax.ejb.NoSuchEntityException JavaDoc;
30
31 import org.jboss.ejb.EntityEnterpriseContext;
32 import org.jboss.ejb.plugins.cmp.jdbc.bridge.JDBCFieldBridge;
33 import org.jboss.ejb.plugins.cmp.jdbc.bridge.JDBCCMPFieldBridge;
34 import org.jboss.ejb.plugins.cmp.jdbc.bridge.JDBCEntityBridge;
35 import org.jboss.ejb.plugins.cmp.jdbc.metadata.JDBCFunctionMappingMetaData;
36 import org.jboss.logging.Logger;
37 import org.jboss.deployment.DeploymentException;
38
39 /**
40  * JDBCLoadEntityCommand loads the data for an instance from the table.
41  * This command implements specified eager loading. For CMP 2.x, the
42  * entity can be configured to only load some of the fields, which is
43  * helpful for entitys with lots of data.
44  *
45  * @author <a HREF="mailto:dain@daingroup.com">Dain Sundstrom</a>
46  * @author <a HREF="mailto:on@ibis.odessa.ua">Oleg Nitz</a>
47  * @author <a HREF="mailto:rickard.oberg@telkel.com">Rickard �berg</a>
48  * @author <a HREF="mailto:marc.fleury@telkel.com">Marc Fleury</a>
49  * @author <a HREF="mailto:shevlandj@kpi.com.au">Joe Shevland</a>
50  * @author <a HREF="mailto:justin@j-m-f.demon.co.uk">Justin Forder</a>
51  * @author <a HREF="mailto:dirk@jboss.de">Dirk Zimmermann</a>
52  * @author <a HREF="mailto:danch@nvisia.com">danch (Dan Christopherson)</a>
53  * @author <a HREF="mailto:alex@jboss.org">Alexey Loubyansky</a>
54  * @version $Revision: 37459 $
55  */

56 public final class JDBCLoadEntityCommand
57 {
58    private final JDBCStoreManager manager;
59    private final JDBCEntityBridge entity;
60    private final Logger log;
61    private final JDBCFunctionMappingMetaData rowLockingTemplate;
62
63    public JDBCLoadEntityCommand(JDBCStoreManager manager) throws DeploymentException
64    {
65       this.manager = manager;
66       entity = (JDBCEntityBridge) manager.getEntityBridge();
67       boolean rowLocking = entity.getMetaData().hasRowLocking();
68       rowLockingTemplate = rowLocking ? entity.getMetaData().getTypeMapping().getRowLockingTemplate() : null;
69
70       // Create the Log
71
log = Logger.getLogger(
72               this.getClass().getName() +
73               "." +
74               manager.getMetaData().getName());
75    }
76
77    /**
78     * Loads entity.
79     * If failIfNotFound is true and entity wasn't found then NoSuchEntityException is thrown.
80     * Otherwise, if entity wasn't found, returns false.
81     * If entity was loaded successfully return true.
82     * @param ctx - entity context;
83     * @param failIfNotFound - whether to fail if entity wasn't found;
84     * @return true if entity was loaded, false - otherwise.
85     */

86    public boolean execute(EntityEnterpriseContext ctx, boolean failIfNotFound)
87    {
88       return execute(null, ctx, failIfNotFound);
89    }
90
91    /**
92     * Loads entity or required field. If entity not found throws NoSuchEntityException.
93     * @param requiredField - required field or null;
94     * @param ctx - the corresponding context;
95     */

96    public void execute(JDBCCMPFieldBridge requiredField, EntityEnterpriseContext ctx)
97    {
98       execute(requiredField, ctx, true);
99    }
100
101
102    /**
103     * Loads entity or required field.
104     * If failIfNotFound is set to true, then NoSuchEntityException is thrown if the
105     * entity wasn't found.
106     * If failIfNotFound is false then if the entity wasn't found returns false,
107     * if the entity was loaded successfully, returns true.
108     * @param requiredField - required field;
109     * @param ctx - entity context;
110     * @param failIfNotFound - whether to fail if entity wasn't loaded.
111     * @return true if entity was loaded, false - otherwise.
112     */

113    private boolean execute(JDBCCMPFieldBridge requiredField,
114                            EntityEnterpriseContext ctx,
115                            boolean failIfNotFound)
116    {
117       // load the instance primary key fields into the context
118
Object JavaDoc id = ctx.getId();
119       // TODO: when exactly do I need to do the following?
120
entity.injectPrimaryKeyIntoInstance(ctx, id);
121
122       // get the read ahead cache
123
ReadAheadCache readAheadCache = manager.getReadAheadCache();
124
125       // load any preloaded fields into the context
126
if(readAheadCache.load(ctx))
127       {
128          if(requiredField == null || (requiredField != null && requiredField.isLoaded(ctx)))
129          {
130             return true;
131          }
132       }
133
134       // get the finder results associated with this context, if it exists
135
ReadAheadCache.EntityReadAheadInfo info = readAheadCache.getEntityReadAheadInfo(id);
136
137       // determine the fields to load
138
JDBCEntityBridge.FieldIterator loadIter = entity.getLoadIterator(requiredField, info.getReadAhead(), ctx);
139       if(!loadIter.hasNext())
140          return true;
141
142       // get the keys to load
143
List JavaDoc loadKeys = info.getLoadKeys();
144
145       // generate the sql
146
String JavaDoc sql = (rowLockingTemplate != null ? getRawLockingSQL(loadIter, loadKeys.size()) : getSQL(loadIter, loadKeys.size()));
147
148       Connection JavaDoc con = null;
149       PreparedStatement JavaDoc ps = null;
150       ResultSet JavaDoc rs = null;
151       try
152       {
153          // create the statement
154
if (log.isDebugEnabled())
155          {
156             log.debug("Executing SQL: " + sql);
157          }
158
159          // get the connection
160
con = entity.getDataSource().getConnection();
161          ps = con.prepareStatement(sql);
162
163          // Set the fetch size of the statement
164
if (entity.getFetchSize() > 0)
165          {
166             ps.setFetchSize(entity.getFetchSize());
167          }
168
169          // set the parameters
170
int paramIndex = 1;
171          for (int i = 0; i < loadKeys.size(); i++)
172          {
173             paramIndex = entity.setPrimaryKeyParameters(ps, paramIndex, loadKeys.get(i));
174          }
175
176          // execute statement
177
rs = ps.executeQuery();
178
179          // load results
180
boolean mainEntityLoaded = false;
181          Object JavaDoc[] ref = new Object JavaDoc[1];
182          while (rs.next())
183          {
184             // reset the column index for this row
185
int index = 1;
186
187             // ref must be reset to null before load
188
ref[0] = null;
189
190             // if we are loading more then one entity, load the pk from the row
191
Object JavaDoc pk = null;
192             if (loadKeys.size() > 1)
193             {
194                // load the pk
195
index = entity.loadPrimaryKeyResults(rs, index, ref);
196                pk = ref[0];
197             }
198
199             // is this the main entity or a preload entity
200
if (loadKeys.size() == 1 || pk.equals(id))
201             {
202                // main entity; load the values into the context
203
loadIter.reset();
204                while(loadIter.hasNext())
205                {
206                   JDBCCMPFieldBridge field = loadIter.next();
207                   index = field.loadInstanceResults(rs, index, ctx);
208                   field.setClean(ctx);
209                }
210                mainEntityLoaded = true;
211             }
212             else
213             {
214                // preload entity; load the values into the read ahead cahce
215
loadIter.reset();
216                while(loadIter.hasNext())
217                {
218                   JDBCCMPFieldBridge field = loadIter.next();
219                   // ref must be reset to null before load
220
ref[0] = null;
221
222                   // load the result of the field
223
index = field.loadArgumentResults(rs, index, ref);
224
225                   // cache the field value
226
readAheadCache.addPreloadData(pk, field, ref[0]);
227                }
228             }
229          }
230
231          // clear LOAD_REQUIRED flag
232
loadIter.removeAll();
233
234          // did we load the main results
235
if (!mainEntityLoaded)
236          {
237             if (failIfNotFound)
238                throw new NoSuchEntityException JavaDoc("Entity not found: primaryKey=" + ctx.getId());
239             else
240                return false;
241          }
242          else
243             return true;
244       }
245       catch (EJBException JavaDoc e)
246       {
247          throw e;
248       }
249       catch (Exception JavaDoc e)
250       {
251          throw new EJBException JavaDoc("Load failed", e);
252       }
253       finally
254       {
255          JDBCUtil.safeClose(rs);
256          JDBCUtil.safeClose(ps);
257          JDBCUtil.safeClose(con);
258       }
259    }
260
261    private String JavaDoc getSQL(JDBCEntityBridge.FieldIterator loadIter, int keyCount)
262    {
263       StringBuffer JavaDoc sql = new StringBuffer JavaDoc(250);
264       sql.append(SQLUtil.SELECT);
265
266       // if we are loading more then one entity we need to add the primry
267
// key to the load fields to match up the results with the correct entity.
268
JDBCFieldBridge[] primaryKeyFields = entity.getPrimaryKeyFields();
269       if (keyCount > 1)
270       {
271          SQLUtil.getColumnNamesClause(primaryKeyFields, sql);
272          sql.append(SQLUtil.COMMA);
273       }
274       SQLUtil.getColumnNamesClause(loadIter, sql);
275       sql.append(SQLUtil.FROM)
276               .append(entity.getQualifiedTableName())
277               .append(SQLUtil.WHERE);
278
279       //
280
// where clause
281
String JavaDoc pkWhere = SQLUtil.getWhereClause(primaryKeyFields, new StringBuffer JavaDoc(50)).toString();
282       sql.append('(').append(pkWhere).append(')');
283       for (int i = 1; i < keyCount; i++)
284       {
285          sql.append(SQLUtil.OR).append('(').append(pkWhere).append(')');
286       }
287
288       return sql.toString();
289    }
290
291    private String JavaDoc getRawLockingSQL(JDBCEntityBridge.FieldIterator loadIter, int keyCount)
292    {
293       //
294
// column names clause
295
StringBuffer JavaDoc columnNamesClause = new StringBuffer JavaDoc(250);
296       // if we are loading more then one entity we need to add the primry
297
// key to the load fields to match up the results with the correct
298
// entity.
299
if (keyCount > 1)
300       {
301          SQLUtil.getColumnNamesClause(entity.getPrimaryKeyFields(), columnNamesClause);
302          columnNamesClause.append(SQLUtil.COMMA);
303       }
304
305       SQLUtil.getColumnNamesClause(loadIter, columnNamesClause);
306
307       //
308
// table name clause
309
String JavaDoc tableName = entity.getQualifiedTableName();
310
311       //
312
// where clause
313
String JavaDoc whereClause = SQLUtil.
314               getWhereClause(entity.getPrimaryKeyFields(), new StringBuffer JavaDoc(50)).toString();
315       if (keyCount > 0)
316       {
317          StringBuffer JavaDoc sb = new StringBuffer JavaDoc((whereClause.length() + 6) * keyCount + 4);
318          for (int i = 0; i < keyCount; i++)
319          {
320             if (i > 0)
321                sb.append(SQLUtil.OR);
322             sb.append('(').append(whereClause).append(')');
323          }
324          whereClause = sb.toString();
325       }
326
327       String JavaDoc[] args = new String JavaDoc[]{
328          columnNamesClause.toString(),
329          tableName,
330          whereClause,
331          null // order by
332
};
333       return rowLockingTemplate.getFunctionSql(args, new StringBuffer JavaDoc(300)).toString();
334    }
335 }
336
Popular Tags