コード例 #1
0
  /**
   * Gives a possibility to patch the Castor-generated SQL statement for INSERT (makes sense for
   * DURING_INSERT key generators)
   */
  public String patchSQL(String insert, String primKeyName) throws MappingException {
    StringTokenizer st;
    String tableName;
    String seqName;
    String nextval;
    StringBuffer sb;
    int lp1; // the first left parenthesis, which starts fields list
    int lp2; // the second left parenthesis, which starts values list

    if (_style == BEFORE_INSERT) {
      return insert;
    }

    // First find the table name
    st = new StringTokenizer(insert);
    if (!st.hasMoreTokens() || !st.nextToken().equalsIgnoreCase("INSERT")) {
      throw new MappingException(Messages.format("mapping.keyGenCannotParse", insert));
    }
    if (!st.hasMoreTokens() || !st.nextToken().equalsIgnoreCase("INTO")) {
      throw new MappingException(Messages.format("mapping.keyGenCannotParse", insert));
    }
    if (!st.hasMoreTokens()) {
      throw new MappingException(Messages.format("mapping.keyGenCannotParse", insert));
    }
    tableName = st.nextToken();

    // remove every double quote in the tablename
    int idxQuote = tableName.indexOf('"');
    if (idxQuote >= 0) {
      StringBuffer buffer2 = new StringBuffer();
      int pos = 0;

      do {
        buffer2.append(tableName.substring(pos, idxQuote));
        pos = idxQuote + 1;
      } while ((idxQuote = tableName.indexOf('"', pos)) != -1);

      buffer2.append(tableName.substring(pos));

      tableName = buffer2.toString();
    }

    seqName =
        MessageFormat.format(
            _seqName,
            new String[] {tableName, primKeyName}); // due to varargs in 1.5, see CASTOR-1097
    nextval = _factory.quoteName(seqName + ".nextval");
    lp1 = insert.indexOf('(');
    lp2 = insert.indexOf('(', lp1 + 1);
    if (lp1 < 0) {
      throw new MappingException(Messages.format("mapping.keyGenCannotParse", insert));
    }
    sb = new StringBuffer(insert);
    if (!_triggerPresent) { // if no onInsert triggers in the DB, we have to supply the Key values
                            // manually
      if (lp2 < 0) {
        // Only one pk field in the table, the INSERT statement would be
        // INSERT INTO table VALUES ()
        lp2 = lp1;
        lp1 = insert.indexOf(" VALUES ");
        // don't change the order of lines below,
        // otherwise index becomes invalid
        sb.insert(lp2 + 1, nextval);
        sb.insert(lp1 + 1, "(" + _factory.quoteName(primKeyName) + ") ");
      } else {
        // don't change the order of lines below,
        // otherwise index becomes invalid
        sb.insert(lp2 + 1, nextval + ",");
        sb.insert(lp1 + 1, _factory.quoteName(primKeyName) + ",");
      }
    }
    if (_style == DURING_INSERT) {
      // append 'RETURNING primKeyName INTO ?'
      sb.append(" RETURNING ");
      sb.append(_factory.quoteName(primKeyName));
      sb.append(" INTO ?");
    }
    return sb.toString();
  }
コード例 #2
0
  /**
   * @param conn An open connection within the given transaction
   * @param tableName The table name
   * @param primKeyName The primary key name
   * @param props A temporary replacement for Principal object
   * @return A new key
   * @throws PersistenceException An error occured talking to persistent storage
   */
  public Object generateKey(Connection conn, String tableName, String primKeyName, Properties props)
      throws PersistenceException {
    PreparedStatement stmt = null;
    ResultSet rs;
    String seqName;
    String table;

    seqName =
        MessageFormat.format(
            _seqName,
            new String[] {tableName, primKeyName}); // due to varargs in 1.5, see CASTOR-1097
    table = _factory.quoteName(tableName);
    try {
      if (_factory.getFactoryName().equals(InterbaseFactory.FACTORY_NAME)) {
        // interbase only does before_insert, and does it its own way
        stmt =
            conn.prepareStatement(
                "SELECT gen_id(" + seqName + "," + _increment + ") FROM rdb$database");
        rs = stmt.executeQuery();
      } else if (_factory.getFactoryName().equals(DB2Factory.FACTORY_NAME)) {
        stmt = conn.prepareStatement("SELECT nextval FOR " + seqName + " FROM SYSIBM.SYSDUMMY1");
        rs = stmt.executeQuery();
      } else {
        if (_style == BEFORE_INSERT) {
          stmt = conn.prepareStatement("SELECT nextval('" + seqName + "')");
          rs = stmt.executeQuery();
        } else if (_triggerPresent && _factoryName.equals(PostgreSQLFactory.FACTORY_NAME)) {
          Object insStmt = props.get("insertStatement");
          Class psqlStmtClass = Class.forName("org.postgresql.Statement");
          Method getInsertedOID = psqlStmtClass.getMethod("getInsertedOID", (Class[]) null);
          int insertedOID = ((Integer) getInsertedOID.invoke(insStmt, (Object[]) null)).intValue();
          stmt =
              conn.prepareStatement(
                  "SELECT " + _factory.quoteName(primKeyName) + " FROM " + table + " WHERE OID=?");
          stmt.setInt(1, insertedOID);
          rs = stmt.executeQuery();

        } else {
          stmt =
              conn.prepareStatement(
                  "SELECT " + _factory.quoteName(seqName + ".currval") + " FROM " + table);
          rs = stmt.executeQuery();
        }
      }

      if (!rs.next()) {
        throw new PersistenceException(
            Messages.format("persist.keyGenFailed", getClass().getName()));
      }

      Object resultKey = null;
      int resultValue = rs.getInt(1);
      String resultColName = rs.getMetaData().getColumnName(1);
      int resultColType = rs.getMetaData().getColumnType(1);
      if (LOG.isDebugEnabled()) {
        LOG.debug(
            "JDBC query returned value "
                + resultValue
                + " from column "
                + resultColName
                + "/"
                + resultColType);
      }
      if (_sqlType == Types.INTEGER) {
        resultKey = new Integer(resultValue);
      } else if (_sqlType == Types.BIGINT) {
        resultKey = new Long(resultValue);
      } else if (_sqlType == Types.CHAR || _sqlType == Types.VARCHAR) {
        resultKey = String.valueOf(resultValue);
      } else {
        resultKey = new BigDecimal(resultValue);
      }

      if (LOG.isDebugEnabled()) {
        if (resultKey != null) {
          LOG.debug(
              "Returning value "
                  + resultKey
                  + " of type "
                  + resultKey.getClass().getName()
                  + " as key.");
        }
      }
      return resultKey;
    } catch (Exception ex) {
      throw new PersistenceException(
          Messages.format("persist.keyGenSQL", getClass().getName(), ex.toString()));
    } finally {
      JDOUtils.closeStatement(stmt);
    }
  }