1 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 ; 33 import javax.transaction.Transaction ; 34 import java.sql.SQLException ; 35 import java.sql.Connection ; 36 import java.sql.PreparedStatement ; 37 38 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 ds; 51 private final String tableName; 52 private final JDBCCMRFieldBridge2 leftField; 53 private final JDBCCMRFieldBridge2 rightField; 54 private final Logger log; 55 56 private String insertSql; 57 private String 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 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 121 public void addRelation(JDBCCMRFieldBridge2 field1, Object key1, JDBCCMRFieldBridge2 field2, Object 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 key1, JDBCCMRFieldBridge2 field2, Object 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 149 public int getTableId() 150 { 151 return tableId; 152 } 153 154 public String getTableName() 155 { 156 return tableName; 157 } 158 159 public Table.View createView(Transaction tx) 160 { 161 return new View(); 162 } 163 164 166 private void delete(View view) throws SQLException 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 con = null; 178 PreparedStatement 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 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 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 ("There are still rows to delete!"); 222 } 223 224 if(log.isTraceEnabled()) 225 { 226 log.trace("deleted rows: " + batchCount); 227 } 228 } 229 catch(SQLException 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 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 con = null; 253 PreparedStatement 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 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 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 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 318 private class View implements Table.View 319 { 320 private RelationKeys created; 321 private RelationKeys deleted; 322 323 325 public void addKeys(Object leftKey, Object rightKey) 326 { 327 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 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 leftKey, Object rightKey) 352 { 353 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 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 379 public void flushDeleted(Schema.Views views) throws SQLException 380 { 381 delete(this); 382 } 383 384 public void flushCreated(Schema.Views views) throws SQLException 385 { 386 insert(this); 387 } 388 389 public void flushUpdated() throws SQLException 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 leftKey; 410 private final Object rightKey; 411 412 private byte state; 413 private RelationKeys next; 414 private RelationKeys prev; 415 416 public RelationKeys(View view, Object leftKey, Object rightKey) 417 { 418 this.view = view; 419 this.leftKey = leftKey; 420 this.rightKey = rightKey; 421 } 422 423 425 public boolean equals(Object leftKey, Object 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 |