ambertable.java

来自「RESIN 3.2 最新源码」· Java 代码 · 共 567 行

JAVA
567
字号
/* * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved * * This file is part of Resin(R) Open Source * * Each copy or derived work must preserve the copyright notice and this * notice unmodified. * * Resin Open Source is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Resin Open Source is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty * of NON-INFRINGEMENT.  See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with Resin Open Source; if not, write to the * *   Free Software Foundation, Inc. *   59 Temple Place, Suite 330 *   Boston, MA 02111-1307  USA * * @author Scott Ferguson */package com.caucho.amber.table;import com.caucho.amber.AmberRuntimeException;import com.caucho.amber.entity.AmberCompletion;import com.caucho.amber.entity.Entity;import com.caucho.amber.entity.EntityListener;import com.caucho.amber.entity.TableInvalidateCompletion;import com.caucho.amber.manager.AmberConnection;import com.caucho.amber.manager.AmberPersistenceUnit;import com.caucho.amber.type.EntityType;import com.caucho.amber.type.AmberType;import com.caucho.config.ConfigException;import com.caucho.config.LineConfigException;import com.caucho.util.CharBuffer;import com.caucho.util.L10N;import javax.sql.DataSource;import java.sql.Connection;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;import java.util.ArrayList;import java.util.Collections;/** * Representation of a database table. */public class AmberTable {  private static final L10N L = new L10N(AmberTable.class);  private String _name;  private String _configLocation;  private AmberPersistenceUnit _manager;  // The entity type is used to generate primary keys for cascade deletes  private EntityType _type;  private ArrayList<AmberColumn> _columns = new ArrayList<AmberColumn>();  private ArrayList<LinkColumns> _incomingLinks = new ArrayList<LinkColumns>();  private ArrayList<LinkColumns> _outgoingLinks = new ArrayList<LinkColumns>();  private ArrayList<AmberColumn> _idColumns = new ArrayList<AmberColumn>();  private LinkColumns _dependentIdLink;  private boolean _isReadOnly;  private long _cacheTimeout = 250;  private ArrayList<EntityListener> _entityListeners    = new ArrayList<EntityListener>();  private TableInvalidateCompletion _invalidateCompletion;  public AmberTable(AmberPersistenceUnit manager, String name)  {    _manager = manager;    _name = name;  }  public ArrayList<LinkColumns> getIncomingLinks()  {    return _incomingLinks;  }  public ArrayList<LinkColumns> getOutgoingLinks()  {    return _outgoingLinks;  }  /**   * Gets the sql table name.   */  public String getName()  {    return _name;  }  /**   * Sets the config location.   */  public void setConfigLocation(String location)  {    _configLocation = location;  }  /**   * Returns the location.   */  public String getLocation()  {    return _configLocation;  }  /**   * Returns the amber manager.   */  public AmberPersistenceUnit getAmberManager()  {    return _manager;  }  /**   * Sets the entity type.   */  public void setType(EntityType type)  {    if (_type == null)      _type = type;  }  /**   * Gets the entity type.   */  public EntityType getType()  {    return _type;  }  /**   * Returns true if read-only   */  public boolean isReadOnly()  {    return _isReadOnly;  }  /**   * Sets true if read-only   */  public void setReadOnly(boolean isReadOnly)  {    _isReadOnly = isReadOnly;  }  /**   * Returns the cache timeout.   */  public long getCacheTimeout()  {    return _cacheTimeout;  }  /**   * Sets the cache timeout.   */  public void setCacheTimeout(long timeout)  {    _cacheTimeout = timeout;  }  /**   * Creates a column.   */  public AmberColumn createColumn(String name, AmberType type)  {    for (int i = 0; i < _columns.size(); i++) {      AmberColumn oldColumn = _columns.get(i);      if (oldColumn.getName().equals(name))        return oldColumn;    }    AmberColumn column = new AmberColumn(this, name, type);    _columns.add(column);    Collections.sort(_columns, new ColumnCompare());    return column;  }  /**   * Creates a foreign column.   */  public ForeignColumn createForeignColumn(String name, AmberColumn key)  {    for (int i = 0; i < _columns.size(); i++) {      AmberColumn oldColumn = _columns.get(i);      if (! oldColumn.getName().equals(name)) {      }      else if (oldColumn instanceof ForeignColumn) {        // XXX: check type        return (ForeignColumn) oldColumn;      }      else {        // XXX: copy props(?)        ForeignColumn column = new ForeignColumn(this, name, key);        _columns.set(i, column);        return column;      }    }    ForeignColumn column = new ForeignColumn(this, name, key);    _columns.add(column);    Collections.sort(_columns, new ColumnCompare());    return column;  }  /**   * Adds a column.   */  public AmberColumn addColumn(AmberColumn column)  {    for (int i = 0; i < _columns.size(); i++) {      AmberColumn oldColumn = _columns.get(i);      if (! oldColumn.getName().equals(column.getName())) {      }      else if (oldColumn instanceof ForeignColumn)        return oldColumn;      else if (column instanceof ForeignColumn) {        _columns.set(i, column);        return column;      }      else        return oldColumn;    }    _columns.add(column);    Collections.sort(_columns, new ColumnCompare());    return column;  }  /**   * Returns the columns.   */  public ArrayList<AmberColumn> getColumns()  {    return _columns;  }  /**   * Remove a given column.   */  public boolean removeColumn(AmberColumn column)  {    return _columns.remove(column);  }  /**   * Adds an incoming link.   */  void addIncomingLink(LinkColumns link)  {    assert(! _incomingLinks.contains(link));    // XXX: ejb/06ip vs jpa/0s2d    if (_manager.isJPA()) {      // XXX: jpa/0j5e, jpa/0s2d      for (LinkColumns l : _incomingLinks) {        if (l.getSourceTable().equals(link.getSourceTable()) &&            l.getTargetTable().equals(link.getTargetTable()))          return;      }    }    _incomingLinks.add(link);  }  /**   * Adds an outgoing link.   */  void addOutgoingLink(LinkColumns link)  {    assert(! _outgoingLinks.contains(link));    _outgoingLinks.add(link);  }  /**   * Adds an id column.   */  public void addIdColumn(AmberColumn column)  {    _idColumns.add(column);  }  /**   * Returns the id columns.   */  public ArrayList<AmberColumn> getIdColumns()  {    return _idColumns;  }  /**   * Sets the id link for a dependent table.   */  public void setDependentIdLink(LinkColumns link)  {    _dependentIdLink = link;  }  /**   * Gets the id link for a dependent table.   */  public LinkColumns getDependentIdLink()  {    return _dependentIdLink;  }  /**   * Creates the table if missing.   */  public void createDatabaseTable(AmberPersistenceUnit amberPersistenceUnit)    throws ConfigException  {    try {      DataSource ds = amberPersistenceUnit.getDataSource();      Connection conn = ds.getConnection();      try {        Statement stmt = conn.createStatement();        try {          // If the table exists, return          String sql = "select 1 from " + getName() + " o where 1=0";          ResultSet rs = stmt.executeQuery(sql);          rs.close();          return;        } catch (SQLException e) {        }        String createSQL = generateCreateTableSQL(amberPersistenceUnit);        stmt.executeUpdate(createSQL);        stmt.close();      } finally {        conn.close();      }    } catch (Exception e) {      throw error(e);    }  }  /**   * Generates the SQL to create the table.   */  private String generateCreateTableSQL(AmberPersistenceUnit amberPersistenceUnit)  {    CharBuffer cb = new CharBuffer();    cb.append("create table " + getName() + " (");    boolean hasColumn = false;    for (AmberColumn column : _columns) {      String columnSQL = column.generateCreateTableSQL(amberPersistenceUnit);      if (columnSQL == null) {      }      else if (! hasColumn) {        hasColumn = true;        cb.append("\n  " + columnSQL);      }      else {        cb.append(",\n  " + columnSQL);      }    }    cb.append("\n)");    return cb.close();  }  /**   * Creates the table if missing.   */  public void validateDatabaseTable(AmberPersistenceUnit amberPersistenceUnit)    throws ConfigException  {    try {      DataSource ds = amberPersistenceUnit.getDataSource();      Connection conn = ds.getConnection();      try {        Statement stmt = conn.createStatement();        try {          // If the table exists, return          String sql = "select 1 from " + getName() + " o where 1=0";          ResultSet rs = stmt.executeQuery(sql);          rs.close();        } catch (SQLException e) {          throw error(L.l("'{0}' is not a valid database table.  Either the table needs to be created or the create-database-tables attribute must be set.\n\n{1}",                          getName(), e.toString()), e);        }      } finally {        conn.close();      }      for (AmberColumn column : _columns) {        column.validateDatabase(amberPersistenceUnit);      }    } catch (ConfigException e) {      if (_type != null)        _type.setConfigException(e);      throw e;    } catch (Exception e) {      if (_type != null)        _type.setConfigException(e);      throw error(e);    }  }  /**   * Returns the table's invalidation.   */  public AmberCompletion getInvalidateCompletion()  {    if (_invalidateCompletion == null)      _invalidateCompletion = new TableInvalidateCompletion(getName());    return _invalidateCompletion;  }  /**   * Returns the table's invalidation.   */  public AmberCompletion getUpdateCompletion()  {    return getInvalidateCompletion();  }  /**   * Returns the table's invalidation.   */  public AmberCompletion getDeleteCompletion()  {    return getInvalidateCompletion();  }  /**   * Adds a listener for create/delete events   */  public void addEntityListener(EntityListener listener)  {    if (! _entityListeners.contains(listener))      _entityListeners.add(listener);  }  /**   * Returns true if there are any listeners.   */  public boolean hasListeners()  {    return _entityListeners.size() > 0;  }  /**   * Returns true if any deletes of this object are cascaded.   */  public boolean isCascadeDelete()  {    // check if any of the incoming links have a target cascade delete    for (int i = 0; i < _incomingLinks.size(); i++) {      LinkColumns link = _incomingLinks.get(i);      if (link.isSourceCascadeDelete())        return true;    }    // check if any of the outgoing links have a source cascade delete    for (int i = 0; i < _outgoingLinks.size(); i++) {      LinkColumns link = _outgoingLinks.get(i);      if (link.isTargetCascadeDelete())        return true;    }    return false;  }  /**   * Called before the entity is deleted.   */  public void beforeEntityDelete(AmberConnection aConn, Entity entity)  {    try {      for (int i = 0; i < _entityListeners.size(); i++) {        EntityListener listener = _entityListeners.get(i);        listener.beforeEntityDelete(aConn, entity);      }      // getHome().completeDelete(aConn, key);      // jpa/0h60, the application should be responsible for deleting      // the incoming links even when there are FK constraints.      for (int i = 0; i < _incomingLinks.size(); i++) {        LinkColumns link = _incomingLinks.get(i);        link.beforeTargetDelete(aConn, entity);      }      aConn.addCompletion(getDeleteCompletion());    } catch (RuntimeException e) {      throw e;    } catch (Exception e) {      throw new AmberRuntimeException(e);    }  }  protected ConfigException error(String msg, Throwable e)  {    if (_configLocation != null)      return new LineConfigException(_configLocation + msg, e);    else      return new ConfigException(msg, e);  }  protected RuntimeException error(Throwable e)  {    if (_configLocation != null)      return ConfigException.create(_configLocation, e);    else      return ConfigException.create(e);  }  /**   * Printable version of the entity.   */  @Override  public String toString()  {    return "Table[" + getName() + "]";  }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?