KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > ejb > plugins > cmp > jdbc2 > schema > RelationTable


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.jdbc2.schema;
23
24 import org.jboss.ejb.plugins.cmp.jdbc2.bridge.JDBCCMRFieldBridge2;
25 import org.jboss.ejb.plugins.cmp.jdbc2.bridge.JDBCCMPFieldBridge2;
26 import org.jboss.ejb.plugins.cmp.jdbc.metadata.JDBCRelationMetaData;
27 import org.jboss.ejb.plugins.cmp.jdbc.SQLUtil;
28 import org.jboss.ejb.plugins.cmp.jdbc.JDBCUtil;
29 import org.jboss.deployment.DeploymentException;
30 import org.jboss.logging.Logger;
31
32 import javax.sql.DataSource JavaDoc;
33 import javax.transaction.Transaction JavaDoc;
34 import java.sql.SQLException JavaDoc;
35 import java.sql.Connection JavaDoc;
36 import java.sql.PreparedStatement JavaDoc;
37
38 /**
39  * @author <a HREF="mailto:alex@jboss.org">Alexey Loubyansky</a>
40  * @version <tt>$Revision: 37459 $</tt>
41  */

42 public class RelationTable
43    implements Table
44 {
45    private static final byte CREATED = 1;
46    private static final byte DELETED = 2;
47
48    private final Schema schema;
49    private final int tableId;
50    private final DataSource JavaDoc ds;
51    private final String JavaDoc tableName;
52    private final JDBCCMRFieldBridge2 leftField;
53    private final JDBCCMRFieldBridge2 rightField;
54    private final Logger log;
55
56    private String JavaDoc insertSql;
57    private String JavaDoc deleteSql;
58
59    public RelationTable(JDBCCMRFieldBridge2 leftField, JDBCCMRFieldBridge2 rightField, Schema schema, int tableId)
60       throws DeploymentException
61    {
62       this.schema = schema;
63       this.tableId = tableId;
64       this.leftField = leftField;
65       this.rightField = rightField;
66
67       JDBCRelationMetaData metadata = leftField.getMetaData().getRelationMetaData();
68       ds = metadata.getDataSource();
69       tableName = SQLUtil.fixTableName(metadata.getDefaultTableName(), ds);
70
71       log = Logger.getLogger(getClass().getName() + "." + tableName);
72
73       // generate sql
74

75       insertSql = "insert into " + tableName + " (";
76
77       JDBCCMPFieldBridge2[] keyFields = (JDBCCMPFieldBridge2[])this.leftField.getTableKeyFields();
78       insertSql += keyFields[0].getColumnName();
79       for(int i = 1; i < keyFields.length; ++i)
80       {
81          insertSql += ", " + keyFields[i].getColumnName();
82       }
83
84       keyFields = (JDBCCMPFieldBridge2[])this.rightField.getTableKeyFields();
85       insertSql += ", " + keyFields[0].getColumnName();
86       for(int i = 1; i < keyFields.length; ++i)
87       {
88          insertSql += ", " + keyFields[i].getColumnName();
89       }
90
91       insertSql += ") values (?";
92       for(int i = 1; i < this.leftField.getTableKeyFields().length + this.rightField.getTableKeyFields().length; ++i)
93       {
94          insertSql += ", ?";
95       }
96
97       insertSql += ")";
98
99       log.debug("insert sql: " + insertSql);
100
101       deleteSql = "delete from " + tableName + " where ";
102       keyFields = (JDBCCMPFieldBridge2[])this.leftField.getTableKeyFields();
103       deleteSql += keyFields[0].getColumnName() + "=?";
104       for(int i = 1; i < keyFields.length; ++i)
105       {
106          deleteSql += " and " + keyFields[i].getColumnName() + "=?";
107       }
108
109       keyFields = (JDBCCMPFieldBridge2[])this.rightField.getTableKeyFields();
110       deleteSql += " and " + keyFields[0].getColumnName() + "=?";
111       for(int i = 1; i < keyFields.length; ++i)
112       {
113          deleteSql += " and " + keyFields[i].getColumnName() + "=?";
114       }
115
116       log.debug("delete sql: " + deleteSql);
117    }
118
119    // Public
120

121    public void addRelation(JDBCCMRFieldBridge2 field1, Object JavaDoc key1, JDBCCMRFieldBridge2 field2, Object JavaDoc key2)
122    {
123       View view = getView();
124       if(field1 == leftField)
125       {
126          view.addKeys(key1, key2);
127       }
128       else
129       {
130          view.addKeys(key2, key1);
131       }
132    }
133
134    public void removeRelation(JDBCCMRFieldBridge2 field1, Object JavaDoc key1, JDBCCMRFieldBridge2 field2, Object JavaDoc key2)
135    {
136       View view = getView();
137       if(field1 == leftField)
138       {
139          view.removeKeys(key1, key2);
140       }
141       else
142       {
143          view.removeKeys(key2, key1);
144       }
145    }
146
147    // Table implementation
148

149    public int getTableId()
150    {
151       return tableId;
152    }
153
154    public String JavaDoc getTableName()
155    {
156       return tableName;
157    }
158    
159    public Table.View createView(Transaction JavaDoc tx)
160    {
161       return new View();
162    }
163
164    // Private
165

166    private void delete(View view) throws SQLException JavaDoc
167    {
168       if(view.deleted == null)
169       {
170          if(log.isTraceEnabled())
171          {
172             log.trace("no rows to delete");
173          }
174          return;
175       }
176
177       Connection JavaDoc con = null;
178       PreparedStatement JavaDoc ps = null;
179       try
180       {
181          if(log.isDebugEnabled())
182          {
183             log.debug("executing : " + deleteSql);
184          }
185
186          con = ds.getConnection();
187          ps = con.prepareStatement(deleteSql);
188
189          int batchCount = 0;
190          while(view.deleted != null)
191          {
192             RelationKeys keys = view.deleted;
193
194             int paramInd = 1;
195             JDBCCMPFieldBridge2[] keyFields = (JDBCCMPFieldBridge2[])leftField.getTableKeyFields();
196             for(int pkInd = 0; pkInd < keyFields.length; ++pkInd)
197             {
198                JDBCCMPFieldBridge2 pkField = keyFields[pkInd];
199                Object JavaDoc fieldValue = pkField.getPrimaryKeyValue(keys.leftKey);
200                paramInd = pkField.setArgumentParameters(ps, paramInd, fieldValue);
201             }
202
203             keyFields = (JDBCCMPFieldBridge2[])rightField.getTableKeyFields();
204             for(int pkInd = 0; pkInd < keyFields.length; ++pkInd)
205             {
206                JDBCCMPFieldBridge2 pkField = keyFields[pkInd];
207                Object JavaDoc fieldValue = pkField.getPrimaryKeyValue(keys.rightKey);
208                paramInd = pkField.setArgumentParameters(ps, paramInd, fieldValue);
209             }
210
211             ps.addBatch();
212             ++batchCount;
213
214             keys.dereference();
215          }
216
217          ps.executeBatch();
218
219          if(view.deleted != null)
220          {
221             throw new IllegalStateException JavaDoc("There are still rows to delete!");
222          }
223
224          if(log.isTraceEnabled())
225          {
226             log.trace("deleted rows: " + batchCount);
227          }
228       }
229       catch(SQLException JavaDoc e)
230       {
231          log.error("Failed to delete view: " + e.getMessage(), e);
232          throw e;
233       }
234       finally
235       {
236          JDBCUtil.safeClose(ps);
237          JDBCUtil.safeClose(con);
238       }
239    }
240
241    private void insert(View view) throws SQLException JavaDoc
242    {
243       if(view.created == null)
244       {
245          if(log.isTraceEnabled())
246          {
247             log.trace("no rows to insert");
248          }
249          return;
250       }
251
252       Connection JavaDoc con = null;
253       PreparedStatement JavaDoc ps = null;
254       try
255       {
256          if(log.isDebugEnabled())
257          {
258             log.debug("executing : " + insertSql);
259          }
260
261          con = ds.getConnection();
262          ps = con.prepareStatement(insertSql);
263
264          int batchCount = 0;
265          while(view.created != null)
266          {
267             RelationKeys keys = view.created;
268
269             JDBCCMPFieldBridge2[] keyFields = (JDBCCMPFieldBridge2[])leftField.getTableKeyFields();
270             int paramInd = 1;
271             for(int fInd = 0; fInd < keyFields.length; ++fInd)
272             {
273                JDBCCMPFieldBridge2 field = keyFields[fInd];
274                Object JavaDoc fieldValue = field.getPrimaryKeyValue(keys.leftKey);
275                paramInd = field.setArgumentParameters(ps, paramInd, fieldValue);
276             }
277
278             keyFields = (JDBCCMPFieldBridge2[])rightField.getTableKeyFields();
279             for(int fInd = 0; fInd < keyFields.length; ++fInd)
280             {
281                JDBCCMPFieldBridge2 field = keyFields[fInd];
282                Object JavaDoc fieldValue = field.getPrimaryKeyValue(keys.rightKey);
283                paramInd = field.setArgumentParameters(ps, paramInd, fieldValue);
284             }
285
286             ps.addBatch();
287             ++batchCount;
288
289             keys.dereference();
290          }
291
292          ps.executeBatch();
293
294          if(log.isTraceEnabled())
295          {
296             log.trace("inserted rows: " + batchCount);
297          }
298       }
299       catch(SQLException JavaDoc e)
300       {
301          log.error("Failed to insert new rows: " + e.getMessage(), e);
302          throw e;
303       }
304       finally
305       {
306          JDBCUtil.safeClose(ps);
307          JDBCUtil.safeClose(con);
308       }
309    }
310
311    private View getView()
312    {
313       return (View) schema.getView(this);
314    }
315
316    // Inner
317

318    private class View implements Table.View
319    {
320       private RelationKeys created;
321       private RelationKeys deleted;
322
323       // Public
324

325       public void addKeys(Object JavaDoc leftKey, Object JavaDoc rightKey)
326       {
327          // if it was deleted then dereference
328
RelationKeys keys = deleted;
329          while(keys != null)
330          {
331             if(keys.equals(leftKey, rightKey))
332             {
333                keys.dereference();
334                return;
335             }
336             keys = keys.next;
337          }
338
339          // add to created
340
keys = new RelationKeys(this, leftKey, rightKey);
341
342          if(created != null)
343          {
344             keys.next = created;
345             created.prev = keys;
346          }
347          created = keys;
348          keys.state = CREATED;
349       }
350
351       public void removeKeys(Object JavaDoc leftKey, Object JavaDoc rightKey)
352       {
353          // if it was created then dereference
354
RelationKeys keys = created;
355          while(keys != null)
356          {
357             if(keys.equals(leftKey, rightKey))
358             {
359                keys.dereference();
360                return;
361             }
362             keys = keys.next;
363          }
364
365          // add to deleted
366
keys = new RelationKeys(this, leftKey, rightKey);
367
368          if(deleted != null)
369          {
370             keys.next = deleted;
371             deleted.prev = keys;
372          }
373          deleted = keys;
374          keys.state = DELETED;
375       }
376
377       // Table.View implementation
378

379       public void flushDeleted(Schema.Views views) throws SQLException JavaDoc
380       {
381          delete(this);
382       }
383
384       public void flushCreated(Schema.Views views) throws SQLException JavaDoc
385       {
386          insert(this);
387       }
388
389       public void flushUpdated() throws SQLException JavaDoc
390       {
391       }
392
393       public void beforeCompletion()
394       {
395       }
396
397       public void committed()
398       {
399       }
400
401       public void rolledback()
402       {
403       }
404    }
405
406    private class RelationKeys
407    {
408       private final View view;
409       private final Object JavaDoc leftKey;
410       private final Object JavaDoc rightKey;
411
412       private byte state;
413       private RelationKeys next;
414       private RelationKeys prev;
415
416       public RelationKeys(View view, Object JavaDoc leftKey, Object JavaDoc rightKey)
417       {
418          this.view = view;
419          this.leftKey = leftKey;
420          this.rightKey = rightKey;
421       }
422
423       // Public
424

425       public boolean equals(Object JavaDoc leftKey, Object JavaDoc rightKey)
426       {
427          return this.leftKey.equals(leftKey) && this.rightKey.equals(rightKey);
428       }
429
430       public void dereference()
431       {
432          if(state == CREATED && this == view.created)
433          {
434             view.created = next;
435          }
436          else if(state == DELETED && this == view.deleted)
437          {
438             view.deleted = next;
439          }
440
441          if(next != null)
442          {
443             next.prev = prev;
444          }
445
446          if(prev != null)
447          {
448             prev.next = next;
449          }
450
451          next = null;
452          prev = null;
453       }
454    }
455 }
456
Popular Tags