/* */ package org.jboss.ejb.plugins.cmp.jdbc2.schema;
/* */
/* */ import java.sql.Connection;
/* */ import java.sql.PreparedStatement;
/* */ import java.sql.ResultSet;
/* */ import java.sql.SQLException;
/* */ import java.util.ArrayList;
/* */ import java.util.HashMap;
/* */ import java.util.List;
/* */ import java.util.Map;
/* */ import javax.ejb.DuplicateKeyException;
/* */ import javax.ejb.EJBException;
/* */ import javax.ejb.NoSuchEntityException;
/* */ import javax.ejb.NoSuchObjectLocalException;
/* */ import javax.management.MBeanServer;
/* */ import javax.management.ObjectName;
/* */ import javax.naming.InitialContext;
/* */ import javax.naming.NamingException;
/* */ import javax.sql.DataSource;
/* */ import javax.transaction.Transaction;
/* */ import org.jboss.cache.invalidation.InvalidationGroup;
/* */ import org.jboss.cache.invalidation.InvalidationManagerMBean;
/* */ import org.jboss.deployment.DeploymentException;
/* */ import org.jboss.ejb.EntityContainer;
/* */ import org.jboss.ejb.plugins.cmp.jdbc.JDBCEntityPersistenceStore;
/* */ import org.jboss.ejb.plugins.cmp.jdbc.JDBCType;
/* */ import org.jboss.ejb.plugins.cmp.jdbc.JDBCTypeFactory;
/* */ import org.jboss.ejb.plugins.cmp.jdbc.JDBCUtil;
/* */ import org.jboss.ejb.plugins.cmp.jdbc.SQLUtil;
/* */ import org.jboss.ejb.plugins.cmp.jdbc.bridge.JDBCAbstractCMRFieldBridge;
/* */ import org.jboss.ejb.plugins.cmp.jdbc.metadata.JDBCEntityMetaData;
/* */ import org.jboss.ejb.plugins.cmp.jdbc.metadata.JDBCFunctionMappingMetaData;
/* */ import org.jboss.ejb.plugins.cmp.jdbc.metadata.JDBCTypeMappingMetaData;
/* */ import org.jboss.ejb.plugins.cmp.jdbc2.bridge.JDBCCMPFieldBridge2;
/* */ import org.jboss.ejb.plugins.cmp.jdbc2.bridge.JDBCEntityBridge2;
/* */ import org.jboss.logging.Logger;
/* */ import org.jboss.metadata.CacheInvalidationConfigMetaData;
/* */ import org.jboss.metadata.ConfigurationMetaData;
/* */ import org.jboss.metadata.EntityMetaData;
/* */ import org.jboss.metadata.MetaData;
/* */ import org.jboss.mx.util.MBeanProxyExt;
/* */ import org.jboss.mx.util.MBeanServerLocator;
/* */ import org.jboss.system.Registry;
/* */ import org.jboss.system.ServiceControllerMBean;
/* */ import org.w3c.dom.Element;
/* */
/* */ public class EntityTable
/* */ implements Table
/* */ {
/* */ private static final byte UNREFERENCED = 0;
/* */ private static final byte CLEAN = 1;
/* */ private static final byte DIRTY = 2;
/* */ private static final byte CREATED = 4;
/* */ private static final byte DELETED = 8;
/* */ private static final byte DIRTY_RELATIONS = 16;
/* 83 */ private static final Object NOT_LOADED = new Object();
/* */ private JDBCEntityBridge2 entity;
/* */ private String tableName;
/* */ private int fieldsTotal;
/* */ private int relationsTotal;
/* */ private DataSource dataSource;
/* */ private Schema schema;
/* */ private int tableId;
/* */ private boolean dontFlushCreated;
/* */ private String deleteSql;
/* */ private String updateSql;
/* */ private String insertSql;
/* */ private String selectSql;
/* */ private String duplicatePkSql;
/* */ private final CommitStrategy insertStrategy;
/* */ private final CommitStrategy deleteStrategy;
/* */ private final CommitStrategy updateStrategy;
/* */ private Logger log;
/* */ private Cache cache;
/* */ private ServiceControllerMBean serviceController;
/* */ private ObjectName cacheName;
/* */ private int[] references;
/* */ private int[] referencedBy;
/* */ private ForeignKeyConstraint[] fkConstraints;
/* */ private CacheInvalidator cacheInvalidator;
/* 1817 */ private static final CommitStrategy BATCH_UPDATE = new CommitStrategy()
/* */ {
/* */ public void executeUpdate(PreparedStatement ps) throws SQLException
/* */ {
/* 1821 */ ps.addBatch();
/* */ }
/* */
/* */ public void executeBatch(PreparedStatement ps) throws SQLException
/* */ {
/* 1826 */ int[] updates = ps.executeBatch();
/* 1827 */ for (int i = 0; i < updates.length; i++)
/* */ {
/* 1829 */ int status = updates[i];
/* 1830 */ if ((status == 1) || (status == -2))
/* */ continue;
/* 1832 */ String msg = "Each command in the batch should update exactly 1 row but one of the commands updated " + updates[i] + " rows.";
/* */
/* 1836 */ throw new EJBException(msg);
/* */ }
/* */ }
/* 1817 */ };
/* */
/* 1842 */ private static final CommitStrategy NON_BATCH_UPDATE = new CommitStrategy()
/* */ {
/* */ public void executeUpdate(PreparedStatement ps) throws SQLException
/* */ {
/* 1846 */ int rows = ps.executeUpdate();
/* 1847 */ if (rows != 1)
/* */ {
/* 1849 */ throw new EJBException("Expected one updated row but got: " + rows);
/* */ }
/* */ }
/* */
/* */ public void executeBatch(PreparedStatement ps)
/* */ {
/* */ }
/* 1842 */ };
/* */
/* */ public EntityTable(JDBCEntityMetaData metadata, JDBCEntityBridge2 entity, Schema schema, int tableId)
/* */ throws DeploymentException
/* */ {
/* */ try
/* */ {
/* 122 */ InitialContext ic = new InitialContext();
/* 123 */ this.dataSource = ((DataSource)ic.lookup(metadata.getDataSourceName()));
/* */ }
/* */ catch (NamingException e)
/* */ {
/* 127 */ throw new DeploymentException("Filed to lookup: " + metadata.getDataSourceName(), e);
/* */ }
/* */
/* 130 */ this.entity = entity;
/* 131 */ this.tableName = SQLUtil.fixTableName(metadata.getDefaultTableName(), this.dataSource);
/* 132 */ this.log = Logger.getLogger(getClass().getName() + "." + this.tableName);
/* */
/* 134 */ this.schema = schema;
/* 135 */ this.tableId = tableId;
/* */
/* 137 */ EntityMetaData entityMetaData = (EntityMetaData)entity.getContainer().getBeanMetaData();
/* 138 */ ConfigurationMetaData containerConf = entityMetaData.getContainerConfiguration();
/* 139 */ this.dontFlushCreated = containerConf.isInsertAfterEjbPostCreate();
/* */
/* 142 */ Element cacheConf = containerConf.getContainerCacheConf();
/* 143 */ Element cachePolicy = cacheConf == null ? null : MetaData.getOptionalChild(cacheConf, "cache-policy-conf");
/* */ int maxCapacity;
/* */ int minCapacity;
/* */ int maxCapacity;
/* 147 */ if (cachePolicy != null)
/* */ {
/* 149 */ String str = MetaData.getOptionalChildContent(cachePolicy, "min-capacity");
/* 150 */ int minCapacity = str == null ? 1000 : Integer.parseInt(str);
/* 151 */ str = MetaData.getOptionalChildContent(cachePolicy, "max-capacity");
/* 152 */ maxCapacity = str == null ? 10000 : Integer.parseInt(str);
/* */ }
/* */ else
/* */ {
/* 156 */ minCapacity = 1000;
/* 157 */ maxCapacity = 10000;
/* */ }
/* */
/* 160 */ Element otherConf = cacheConf == null ? null : MetaData.getOptionalChild(cacheConf, "cache-policy-conf-other");
/* */ boolean invalidable;
/* */ int partitionsTotal;
/* */ Element batchCommitStrategy;
/* */ boolean invalidable;
/* 165 */ if (otherConf != null)
/* */ {
/* 167 */ String str = MetaData.getOptionalChildContent(otherConf, "partitions");
/* 168 */ int partitionsTotal = str == null ? 10 : Integer.parseInt(str);
/* 169 */ Element batchCommitStrategy = MetaData.getOptionalChild(otherConf, "batch-commit-strategy");
/* 170 */ invalidable = MetaData.getOptionalChild(otherConf, "invalidable") != null;
/* */ }
/* */ else
/* */ {
/* 174 */ partitionsTotal = 10;
/* 175 */ batchCommitStrategy = null;
/* 176 */ invalidable = false;
/* */ }
/* */
/* 179 */ if (cachePolicy != null)
/* */ {
/* 181 */ this.cache = new PartitionedTableCache(minCapacity, maxCapacity, partitionsTotal);
/* */
/* 183 */ String periodStr = MetaData.getOptionalChildContent(cachePolicy, "overager-period");
/* 184 */ String maxAgeStr = MetaData.getOptionalChildContent(cachePolicy, "max-bean-age");
/* 185 */ if (((periodStr != null) && (maxAgeStr == null)) || ((maxAgeStr != null) && (periodStr == null)))
/* */ {
/* 187 */ throw new DeploymentException("Failed to initialize age-out thread for entity " + entity.getEntityName() + ": overager-period or max-bean-age is missing!");
/* */ }
/* */
/* 191 */ if ((periodStr != null) && (maxAgeStr != null))
/* */ {
/* 193 */ long period = Long.parseLong(periodStr);
/* 194 */ long maxAge = Long.parseLong(maxAgeStr);
/* 195 */ ((PartitionedTableCache)this.cache).initOverager(period, maxAge, entity.getEntityName() + " overager");
/* */
/* 197 */ if (this.log.isTraceEnabled())
/* */ {
/* 199 */ this.log.trace("initialized age-out thread for " + entity.getEntityName() + ": overager-period=" + period + ", max-bean-age=" + maxAge);
/* */ }
/* */
/* */ }
/* */
/* 204 */ MBeanServer server = MBeanServerLocator.locateJBoss();
/* 205 */ this.serviceController = ((ServiceControllerMBean)MBeanProxyExt.create(ServiceControllerMBean.class, ServiceControllerMBean.OBJECT_NAME, server));
/* */ try
/* */ {
/* 211 */ this.cacheName = new ObjectName("jboss.cmp:service=tablecache,ejbname=" + metadata.getName() + ",table=" + this.tableName);
/* */
/* 213 */ server.registerMBean(this.cache, this.cacheName);
/* 214 */ this.serviceController.create(this.cacheName);
/* */ }
/* */ catch (Exception e)
/* */ {
/* 218 */ throw new DeploymentException("Failed to register table cache for " + this.tableName, e);
/* */ }
/* */ }
/* */ else
/* */ {
/* 223 */ this.cache = Cache.NONE;
/* */ }
/* */
/* 226 */ if (invalidable)
/* */ {
/* 228 */ String groupName = entityMetaData.getDistributedCacheInvalidationConfig().getInvalidationGroupName();
/* 229 */ String imName = entityMetaData.getDistributedCacheInvalidationConfig().getInvalidationManagerName();
/* */
/* 231 */ InvalidationManagerMBean im = (InvalidationManagerMBean)Registry.lookup(imName);
/* 232 */ InvalidationGroup invalidationGroup = im.getInvalidationGroup(groupName);
/* */
/* 234 */ this.cacheInvalidator = new CacheInvalidator(this.cache, entity.getContainer().getTransactionManager(), invalidationGroup);
/* */ }
/* */
/* 237 */ if (batchCommitStrategy == null)
/* */ {
/* 239 */ this.insertStrategy = NON_BATCH_UPDATE;
/* 240 */ this.deleteStrategy = NON_BATCH_UPDATE;
/* 241 */ this.updateStrategy = NON_BATCH_UPDATE;
/* */ }
/* */ else
/* */ {
/* 245 */ this.log.debug("batch-commit-strategy enabled");
/* 246 */ this.insertStrategy = BATCH_UPDATE;
/* 247 */ this.deleteStrategy = BATCH_UPDATE;
/* 248 */ this.updateStrategy = BATCH_UPDATE;
/* */ }
/* */ }
/* */
/* */ public void start() throws DeploymentException
/* */ {
/* 254 */ JDBCAbstractCMRFieldBridge[] cmrFields = this.entity.getCMRFields();
/* 255 */ this.relationsTotal = (cmrFields != null ? cmrFields.length : 0);
/* */
/* 257 */ JDBCCMPFieldBridge2[] pkFields = (JDBCCMPFieldBridge2[])(JDBCCMPFieldBridge2[])this.entity.getPrimaryKeyFields();
/* 258 */ JDBCCMPFieldBridge2[] tableFields = (JDBCCMPFieldBridge2[])(JDBCCMPFieldBridge2[])this.entity.getTableFields();
/* */
/* 261 */ this.deleteSql = ("delete from " + this.tableName + " where ");
/* 262 */ this.deleteSql = (this.deleteSql + pkFields[0].getColumnName() + "=?");
/* 263 */ for (int i = 1; i < pkFields.length; i++)
/* */ {
/* 265 */ this.deleteSql = (this.deleteSql + " and " + pkFields[i].getColumnName() + "=?");
/* */ }
/* 267 */ this.log.debug("delete sql: " + this.deleteSql);
/* */
/* 270 */ this.insertSql = ("insert into " + this.tableName + "(");
/* 271 */ this.insertSql += tableFields[0].getColumnName();
/* 272 */ for (int i = 1; i < tableFields.length; i++)
/* */ {
/* 274 */ this.insertSql = (this.insertSql + ", " + tableFields[i].getColumnName());
/* */ }
/* 276 */ this.insertSql += ") values (?";
/* 277 */ for (int i = 1; i < tableFields.length; i++)
/* */ {
/* 279 */ this.insertSql += ", ?";
/* */ }
/* 281 */ this.insertSql += ")";
/* 282 */ this.log.debug("insert sql: " + this.insertSql);
/* */
/* 285 */ this.updateSql = ("update " + this.tableName + " set ");
/* 286 */ int setFields = 0;
/* 287 */ for (int i = 0; i < tableFields.length; i++)
/* */ {
/* 289 */ JDBCCMPFieldBridge2 field = tableFields[i];
/* 290 */ if (field.isPrimaryKeyMember())
/* */ continue;
/* 292 */ if (setFields++ > 0)
/* */ {
/* 294 */ this.updateSql += ", ";
/* */ }
/* 296 */ this.updateSql = (this.updateSql + field.getColumnName() + "=?");
/* */ }
/* */
/* 299 */ this.updateSql += " where ";
/* 300 */ this.updateSql = (this.updateSql + pkFields[0].getColumnName() + "=?");
/* 301 */ for (int i = 1; i < pkFields.length; i++)
/* */ {
/* 303 */ this.updateSql = (this.updateSql + " and " + pkFields[i].getColumnName() + "=?");
/* */ }
/* */
/* 306 */ if (this.entity.getVersionField() != null)
/* */ {
/* 308 */ this.updateSql = (this.updateSql + " and " + this.entity.getVersionField().getColumnName() + "=?");
/* */ }
/* 310 */ this.log.debug("update sql: " + this.updateSql);
/* */
/* 313 */ String selectColumns = tableFields[0].getColumnName();
/* 314 */ for (int i = 1; i < tableFields.length; i++)
/* */ {
/* 316 */ JDBCCMPFieldBridge2 field = tableFields[i];
/* 317 */ selectColumns = selectColumns + ", " + field.getColumnName();
/* */ }
/* */
/* 320 */ String whereColumns = pkFields[0].getColumnName() + "=?";
/* 321 */ for (int i = 1; i < pkFields.length; i++)
/* */ {
/* 323 */ whereColumns = whereColumns + " and " + pkFields[i].getColumnName() + "=?";
/* */ }
/* */
/* 326 */ if (this.entity.getMetaData().hasRowLocking())
/* */ {
/* 328 */ JDBCEntityPersistenceStore manager = this.entity.getManager();
/* 329 */ JDBCTypeFactory typeFactory = manager.getJDBCTypeFactory();
/* 330 */ JDBCTypeMappingMetaData typeMapping = typeFactory.getTypeMapping();
/* 331 */ JDBCFunctionMappingMetaData rowLockingTemplate = typeMapping.getRowLockingTemplate();
/* 332 */ if (rowLockingTemplate == null)
/* */ {
/* 334 */ throw new DeploymentException("Row locking template is not defined for mapping: " + typeMapping.getName());
/* */ }
/* */
/* 337 */ this.selectSql = rowLockingTemplate.getFunctionSql(new Object[] { selectColumns, this.tableName, whereColumns, null }, new StringBuffer()).toString();
/* */ }
/* */ else
/* */ {
/* 342 */ this.selectSql = "select ";
/* 343 */ this.selectSql += selectColumns;
/* 344 */ this.selectSql = (this.selectSql + " from " + this.tableName + " where ");
/* 345 */ this.selectSql += whereColumns;
/* */ }
/* 347 */ this.log.debug("select sql: " + this.selectSql);
/* */
/* 350 */ if (this.dontFlushCreated)
/* */ {
/* 352 */ this.duplicatePkSql = "select ";
/* 353 */ this.duplicatePkSql += pkFields[0].getColumnName();
/* 354 */ for (int i = 1; i < pkFields.length; i++)
/* */ {
/* 356 */ this.duplicatePkSql = (this.duplicatePkSql + ", " + pkFields[i].getColumnName());
/* */ }
/* 358 */ this.duplicatePkSql = (this.duplicatePkSql + " from " + this.tableName + " where ");
/* 359 */ this.duplicatePkSql = (this.duplicatePkSql + pkFields[0].getColumnName() + "=?");
/* 360 */ for (int i = 1; i < pkFields.length; i++)
/* */ {
/* 362 */ this.duplicatePkSql = (this.duplicatePkSql + " and " + pkFields[i].getColumnName() + "=?");
/* */ }
/* 364 */ this.log.debug("duplicate pk sql: " + this.duplicatePkSql);
/* */ }
/* */
/* 367 */ if (this.cacheName != null)
/* */ {
/* */ try
/* */ {
/* 371 */ this.serviceController.start(this.cacheName);
/* */ }
/* */ catch (Exception e)
/* */ {
/* 375 */ throw new DeploymentException("Failed to start table cache.", e);
/* */ }
/* */ }
/* */ }
/* */
/* */ public void stop() throws Exception
/* */ {
/* 382 */ if (this.cacheInvalidator != null)
/* */ {
/* 384 */ this.cacheInvalidator.unregister();
/* */ }
/* */
/* 387 */ if (this.cacheName != null)
/* */ {
/* 389 */ this.serviceController.stop(this.cacheName);
/* 390 */ this.serviceController.destroy(this.cacheName);
/* 391 */ this.serviceController.remove(this.cacheName);
/* */ }
/* 393 */ this.serviceController = null;
/* */ }
/* */
/* */ public StringBuffer appendColumnNames(JDBCCMPFieldBridge2[] fields, String alias, StringBuffer buf)
/* */ {
/* 398 */ for (int i = 0; i < fields.length; i++)
/* */ {
/* 400 */ if (i > 0)
/* */ {
/* 402 */ buf.append(", ");
/* */ }
/* */
/* 405 */ if (alias != null)
/* */ {
/* 407 */ buf.append(alias).append(".");
/* */ }
/* */
/* 410 */ buf.append(fields[i].getColumnName());
/* */ }
/* */
/* 413 */ return buf;
/* */ }
/* */
/* */ public void addField()
/* */ {
/* 418 */ this.fieldsTotal += 1;
/* */ }
/* */
/* */ public int addVersionField()
/* */ {
/* 423 */ return this.fieldsTotal++;
/* */ }
/* */
/* */ public ForeignKeyConstraint addFkConstraint(JDBCCMPFieldBridge2[] fkFields, EntityTable referenced)
/* */ {
/* 428 */ addReference(referenced);
/* 429 */ referenced.addReferencedBy(this);
/* */
/* 431 */ if (this.fkConstraints == null)
/* */ {
/* 433 */ this.fkConstraints = new ForeignKeyConstraint[1];
/* */ }
/* */ else
/* */ {
/* 437 */ ForeignKeyConstraint[] tmp = this.fkConstraints;
/* 438 */ this.fkConstraints = new ForeignKeyConstraint[tmp.length + 1];
/* 439 */ System.arraycopy(tmp, 0, this.fkConstraints, 0, tmp.length);
/* */ }
/* 441 */ int fkindex = this.fkConstraints.length - 1;
/* 442 */ ForeignKeyConstraint fkc = new ForeignKeyConstraint(fkindex, fkFields);
/* 443 */ this.fkConstraints[fkindex] = fkc;
/* 444 */ return fkc;
/* */ }
/* */
/* */ public DataSource getDataSource()
/* */ {
/* 449 */ return this.dataSource;
/* */ }
/* */
/* */ public Object loadRow(ResultSet rs, boolean searchableOnly)
/* */ {
/* 454 */ View view = getView();
/* 455 */ Object pk = view.loadPk(rs);
/* 456 */ if (pk != null)
/* */ {
/* 458 */ view.loadRow(rs, pk, searchableOnly);
/* */ }
/* 460 */ else if (this.log.isTraceEnabled())
/* */ {
/* 462 */ this.log.trace("loaded pk is null.");
/* */ }
/* 464 */ return pk;
/* */ }
/* */
/* */ public Row getRow(Object id)
/* */ {
/* 469 */ return getView().getRow(id);
/* */ }
/* */
/* */ public boolean hasRow(Object id)
/* */ {
/* 474 */ return getView().hasRow(id);
/* */ }
/* */
/* */ public Row loadRow(Object id) throws SQLException
/* */ {
/* 479 */ View view = getView();
/* */
/* 481 */ Row row = view.getRowByPk(id, false);
/* 482 */ if (row != null)
/* */ {
/* 484 */ if (this.log.isTraceEnabled())
/* */ {
/* 486 */ this.log.trace("row is already loaded: pk=" + id);
/* */ }
/* 488 */ return row;
/* */ }
/* */
/* 491 */ JDBCCMPFieldBridge2[] pkFields = (JDBCCMPFieldBridge2[])(JDBCCMPFieldBridge2[])this.entity.getPrimaryKeyFields();
/* */
/* 493 */ Connection con = null;
/* 494 */ PreparedStatement ps = null;
/* 495 */ ResultSet rs = null;
/* */ try
/* */ {
/* 498 */ if (this.log.isDebugEnabled())
/* */ {
/* 500 */ this.log.debug("executing sql: " + this.selectSql);
/* */ }
/* */
/* 503 */ con = this.dataSource.getConnection();
/* 504 */ ps = con.prepareStatement(this.selectSql);
/* */
/* 506 */ int paramInd = 1;
/* 507 */ for (i = 0; i < pkFields.length; i++)
/* */ {
/* 509 */ JDBCCMPFieldBridge2 pkField = pkFields[i];
/* 510 */ Object pkValue = pkField.getPrimaryKeyValue(id);
/* 511 */ paramInd = pkField.setArgumentParameters(ps, paramInd, pkValue);
/* */ }
/* */
/* 514 */ rs = ps.executeQuery();
/* */
/* 516 */ if (!rs.next())
/* */ {
/* 518 */ throw new NoSuchEntityException("Row not found: " + id);
/* */ }
/* */
/* 521 */ i = view.loadRow(rs, id, false);
/* */ }
/* */ catch (SQLException e)
/* */ {
/* */ int i;
/* 525 */ this.log.error("Failed to load row: table=" + this.tableName + ", pk=" + id);
/* 526 */ throw e;
/* */ }
/* */ finally
/* */ {
/* 530 */ JDBCUtil.safeClose(rs);
/* 531 */ JDBCUtil.safeClose(ps);
/* 532 */ JDBCUtil.safeClose(con);
/* */ }
/* */ }
/* */
/* */ public int getTableId()
/* */ {
/* 540 */ return this.tableId;
/* */ }
/* */
/* */ public String getTableName()
/* */ {
/* 545 */ return this.tableName;
/* */ }
/* */
/* */ public Table.View createView(Transaction tx)
/* */ {
/* 550 */ return new View(tx);
/* */ }
/* */
/* */ private void addReference(EntityTable table)
/* */ {
/* 557 */ boolean wasRegistered = false;
/* 558 */ if (this.references != null)
/* */ {
/* 560 */ for (int i = 0; i < this.references.length; i++)
/* */ {
/* 562 */ if (this.references[i] != table.getTableId())
/* */ continue;
/* 564 */ wasRegistered = true;
/* 565 */ break;
/* */ }
/* */
/* 569 */ if (!wasRegistered)
/* */ {
/* 571 */ int[] tmp = this.references;
/* 572 */ this.references = new int[this.references.length + 1];
/* 573 */ System.arraycopy(tmp, 0, this.references, 0, tmp.length);
/* 574 */ this.references[tmp.length] = table.getTableId();
/* */ }
/* */ }
/* */ else
/* */ {
/* 579 */ this.references = new int[1];
/* 580 */ this.references[0] = table.getTableId();
/* */ }
/* */
/* 583 */ if (!wasRegistered)
/* */ {
/* 585 */ if (this.log.isTraceEnabled())
/* */ {
/* 587 */ this.log.trace("references " + table.getTableName());
/* */ }
/* */ }
/* */ }
/* */
/* */ private void addReferencedBy(EntityTable table)
/* */ {
/* 594 */ boolean wasRegistered = false;
/* 595 */ if (this.referencedBy != null)
/* */ {
/* 597 */ for (int i = 0; i < this.referencedBy.length; i++)
/* */ {
/* 599 */ if (this.referencedBy[i] != table.getTableId())
/* */ continue;
/* 601 */ wasRegistered = true;
/* 602 */ break;
/* */ }
/* */
/* 606 */ if (!wasRegistered)
/* */ {
/* 608 */ int[] tmp = this.referencedBy;
/* 609 */ this.referencedBy = new int[this.referencedBy.length + 1];
/* 610 */ System.arraycopy(tmp, 0, this.referencedBy, 0, tmp.length);
/* 611 */ this.referencedBy[tmp.length] = table.getTableId();
/* */ }
/* */ }
/* */ else
/* */ {
/* 616 */ this.referencedBy = new int[1];
/* 617 */ this.referencedBy[0] = table.getTableId();
/* */ }
/* */
/* 620 */ if (!wasRegistered)
/* */ {
/* 622 */ if (this.log.isTraceEnabled())
/* */ {
/* 624 */ this.log.trace("referenced by " + table.getTableName());
/* */ }
/* */ }
/* */ }
/* */
/* */ private void delete(View view) throws SQLException
/* */ {
/* 631 */ JDBCCMPFieldBridge2[] pkFields = (JDBCCMPFieldBridge2[])(JDBCCMPFieldBridge2[])this.entity.getPrimaryKeyFields();
/* */
/* 633 */ Connection con = null;
/* 634 */ PreparedStatement ps = null;
/* */ try
/* */ {
/* 637 */ if (this.log.isDebugEnabled())
/* */ {
/* 639 */ this.log.debug("executing : " + this.deleteSql);
/* */ }
/* */
/* 642 */ con = this.dataSource.getConnection();
/* 643 */ ps = con.prepareStatement(this.deleteSql);
/* */
/* 645 */ int batchCount = 0;
/* 646 */ while (view.deleted != null)
/* */ {
/* 648 */ Row row = view.deleted;
/* */
/* 650 */ int paramInd = 1;
/* 651 */ for (int pkInd = 0; pkInd < pkFields.length; pkInd++)
/* */ {
/* 653 */ JDBCCMPFieldBridge2 pkField = pkFields[pkInd];
/* 654 */ Object fieldValue = row.fields[pkField.getRowIndex()];
/* 655 */ paramInd = pkField.setArgumentParameters(ps, paramInd, fieldValue);
/* */ }
/* */
/* 658 */ this.deleteStrategy.executeUpdate(ps);
/* */
/* 660 */ batchCount++;
/* 661 */ row.flushStatus();
/* */ }
/* */
/* 664 */ this.deleteStrategy.executeBatch(ps);
/* */
/* 666 */ if (view.deleted != null)
/* */ {
/* 668 */ throw new IllegalStateException("There are still rows to delete!");
/* */ }
/* */
/* 671 */ if (this.log.isTraceEnabled())
/* */ {
/* 673 */ this.log.trace("deleted rows: " + batchCount);
/* */ }
/* */ }
/* */ catch (SQLException e)
/* */ {
/* 678 */ this.log.error("Failed to delete view: " + e.getMessage(), e);
/* 679 */ throw e;
/* */ }
/* */ finally
/* */ {
/* 683 */ JDBCUtil.safeClose(ps);
/* 684 */ JDBCUtil.safeClose(con);
/* */ }
/* */ }
/* */
/* */ private void update(View view) throws SQLException
/* */ {
/* 690 */ JDBCCMPFieldBridge2[] tableFields = (JDBCCMPFieldBridge2[])(JDBCCMPFieldBridge2[])this.entity.getTableFields();
/* 691 */ JDBCCMPFieldBridge2[] pkFields = (JDBCCMPFieldBridge2[])(JDBCCMPFieldBridge2[])this.entity.getPrimaryKeyFields();
/* */
/* 693 */ Connection con = null;
/* 694 */ PreparedStatement ps = null;
/* */ try
/* */ {
/* 697 */ if (this.log.isDebugEnabled())
/* */ {
/* 699 */ this.log.debug("executing : " + this.updateSql);
/* */ }
/* */
/* 702 */ con = this.dataSource.getConnection();
/* 703 */ ps = con.prepareStatement(this.updateSql);
/* */
/* 705 */ int batchCount = 0;
/* 706 */ while (view.dirty != null)
/* */ {
/* 708 */ Row row = view.dirty;
/* */
/* 710 */ int paramInd = 1;
/* 711 */ for (int fInd = 0; fInd < tableFields.length; fInd++)
/* */ {
/* 713 */ JDBCCMPFieldBridge2 field = tableFields[fInd];
/* 714 */ if (field.isPrimaryKeyMember())
/* */ continue;
/* 716 */ Object fieldValue = row.fields[field.getRowIndex()];
/* 717 */ paramInd = field.setArgumentParameters(ps, paramInd, fieldValue);
/* */ }
/* */
/* 721 */ for (int fInd = 0; fInd < pkFields.length; fInd++)
/* */ {
/* 723 */ JDBCCMPFieldBridge2 pkField = pkFields[fInd];
/* 724 */ Object fieldValue = row.fields[pkField.getRowIndex()];
/* 725 */ paramInd = pkField.setArgumentParameters(ps, paramInd, fieldValue);
/* */ }
/* */
/* 728 */ JDBCCMPFieldBridge2 versionField = this.entity.getVersionField();
/* 729 */ if (versionField != null)
/* */ {
/* 731 */ int versionIndex = versionField.getVersionIndex();
/* 732 */ Object curVersion = row.fields[versionIndex];
/* 733 */ paramInd = versionField.setArgumentParameters(ps, paramInd, curVersion);
/* */
/* 735 */ Object newVersion = row.fields[versionField.getRowIndex()];
/* 736 */ row.fields[versionIndex] = newVersion;
/* */ }
/* */
/* 739 */ this.updateStrategy.executeUpdate(ps);
/* */
/* 741 */ batchCount++;
/* 742 */ row.flushStatus();
/* */ }
/* */
/* 745 */ this.updateStrategy.executeBatch(ps);
/* */
/* 747 */ if (this.log.isTraceEnabled())
/* */ {
/* 749 */ this.log.trace("updated rows: " + batchCount);
/* */ }
/* */ }
/* */ catch (SQLException e)
/* */ {
/* 754 */ this.log.error("Failed to update: table=" + this.tableName, e);
/* 755 */ throw e;
/* */ }
/* */ finally
/* */ {
/* 759 */ JDBCUtil.safeClose(ps);
/* 760 */ JDBCUtil.safeClose(con);
/* */ }
/* */ }
/* */
/* */ private void insert(View view) throws SQLException
/* */ {
/* 766 */ JDBCCMPFieldBridge2[] tableFields = (JDBCCMPFieldBridge2[])(JDBCCMPFieldBridge2[])this.entity.getTableFields();
/* 767 */ Connection con = null;
/* 768 */ PreparedStatement ps = null;
/* */ try
/* */ {
/* 771 */ if (this.log.isDebugEnabled())
/* */ {
/* 773 */ this.log.debug("executing : " + this.insertSql);
/* */ }
/* */
/* 776 */ con = this.dataSource.getConnection();
/* 777 */ ps = con.prepareStatement(this.insertSql);
/* */
/* 779 */ int batchCount = 0;
/* 780 */ while (view.created != null)
/* */ {
/* 782 */ Row row = view.created;
/* */
/* 784 */ int paramInd = 1;
/* 785 */ for (int fInd = 0; fInd < tableFields.length; fInd++)
/* */ {
/* 787 */ JDBCCMPFieldBridge2 field = tableFields[fInd];
/* 788 */ Object fieldValue = row.fields[field.getRowIndex()];
/* 789 */ paramInd = field.setArgumentParameters(ps, paramInd, fieldValue);
/* */ }
/* */
/* 792 */ this.insertStrategy.executeUpdate(ps);
/* */
/* 794 */ batchCount++;
/* 795 */ row.flushStatus();
/* */ }
/* */
/* 798 */ this.insertStrategy.executeBatch(ps);
/* */
/* 800 */ if (this.log.isTraceEnabled())
/* */ {
/* 802 */ this.log.trace("inserted rows: " + batchCount);
/* */ }
/* */ }
/* */ catch (SQLException e)
/* */ {
/* 807 */ this.log.error("Failed to insert new rows: " + e.getMessage(), e);
/* 808 */ throw e;
/* */ }
/* */ finally
/* */ {
/* 812 */ JDBCUtil.safeClose(ps);
/* 813 */ JDBCUtil.safeClose(con);
/* */ }
/* */ }
/* */
/* */ private View getView()
/* */ {
/* 819 */ return (View)this.schema.getView(this);
/* */ }
/* */
/* */ public class ForeignKeyConstraint
/* */ {
/* */ public final int index;
/* */ private final String nullFkSql;
/* */
/* */ public ForeignKeyConstraint(int index, JDBCCMPFieldBridge2[] fkFields)
/* */ {
/* 1865 */ this.index = index;
/* */
/* 1867 */ StringBuffer buf = new StringBuffer();
/* 1868 */ buf.append("update ").append(EntityTable.this.tableName).append(" set ").append(fkFields[0].getColumnName()).append("=null");
/* */
/* 1870 */ for (int i = 1; i < fkFields.length; i++)
/* */ {
/* 1872 */ buf.append(", ").append(fkFields[i].getColumnName()).append("=null");
/* */ }
/* */
/* 1875 */ buf.append(" where ");
/* 1876 */ JDBCCMPFieldBridge2[] pkFields = (JDBCCMPFieldBridge2[])(JDBCCMPFieldBridge2[])EntityTable.this.entity.getPrimaryKeyFields();
/* 1877 */ buf.append(pkFields[0].getColumnName()).append("=?");
/* 1878 */ for (int i = 1; i < pkFields.length; i++)
/* */ {
/* 1880 */ buf.append(" and ").append(pkFields[i].getColumnName()).append("=?");
/* */ }
/* */
/* 1883 */ this.nullFkSql = buf.toString();
/* 1884 */ if (EntityTable.this.log.isDebugEnabled())
/* */ {
/* 1886 */ EntityTable.this.log.debug("update foreign key sql: " + this.nullFkSql);
/* */ }
/* */ }
/* */ }
/* */
/* */ public static abstract interface CommitStrategy
/* */ {
/* */ public abstract void executeUpdate(PreparedStatement paramPreparedStatement)
/* */ throws SQLException;
/* */
/* */ public abstract void executeBatch(PreparedStatement paramPreparedStatement)
/* */ throws SQLException;
/* */ }
/* */
/* */ public class Row
/* */ {
/* */ private EntityTable.View view;
/* */ private Object pk;
/* */ private final Object[] fields;
/* */ private final Object[] relations;
/* */ private byte state;
/* */ private Row prev;
/* */ private Row next;
/* */ private boolean cacheUpdateScheduled;
/* */ private Row nextCacheUpdate;
/* */ private EntityTable.ForeignKeyConstraint[] fkUpdates;
/* */
/* */ public Row(EntityTable.View view)
/* */ {
/* 1410 */ this.view = view;
/* 1411 */ this.fields = new Object[EntityTable.this.fieldsTotal];
/* 1412 */ this.relations = (EntityTable.this.relationsTotal == 0 ? null : new Object[EntityTable.this.relationsTotal]);
/* 1413 */ this.state = 0;
/* */ }
/* */
/* */ public Row(EntityTable.View view, Object[] fields, Object[] relations)
/* */ {
/* 1418 */ this.view = view;
/* 1419 */ this.fields = fields;
/* 1420 */ this.relations = relations;
/* 1421 */ this.state = 0;
/* */ }
/* */
/* */ public Object getPk()
/* */ {
/* 1426 */ return this.pk;
/* */ }
/* */
/* */ public void loadCachedRelations(int index, Cache.CacheLoader loader)
/* */ {
/* 1431 */ if (this.relations != null)
/* */ {
/* 1433 */ Object cached = this.relations[index];
/* 1434 */ this.relations[index] = loader.loadFromCache(cached);
/* */ }
/* */ }
/* */
/* */ public void cacheRelations(int index, Cache.CacheLoader loader)
/* */ {
/* 1440 */ this.relations[index] = loader.getCachedValue();
/* 1441 */ scheduleCacheUpdate();
/* */ }
/* */
/* */ public void insert(Object pk) throws DuplicateKeyException
/* */ {
/* 1446 */ this.pk = pk;
/* 1447 */ this.view.addCreated(this);
/* */ }
/* */
/* */ public Object getFieldValue(int i)
/* */ {
/* 1452 */ if (this.state == 8)
/* */ {
/* 1454 */ throw new NoSuchObjectLocalException("The instance was removed: " + this.pk);
/* */ }
/* */
/* 1457 */ Object value = this.fields[i];
/* 1458 */ if (value == EntityTable.NOT_LOADED)
/* */ {
/* 1460 */ value = loadField(i);
/* */ }
/* */
/* 1463 */ return value;
/* */ }
/* */
/* */ public void setFieldValue(int i, Object value)
/* */ {
/* 1468 */ this.fields[i] = value;
/* */ }
/* */
/* */ public boolean isDirty()
/* */ {
/* 1473 */ return (this.state != 1) && (this.state != 16);
/* */ }
/* */
/* */ public void setDirty()
/* */ {
/* 1478 */ if ((this.state == 1) || (this.state == 16))
/* */ {
/* 1480 */ updateState(2);
/* */ }
/* */ }
/* */
/* */ public void setDirtyRelations()
/* */ {
/* 1486 */ if (this.state == 1)
/* */ {
/* 1488 */ updateState(16);
/* */ }
/* */ }
/* */
/* */ public void delete()
/* */ {
/* 1494 */ if ((this.state == 1) || (this.state == 2) || (this.state == 16))
/* */ {
/* 1496 */ updateState(8);
/* */ }
/* 1498 */ else if (this.state == 4)
/* */ {
/* 1500 */ dereference();
/* 1501 */ this.state = 8;
/* 1502 */ EntityTable.View.access$2700(this.view).remove(this.pk);
/* */ }
/* 1504 */ else if (this.state == 8)
/* */ {
/* 1506 */ throw new IllegalStateException("The row is already deleted: pk=" + this.pk);
/* */ }
/* */ }
/* */
/* */ public void nullForeignKey(EntityTable.ForeignKeyConstraint constraint)
/* */ {
/* 1512 */ if (this.fkUpdates == null)
/* */ {
/* 1514 */ this.fkUpdates = new EntityTable.ForeignKeyConstraint[EntityTable.this.fkConstraints.length];
/* 1515 */ this.view.addRowWithNullFk(this);
/* */ }
/* */
/* 1518 */ this.fkUpdates[constraint.index] = constraint;
/* */ }
/* */
/* */ public void nonNullForeignKey(EntityTable.ForeignKeyConstraint constraint)
/* */ {
/* 1523 */ if (this.fkUpdates != null)
/* */ {
/* 1525 */ this.fkUpdates[constraint.index] = null;
/* */ }
/* */ }
/* */
/* */ private void flushStatus()
/* */ {
/* 1531 */ if ((this.state == 4) || (this.state == 2))
/* */ {
/* 1533 */ updateState(1);
/* */ }
/* 1535 */ else if (this.state == 8)
/* */ {
/* 1537 */ dereference();
/* */ }
/* 1539 */ else if (this.state == 16)
/* */ {
/* 1541 */ updateState(1);
/* */ }
/* */
/* 1544 */ scheduleCacheUpdate();
/* */ }
/* */
/* */ private void scheduleCacheUpdate()
/* */ {
/* 1549 */ if (!this.cacheUpdateScheduled)
/* */ {
/* 1551 */ if (EntityTable.View.access$2800(this.view) == null)
/* */ {
/* 1553 */ EntityTable.View.access$2802(this.view, this);
/* */ }
/* */ else
/* */ {
/* 1557 */ this.nextCacheUpdate = EntityTable.View.access$2800(this.view);
/* 1558 */ EntityTable.View.access$2802(this.view, this);
/* */ }
/* 1560 */ this.cacheUpdateScheduled = true;
/* */ }
/* */ }
/* */
/* */ private void updateState(byte state)
/* */ {
/* 1566 */ dereference();
/* */
/* 1568 */ if (state == 1)
/* */ {
/* 1570 */ if (EntityTable.View.access$2900(this.view) != null)
/* */ {
/* 1572 */ this.next = EntityTable.View.access$2900(this.view);
/* 1573 */ EntityTable.View.access$2900(this.view).prev = this;
/* */ }
/* 1575 */ EntityTable.View.access$2902(this.view, this);
/* */ }
/* 1577 */ else if (state == 2)
/* */ {
/* 1579 */ if (EntityTable.View.access$300(this.view) != null)
/* */ {
/* 1581 */ this.next = EntityTable.View.access$300(this.view);
/* 1582 */ EntityTable.View.access$300(this.view).prev = this;
/* */ }
/* 1584 */ EntityTable.View.access$302(this.view, this);
/* */ }
/* 1586 */ else if (state == 4)
/* */ {
/* 1588 */ if (EntityTable.View.access$400(this.view) != null)
/* */ {
/* 1590 */ this.next = EntityTable.View.access$400(this.view);
/* 1591 */ EntityTable.View.access$400(this.view).prev = this;
/* */ }
/* 1593 */ EntityTable.View.access$402(this.view, this);
/* */ }
/* 1595 */ else if (state == 8)
/* */ {
/* 1597 */ if (EntityTable.View.access$000(this.view) != null)
/* */ {
/* 1599 */ this.next = EntityTable.View.access$000(this.view);
/* 1600 */ EntityTable.View.access$000(this.view).prev = this;
/* */ }
/* 1602 */ EntityTable.View.access$002(this.view, this);
/* */ }
/* 1604 */ else if (state == 16)
/* */ {
/* 1606 */ if (EntityTable.View.access$3000(this.view) != null)
/* */ {
/* 1608 */ this.next = EntityTable.View.access$3000(this.view);
/* 1609 */ EntityTable.View.access$3000(this.view).prev = this;
/* */ }
/* 1611 */ EntityTable.View.access$3002(this.view, this);
/* */ }
/* */ else
/* */ {
/* 1615 */ throw new IllegalStateException("Can't update to state: " + state);
/* */ }
/* */
/* 1618 */ this.state = state;
/* */ }
/* */
/* */ private void dereference()
/* */ {
/* 1623 */ if ((this.state == 1) && (EntityTable.View.access$2900(this.view) == this))
/* */ {
/* 1625 */ EntityTable.View.access$2902(this.view, this.next);
/* */ }
/* 1627 */ else if ((this.state == 2) && (EntityTable.View.access$300(this.view) == this))
/* */ {
/* 1629 */ EntityTable.View.access$302(this.view, this.next);
/* */ }
/* 1631 */ else if ((this.state == 4) && (EntityTable.View.access$400(this.view) == this))
/* */ {
/* 1633 */ EntityTable.View.access$402(this.view, this.next);
/* */ }
/* 1635 */ else if ((this.state == 8) && (EntityTable.View.access$000(this.view) == this))
/* */ {
/* 1637 */ EntityTable.View.access$002(this.view, this.next);
/* */ }
/* 1639 */ else if ((this.state == 16) && (EntityTable.View.access$3000(this.view) == this))
/* */ {
/* 1641 */ EntityTable.View.access$3002(this.view, this.next);
/* */ }
/* */
/* 1644 */ if (this.next != null)
/* */ {
/* 1646 */ this.next.prev = this.prev;
/* */ }
/* */
/* 1649 */ if (this.prev != null)
/* */ {
/* 1651 */ this.prev.next = this.next;
/* */ }
/* */
/* 1654 */ this.prev = null;
/* 1655 */ this.next = null;
/* */ }
/* */
/* */ public void flush()
/* */ throws SQLException, DuplicateKeyException
/* */ {
/* 1662 */ if (this.state != 4)
/* */ {
/* 1664 */ if (EntityTable.this.log.isTraceEnabled())
/* */ {
/* 1666 */ EntityTable.this.log.trace("The row is already inserted: pk=" + this.pk);
/* */ }
/* 1668 */ return;
/* */ }
/* */
/* 1671 */ Connection con = null;
/* 1672 */ PreparedStatement duplicatePkPs = null;
/* 1673 */ PreparedStatement insertPs = null;
/* 1674 */ ResultSet rs = null;
/* */ try
/* */ {
/* 1678 */ con = EntityTable.this.dataSource.getConnection();
/* */
/* 1706 */ if (EntityTable.this.log.isDebugEnabled())
/* */ {
/* 1708 */ EntityTable.this.log.debug("executing : " + EntityTable.this.insertSql);
/* */ }
/* */
/* 1711 */ insertPs = con.prepareStatement(EntityTable.this.insertSql);
/* */
/* 1713 */ int paramInd = 1;
/* 1714 */ JDBCCMPFieldBridge2[] tableFields = (JDBCCMPFieldBridge2[])(JDBCCMPFieldBridge2[])EntityTable.this.entity.getTableFields();
/* 1715 */ for (int fInd = 0; fInd < tableFields.length; fInd++)
/* */ {
/* 1717 */ JDBCCMPFieldBridge2 field = tableFields[fInd];
/* 1718 */ Object fieldValue = this.fields[field.getRowIndex()];
/* 1719 */ paramInd = field.setArgumentParameters(insertPs, paramInd, fieldValue);
/* */ }
/* */
/* 1722 */ insertPs.executeUpdate();
/* */
/* 1724 */ flushStatus();
/* */ }
/* */ catch (SQLException e)
/* */ {
/* 1728 */ EntityTable.this.log.error("Failed to insert new rows: " + e.getMessage(), e);
/* 1729 */ throw e;
/* */ }
/* */ finally
/* */ {
/* 1733 */ JDBCUtil.safeClose(rs);
/* 1734 */ JDBCUtil.safeClose(duplicatePkPs);
/* 1735 */ JDBCUtil.safeClose(insertPs);
/* 1736 */ JDBCUtil.safeClose(con);
/* */ }
/* */ }
/* */
/* */ private Object loadField(int i)
/* */ {
/* 1742 */ JDBCCMPFieldBridge2 field = (JDBCCMPFieldBridge2)EntityTable.this.entity.getFields().get(i);
/* */
/* 1744 */ StringBuffer query = new StringBuffer();
/* 1745 */ query.append("select ").append(field.getColumnName()).append(" from ").append(EntityTable.this.tableName).append(" where ");
/* */
/* 1751 */ JDBCCMPFieldBridge2[] pkFields = (JDBCCMPFieldBridge2[])(JDBCCMPFieldBridge2[])EntityTable.this.entity.getPrimaryKeyFields();
/* 1752 */ for (int pkI = 0; pkI < pkFields.length; pkI++)
/* */ {
/* 1754 */ if (pkI > 0)
/* */ {
/* 1756 */ query.append(" and ");
/* */ }
/* 1758 */ query.append(pkFields[pkI].getColumnName()).append("=?");
/* */ }
/* */
/* 1761 */ if (EntityTable.this.log.isDebugEnabled())
/* */ {
/* 1763 */ EntityTable.this.log.debug("executing: " + query.toString());
/* */ }
/* */
/* 1766 */ Object value = null;
/* 1767 */ Connection con = null;
/* 1768 */ PreparedStatement ps = null;
/* 1769 */ ResultSet rs = null;
/* */ try
/* */ {
/* 1773 */ con = EntityTable.this.dataSource.getConnection();
/* 1774 */ ps = con.prepareStatement(query.toString());
/* */
/* 1776 */ for (int pkI = 0; pkI < pkFields.length; pkI++)
/* */ {
/* 1778 */ JDBCCMPFieldBridge2 pkField = pkFields[pkI];
/* 1779 */ Object fieldValue = this.fields[pkField.getRowIndex()];
/* 1780 */ pkField.setArgumentParameters(ps, pkI + 1, fieldValue);
/* */ }
/* */
/* 1783 */ rs = ps.executeQuery();
/* */
/* 1785 */ if (!rs.next())
/* */ {
/* 1787 */ throw new NoSuchEntityException("Row not found: " + this.pk);
/* */ }
/* */
/* 1790 */ value = field.loadArgumentResults(rs, 1);
/* */ }
/* */ catch (SQLException e)
/* */ {
/* 1794 */ throw new EJBException("Failed to load field " + EntityTable.this.entity.getEntityName() + "." + field.getFieldName() + ": " + e.getMessage(), e);
/* */ }
/* */ finally
/* */ {
/* 1800 */ JDBCUtil.safeClose(rs);
/* 1801 */ JDBCUtil.safeClose(ps);
/* 1802 */ JDBCUtil.safeClose(con);
/* */ }
/* */
/* 1805 */ this.fields[field.getRowIndex()] = value;
/* 1806 */ return value;
/* */ }
/* */ }
/* */
/* */ public class View
/* */ implements Table.View
/* */ {
/* */ private final Transaction tx;
/* 826 */ private Map rowByPk = new HashMap();
/* */ private EntityTable.Row created;
/* */ private EntityTable.Row deleted;
/* */ private EntityTable.Row dirty;
/* */ private EntityTable.Row dirtyRelations;
/* */ private EntityTable.Row clean;
/* */ private EntityTable.Row cacheUpdates;
/* */ private List rowsWithNullFks;
/* */ private boolean inFlush;
/* */
/* */ public View(Transaction tx)
/* */ {
/* 841 */ this.tx = tx;
/* */ }
/* */
/* */ public EntityTable.Row getRow(Object pk)
/* */ {
/* */ EntityTable.Row row;
/* */ EntityTable.Row row;
/* 847 */ if (pk == null)
/* */ {
/* 849 */ row = new EntityTable.Row(EntityTable.this, this);
/* */ }
/* */ else
/* */ {
/* 853 */ row = getRowByPk(pk, false);
/* 854 */ if (row == null)
/* */ {
/* 856 */ row = createCleanRow(pk);
/* */ }
/* */ }
/* 859 */ return row;
/* */ }
/* */
/* */ public EntityTable.Row getRowByPk(Object pk, boolean required)
/* */ {
/* 896 */ EntityTable.Row row = (EntityTable.Row)this.rowByPk.get(pk);
/* */
/* 898 */ if (row == null) {
/* 901 */ Object[] relations = null;
/* */ Object[] fields;
/* */ try {
/* 904 */ EntityTable.this.cache.lock(pk);
/* */
/* 906 */ fields = EntityTable.this.cache.getFields(pk);
/* 907 */ if ((fields != null) && (EntityTable.this.relationsTotal > 0))
/* */ {
/* 909 */ relations = EntityTable.this.cache.getRelations(pk);
/* 910 */ if (relations == null)
/* */ {
/* 912 */ relations = new Object[EntityTable.this.relationsTotal];
/* */ }
/* */ }
/* */ }
/* */ finally
/* */ {
/* 918 */ EntityTable.this.cache.unlock(pk);
/* */ }
/* */
/* 921 */ if (fields != null)
/* */ {
/* 923 */ row = createCleanRow(pk, fields, relations);
/* */ }
/* */ }
/* */
/* 927 */ if ((row == null) && (required))
/* */ {
/* 929 */ throw new IllegalStateException("row not found: pk=" + pk);
/* */ }
/* */
/* 932 */ return row;
/* */ }
/* */
/* */ public void addClean(EntityTable.Row row)
/* */ {
/* 944 */ if (this.clean != null)
/* */ {
/* 946 */ EntityTable.Row.access$702(row, this.clean);
/* 947 */ EntityTable.Row.access$802(this.clean, row);
/* */ }
/* */
/* 950 */ this.clean = row;
/* 951 */ EntityTable.Row.access$902(row, 1);
/* */
/* 953 */ this.rowByPk.put(row.pk, row);
/* */ }
/* */
/* */ public void addCreated(EntityTable.Row row)
/* */ throws DuplicateKeyException
/* */ {
/* 963 */ if (this.created != null)
/* */ {
/* 965 */ EntityTable.Row.access$702(row, this.created);
/* 966 */ EntityTable.Row.access$802(this.created, row);
/* */ }
/* */
/* 969 */ this.created = row;
/* 970 */ EntityTable.Row.access$902(row, 4);
/* */
/* 972 */ this.rowByPk.put(row.pk, row);
/* */
/* 974 */ JDBCCMPFieldBridge2 versionField = EntityTable.this.entity.getVersionField();
/* 975 */ if (versionField != null)
/* */ {
/* 977 */ row.fields[versionField.getVersionIndex()] = EntityTable.Row.access$100(row)[versionField.getRowIndex()];
/* */ }
/* */ }
/* */
/* */ public EntityTable.Row loadRow(ResultSet rs, Object pk, boolean searchableOnly)
/* */ {
/* 983 */ EntityTable.Row row = getRowByPk(pk, false);
/* 984 */ if (row != null)
/* */ {
/* 986 */ if (EntityTable.this.log.isTraceEnabled())
/* */ {
/* 988 */ EntityTable.this.log.trace("row is already loaded: pk=" + pk);
/* */ }
/* 990 */ return row;
/* */ }
/* 992 */ if (EntityTable.this.log.isTraceEnabled())
/* */ {
/* 994 */ EntityTable.this.log.trace("reading result set: pk=" + pk);
/* */ }
/* */
/* 997 */ row = createCleanRow(pk);
/* 998 */ JDBCCMPFieldBridge2[] tableFields = (JDBCCMPFieldBridge2[])(JDBCCMPFieldBridge2[])EntityTable.this.entity.getTableFields();
/* */
/* 1002 */ int rsOffset = 1;
/* 1003 */ for (int i = 0; i < tableFields.length; i++)
/* */ {
/* 1005 */ JDBCCMPFieldBridge2 field = tableFields[i];
/* 1006 */ if ((searchableOnly) && (!field.getJDBCType().isSearchable()))
/* */ {
/* 1008 */ row.fields[field.getRowIndex()] = EntityTable.access$1300();
/* 1009 */ rsOffset--;
/* */ }
/* */ else
/* */ {
/* 1013 */ Object columnValue = field.loadArgumentResults(rs, field.getRowIndex() + rsOffset);
/* 1014 */ row.fields[field.getRowIndex()] = columnValue;
/* */
/* 1016 */ if (field.getVersionIndex() == -1)
/* */ continue;
/* 1018 */ row.fields[field.getVersionIndex()] = columnValue;
/* */ }
/* */ }
/* */
/* 1022 */ Object[] relations = EntityTable.this.relationsTotal > 0 ? new Object[EntityTable.this.relationsTotal] : null;
/* */ try
/* */ {
/* 1026 */ EntityTable.this.cache.lock(row.pk);
/* 1027 */ EntityTable.this.cache.put(this.tx, row.pk, row.fields, relations);
/* */ }
/* */ finally
/* */ {
/* 1031 */ EntityTable.this.cache.unlock(row.pk);
/* */ }
/* */
/* 1034 */ return row;
/* */ }
/* */
/* */ public Object loadPk(ResultSet rs)
/* */ {
/* 1039 */ Object pk = null;
/* 1040 */ JDBCCMPFieldBridge2[] pkFields = (JDBCCMPFieldBridge2[])(JDBCCMPFieldBridge2[])EntityTable.this.entity.getPrimaryKeyFields();
/* */
/* 1042 */ for (int i = 0; i < pkFields.length; i++)
/* */ {
/* 1044 */ JDBCCMPFieldBridge2 field = pkFields[i];
/* */
/* 1046 */ Object columnValue = field.loadArgumentResults(rs, field.getRowIndex() + 1);
/* 1047 */ pk = field.setPrimaryKeyValue(pk, columnValue);
/* */ }
/* 1049 */ return pk;
/* */ }
/* */
/* */ public boolean hasRow(Object id)
/* */ {
/* 1054 */ boolean has = this.rowByPk.containsKey(id);
/* 1055 */ if (!has)
/* */ {
/* */ try
/* */ {
/* 1059 */ EntityTable.this.cache.lock(id);
/* 1060 */ has = EntityTable.this.cache.contains(this.tx, id);
/* */ }
/* */ finally
/* */ {
/* 1064 */ EntityTable.this.cache.unlock(id);
/* */ }
/* */ }
/* 1067 */ return has;
/* */ }
/* */
/* */ public void addRowWithNullFk(EntityTable.Row row)
/* */ {
/* 1072 */ if (this.rowsWithNullFks == null)
/* */ {
/* 1074 */ this.rowsWithNullFks = new ArrayList();
/* */ }
/* 1076 */ this.rowsWithNullFks.add(row);
/* */ }
/* */
/* */ private EntityTable.Row createCleanRow(Object pk)
/* */ {
/* 1081 */ EntityTable.Row row = new EntityTable.Row(EntityTable.this, this);
/* 1082 */ EntityTable.Row.access$1002(row, pk);
/* 1083 */ addClean(row);
/* 1084 */ return row;
/* */ }
/* */
/* */ private EntityTable.Row createCleanRow(Object pk, Object[] fields, Object[] relations)
/* */ {
/* 1089 */ EntityTable.Row row = new EntityTable.Row(EntityTable.this, this, fields, relations);
/* 1090 */ EntityTable.Row.access$1002(row, pk);
/* 1091 */ addClean(row);
/* 1092 */ return row;
/* */ }
/* */
/* */ public void flushDeleted(Schema.Views views)
/* */ throws SQLException
/* */ {
/* 1099 */ if (this.rowsWithNullFks != null)
/* */ {
/* 1101 */ nullifyForeignKeys();
/* 1102 */ this.rowsWithNullFks = null;
/* */ }
/* */
/* 1105 */ if (this.deleted == null)
/* */ {
/* 1107 */ if (EntityTable.this.log.isTraceEnabled())
/* */ {
/* 1109 */ EntityTable.this.log.trace("no rows to delete");
/* */ }
/* 1111 */ return;
/* */ }
/* */
/* 1114 */ if (EntityTable.this.referencedBy != null)
/* */ {
/* 1116 */ if (this.inFlush)
/* */ {
/* 1118 */ if (EntityTable.this.log.isTraceEnabled())
/* */ {
/* 1120 */ EntityTable.this.log.trace("inFlush, ignoring flushDeleted");
/* */ }
/* 1122 */ return;
/* */ }
/* */
/* 1125 */ this.inFlush = true;
/* */ try
/* */ {
/* 1129 */ for (int i = 0; i < EntityTable.this.referencedBy.length; i++)
/* */ {
/* 1131 */ Table.View view = views.entityViews[EntityTable.this.referencedBy[i]];
/* 1132 */ if (view == null)
/* */ continue;
/* 1134 */ view.flushDeleted(views);
/* */ }
/* */
/* */ }
/* */ finally
/* */ {
/* 1140 */ this.inFlush = false;
/* */ }
/* */ }
/* */
/* 1144 */ EntityTable.this.delete(this);
/* */ }
/* */
/* */ public void flushCreated(Schema.Views views) throws SQLException
/* */ {
/* 1149 */ if ((this.created == null) || (EntityTable.this.dontFlushCreated))
/* */ {
/* 1151 */ if (EntityTable.this.log.isTraceEnabled())
/* */ {
/* 1153 */ EntityTable.this.log.trace("no rows to insert");
/* */ }
/* 1155 */ return;
/* */ }
/* */
/* 1158 */ if (EntityTable.this.references != null)
/* */ {
/* 1160 */ if (this.inFlush)
/* */ {
/* 1162 */ if (EntityTable.this.log.isTraceEnabled())
/* */ {
/* 1164 */ EntityTable.this.log.trace("inFlush, ignorning flushCreated");
/* */ }
/* 1166 */ return;
/* */ }
/* 1168 */ if (EntityTable.this.log.isTraceEnabled())
/* */ {
/* 1170 */ EntityTable.this.log.trace("flushing created references");
/* */ }
/* */
/* 1173 */ this.inFlush = true;
/* */ try
/* */ {
/* 1176 */ for (int i = 0; i < EntityTable.this.references.length; i++)
/* */ {
/* 1178 */ Table.View view = views.entityViews[EntityTable.this.references[i]];
/* 1179 */ if (view == null)
/* */ continue;
/* 1181 */ view.flushCreated(views);
/* */ }
/* */
/* */ }
/* */ finally
/* */ {
/* 1187 */ this.inFlush = false;
/* */ }
/* */ }
/* */
/* 1191 */ EntityTable.this.insert(this);
/* */ }
/* */
/* */ public void flushUpdated() throws SQLException
/* */ {
/* 1196 */ if (this.dirtyRelations != null)
/* */ {
/* 1198 */ while (this.dirtyRelations != null)
/* */ {
/* 1200 */ EntityTable.Row row = this.dirtyRelations;
/* 1201 */ row.flushStatus();
/* */ }
/* */ }
/* */
/* 1205 */ if (this.dirty == null)
/* */ {
/* 1207 */ if (EntityTable.this.log.isTraceEnabled())
/* */ {
/* 1209 */ EntityTable.this.log.trace("no rows to update");
/* */ }
/* 1211 */ return;
/* */ }
/* */
/* 1214 */ EntityTable.this.update(this);
/* */ }
/* */
/* */ public void beforeCompletion()
/* */ {
/* */ }
/* */
/* */ public void committed()
/* */ {
/* 1249 */ if (this.cacheUpdates != null)
/* */ {
/* 1251 */ EntityTable.Row cursor = this.cacheUpdates;
/* */
/* 1253 */ while (cursor != null)
/* */ {
/* 1257 */ EntityTable.this.cache.lock(cursor.pk);
/* */ try
/* */ {
/* 1260 */ switch (cursor.state)
/* */ {
/* */ case 1:
/* 1263 */ EntityTable.this.cache.put(this.tx, cursor.pk, cursor.fields, cursor.relations);
/* 1264 */ break;
/* */ case 8:
/* */ try
/* */ {
/* 1268 */ EntityTable.this.cache.remove(this.tx, cursor.pk);
/* */ }
/* */ catch (Cache.RemoveException e)
/* */ {
/* 1272 */ EntityTable.this.log.warn(e.getMessage());
/* */ }
/* */
/* */ default:
/* 1276 */ throw new IllegalStateException("Unexpected row state: table=" + EntityTable.this.entity.getQualifiedTableName() + ", pk=" + cursor.pk + ", state=" + cursor.state);
/* */ }
/* */
/* */ }
/* */ finally
/* */ {
/* 1283 */ EntityTable.this.cache.unlock(cursor.pk);
/* */ }
/* */
/* 1287 */ cursor = cursor.nextCacheUpdate;
/* */ }
/* */ }
/* */ }
/* */
/* */ public void rolledback()
/* */ {
/* */ }
/* */
/* */ private void nullifyForeignKeys()
/* */ throws SQLException
/* */ {
/* 1327 */ if (EntityTable.this.log.isTraceEnabled())
/* */ {
/* 1329 */ EntityTable.this.log.trace("nullifying foreign keys");
/* */ }
/* */
/* 1332 */ Connection con = null;
/* 1333 */ PreparedStatement[] ps = new PreparedStatement[EntityTable.this.fkConstraints.length];
/* */ try
/* */ {
/* 1337 */ JDBCCMPFieldBridge2[] pkFields = (JDBCCMPFieldBridge2[])(JDBCCMPFieldBridge2[])EntityTable.this.entity.getPrimaryKeyFields();
/* 1338 */ con = EntityTable.this.dataSource.getConnection();
/* */
/* 1340 */ for (int i = 0; i < this.rowsWithNullFks.size(); i++)
/* */ {
/* 1342 */ EntityTable.Row row = (EntityTable.Row)this.rowsWithNullFks.get(i);
/* 1343 */ if (row.state == 8)
/* */ continue;
/* 1345 */ EntityTable.ForeignKeyConstraint[] cons = row.fkUpdates;
/* 1346 */ for (int c = 0; c < EntityTable.this.fkConstraints.length; c++)
/* */ {
/* 1348 */ if (cons[c] == null)
/* */ continue;
/* 1350 */ PreparedStatement s = ps[c];
/* 1351 */ if (s == null)
/* */ {
/* 1353 */ if (EntityTable.this.log.isDebugEnabled())
/* */ {
/* 1355 */ EntityTable.this.log.debug("nullifying fk: " + cons[c].nullFkSql);
/* */ }
/* 1357 */ s = con.prepareStatement(cons[c].nullFkSql);
/* 1358 */ ps[c] = s;
/* */ }
/* */
/* 1361 */ int paramInd = 1;
/* 1362 */ for (int fInd = 0; fInd < pkFields.length; fInd++)
/* */ {
/* 1364 */ JDBCCMPFieldBridge2 pkField = pkFields[fInd];
/* 1365 */ Object fieldValue = row.fields[pkField.getRowIndex()];
/* 1366 */ paramInd = pkField.setArgumentParameters(s, paramInd, fieldValue);
/* */ }
/* */
/* 1369 */ int affected = s.executeUpdate();
/* 1370 */ if (affected == 1)
/* */ continue;
/* 1372 */ throw new EJBException("Affected " + affected + " rows while expected just one");
/* */ }
/* */
/* */ }
/* */
/* */ }
/* */ finally
/* */ {
/* 1381 */ for (int i = 0; i < ps.length; i++)
/* */ {
/* 1383 */ JDBCUtil.safeClose(ps[i]);
/* */ }
/* 1385 */ JDBCUtil.safeClose(con);
/* */ }
/* */ }
/* */ }
/* */ }
/* Location: /home/mnovotny/projects/EMBEDDED_JBOSS_BETA3_COMMUNITY/embedded/output/lib/embedded-jboss/lib/jboss-embedded-all.jar
* Qualified Name: org.jboss.ejb.plugins.cmp.jdbc2.schema.EntityTable
* JD-Core Version: 0.6.0
*/