KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cayenne > dba > openbase > OpenBasePkGenerator


1 /*****************************************************************
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License. You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied. See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  ****************************************************************/

19
20 package org.apache.cayenne.dba.openbase;
21
22 import java.sql.Connection JavaDoc;
23 import java.sql.ResultSet JavaDoc;
24 import java.sql.Statement JavaDoc;
25 import java.util.ArrayList JavaDoc;
26 import java.util.Collections JavaDoc;
27 import java.util.Iterator JavaDoc;
28 import java.util.List JavaDoc;
29
30 import org.apache.cayenne.CayenneRuntimeException;
31 import org.apache.cayenne.access.DataNode;
32 import org.apache.cayenne.access.QueryLogger;
33 import org.apache.cayenne.dba.JdbcPkGenerator;
34 import org.apache.cayenne.map.DbAttribute;
35 import org.apache.cayenne.map.DbEntity;
36 import org.apache.cayenne.map.DerivedDbEntity;
37
38 /**
39  * @author <a HREF="mailto:mkienenb@alaska.net">Mike Kienenberger</a>
40  * @author Andrus Adamchik
41  * @since 1.1
42  */

43 public class OpenBasePkGenerator extends JdbcPkGenerator {
44
45     /**
46      * Returns a non-repeating primary key for a given entity. Since OpenBase-specific
47      * mechanism is used, key caching is disabled. Instead a database operation is
48      * performed on every call.
49      */

50     public Object JavaDoc generatePkForDbEntity(DataNode node, DbEntity entity) throws Exception JavaDoc {
51         // check for binary pk
52
Object JavaDoc binPK = binaryPK(entity);
53         if (binPK != null) {
54             return binPK;
55         }
56         return new Integer JavaDoc(pkFromDatabase(node, entity));
57     }
58
59     /**
60      * Generates new (unique and non-repeating) primary key for specified DbEntity.
61      * Executed SQL looks like this:
62      *
63      * <pre>
64      * NEWID FOR Table Column
65      * </pre>
66      *
67      * COLUMN must be marked as UNIQUE in order for this to work properly.
68      */

69     protected int pkFromDatabase(DataNode node, DbEntity entity) throws Exception JavaDoc {
70         String JavaDoc sql = newIDString(entity);
71         QueryLogger.logQuery(sql, Collections.EMPTY_LIST);
72
73         Connection JavaDoc con = node.getDataSource().getConnection();
74         try {
75             Statement JavaDoc st = con.createStatement();
76             try {
77
78                 ResultSet JavaDoc rs = st.executeQuery(sql);
79                 try {
80                     // Object pk = null;
81
if (!rs.next()) {
82                         throw new CayenneRuntimeException(
83                                 "Error generating pk for DbEntity " + entity.getName());
84                     }
85                     return rs.getInt(1);
86                 }
87                 finally {
88                     rs.close();
89                 }
90             }
91             finally {
92                 st.close();
93             }
94         }
95         finally {
96             con.close();
97         }
98     }
99
100     /**
101      * Returns SQL string that can generate new (unique and non-repeating) primary key for
102      * specified DbEntity. No actual database operations are performed.
103      *
104      * @since 1.2
105      */

106     protected String JavaDoc newIDString(DbEntity ent) {
107         if ((null == ent.getPrimaryKey()) || (1 != ent.getPrimaryKey().size())) {
108             throw new CayenneRuntimeException("Error generating pk for DbEntity "
109                     + ent.getName()
110                     + ": pk must be single attribute");
111         }
112         DbAttribute primaryKeyAttribute = (DbAttribute) ent.getPrimaryKey().get(0);
113
114         StringBuffer JavaDoc buf = new StringBuffer JavaDoc("NEWID FOR ");
115         buf.append(ent.getName()).append(' ').append(primaryKeyAttribute.getName());
116         return buf.toString();
117     }
118
119     public void createAutoPk(DataNode node, List JavaDoc dbEntities) throws Exception JavaDoc {
120         // looks like generating a PK on top of an existing one does not
121
// result in errors...
122

123         // create needed sequences
124
Iterator JavaDoc it = dbEntities.iterator();
125         while (it.hasNext()) {
126             DbEntity entity = (DbEntity) it.next();
127
128             // the caller must take care of giving us the right entities
129
// but lets check anyway
130
if (!canCreatePK(entity)) {
131                 continue;
132             }
133
134             runUpdate(node, createPKString(entity));
135             runUpdate(node, createUniquePKIndexString(entity));
136         }
137     }
138
139     /**
140      *
141      */

142     public List JavaDoc createAutoPkStatements(List JavaDoc dbEntities) {
143         List JavaDoc list = new ArrayList JavaDoc(2 * dbEntities.size());
144         Iterator JavaDoc it = dbEntities.iterator();
145         while (it.hasNext()) {
146             DbEntity entity = (DbEntity) it.next();
147
148             // the caller must take care of giving us the right entities
149
// but lets check anyway
150
if (!canCreatePK(entity)) {
151                 continue;
152             }
153
154             list.add(createPKString(entity));
155             list.add(createUniquePKIndexString(entity));
156         }
157
158         return list;
159     }
160
161     protected boolean canCreatePK(DbEntity entity) {
162         if (entity instanceof DerivedDbEntity) {
163             return false;
164         }
165
166         List JavaDoc pk = entity.getPrimaryKey();
167         if (pk == null || pk.size() == 0) {
168             return false;
169         }
170         return true;
171     }
172
173     /**
174      *
175      */

176     public void dropAutoPk(DataNode node, List JavaDoc dbEntities) throws Exception JavaDoc {
177         // there is no simple way to do that... probably requires
178
// editing metadata tables...
179
// Good thing is that it doesn't matter, since PK support
180
// is attached to the table itself, so if a table is dropped,
181
// it will be dropped as well
182
}
183
184     /**
185      * Returns an empty list, since OpenBase doesn't support this operation.
186      */

187     public List JavaDoc dropAutoPkStatements(List JavaDoc dbEntities) {
188         return Collections.EMPTY_LIST;
189     }
190
191     /**
192      * Returns a String to create PK support for an entity.
193      */

194     protected String JavaDoc createPKString(DbEntity entity) {
195         List JavaDoc pk = entity.getPrimaryKey();
196
197         if (pk == null || pk.size() == 0) {
198             throw new CayenneRuntimeException("Entity '"
199                     + entity.getName()
200                     + "' has no PK defined.");
201         }
202
203         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
204         buffer.append("CREATE PRIMARY KEY ").append(entity.getName()).append(" (");
205
206         Iterator JavaDoc it = pk.iterator();
207
208         // at this point we know that there is at least on PK column
209
DbAttribute firstColumn = (DbAttribute) it.next();
210         buffer.append(firstColumn.getName());
211
212         while (it.hasNext()) {
213             DbAttribute column = (DbAttribute) it.next();
214             buffer.append(", ").append(column.getName());
215         }
216
217         buffer.append(")");
218         return buffer.toString();
219     }
220
221     /**
222      * Returns a String to create a unique index on table primary key columns per OpenBase
223      * recommendations.
224      */

225     protected String JavaDoc createUniquePKIndexString(DbEntity entity) {
226         List JavaDoc pk = entity.getPrimaryKey();
227
228         if (pk == null || pk.size() == 0) {
229             throw new CayenneRuntimeException("Entity '"
230                     + entity.getName()
231                     + "' has no PK defined.");
232         }
233
234         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
235
236         // compound PK doesn't work well with UNIQUE index...
237
// create a regular one in this case
238
buffer.append(pk.size() == 1 ? "CREATE UNIQUE INDEX " : "CREATE INDEX ").append(
239                 entity.getName()).append(" (");
240
241         Iterator JavaDoc it = pk.iterator();
242
243         // at this point we know that there is at least on PK column
244
DbAttribute firstColumn = (DbAttribute) it.next();
245         buffer.append(firstColumn.getName());
246
247         while (it.hasNext()) {
248             DbAttribute column = (DbAttribute) it.next();
249             buffer.append(", ").append(column.getName());
250         }
251         buffer.append(")");
252         return buffer.toString();
253     }
254
255     public void reset() {
256         // noop
257
}
258
259     /**
260      * Returns zero, since PK caching is not feasible with OpenBase PK generation
261      * mechanism.
262      */

263     public int getPkCacheSize() {
264         return 0;
265     }
266
267     public void setPkCacheSize(int pkCacheSize) {
268         // noop, no PK caching
269
}
270
271 }
272
Popular Tags