/**
   * This method inserts one row for an entity table and gets latestPK of this row.
   *
   * @param query
   * @param variables
   * @param nullVars
   * @author ywang 11-26-2007
   */
  public void executeWithPK(String query, HashMap variables, HashMap nullVars) {
    clearSignals();

    Connection con = null;
    PreparedStatement ps = null;
    PreparedStatementFactory psf = new PreparedStatementFactory(variables, nullVars);
    try {
      con = ds.getConnection();
      if (con.isClosed()) {
        if (logger.isWarnEnabled()) logger.warn("Connection is closed: EntityDAO.execute!");
        throw new SQLException();
      }
      ps = con.prepareStatement(query);
      ps = psf.generate(ps); // enter variables here!
      if (ps.executeUpdate() != 1) {
        logger.warn("Problem with executing dynamic query, EntityDAO: " + query);
        throw new SQLException();

      } else {
        logger.info("Executing dynamic query, EntityDAO: " + query);

        if (getCurrentPKName == null) {
          this.latestPK = 0;
        }

        this.unsetTypeExpected();
        this.setTypeExpected(1, TypeNames.INT);

        ArrayList al = select(digester.getQuery(getCurrentPKName), con);

        if (al.size() > 0) {
          HashMap h = (HashMap) al.get(0);
          this.latestPK = ((Integer) h.get("key")).intValue();
        }
      }

    } catch (SQLException sqle) {
      signalFailure(sqle);
      if (logger.isWarnEnabled()) {
        logger.warn(
            "Exception while executing dynamic statement, EntityDAO.execute: "
                + query
                + ": "
                + sqle.getMessage());
        sqle.printStackTrace();
      }
    } finally {
      this.closeIfNecessary(con, ps);
    }
  }
  /*
   * @return the current value of the primary key sequence, if <code>
   * getCurrentPKName </code> is non-null, or null if <code> getCurrentPKName
   * </code> is null.
   */
  public int getCurrentPK() {
    int answer = 0;

    if (getCurrentPKName == null) {
      return answer;
    }

    this.unsetTypeExpected();
    this.setTypeExpected(1, TypeNames.INT);

    ArrayList al = select(digester.getQuery(getCurrentPKName));

    if (al.size() > 0) {
      HashMap h = (HashMap) al.get(0);
      answer = ((Integer) h.get("key")).intValue();
    }

    return answer;
  }
  /**
   * This method executes a "findByPK-style" query. Such a query has two characteristics:
   *
   * <ol>
   *   <li>The columns SELECTed by the SQL are all of the columns in the table relevant to the DAO,
   *       and only those columns. (e.g., in StudyDAO, the columns SELECTed are all of the columns
   *       in the study table, and only those columns.)
   *   <li>It returns at most one EntityBean.
   *       <ul>
   *         <li>Typically this means that the WHERE clause includes the columns in a candidate key
   *             with "=" criteria.
   *         <li>e.g., "WHERE item_id = ?" when selecting from item
   *         <li>e.g., "WHERE item_id = ? AND event_crf_id=?" when selecting from item_data
   *       </ol>
   *       Note that queries which join two tables may be included in the definition of
   *       "findByPK-style" query, as long as the first criterion is met.
   *
   * @param queryName The name of the query which should be executed.
   * @param variables The set of variables used to populate the PreparedStatement; should be empty
   *     if none are needed.
   * @return The EntityBean selected by the query.
   */
  public EntityBean executeFindByPKQuery(String queryName, HashMap variables) {
    EntityBean answer = new EntityBean();

    String sql = digester.getQuery(queryName);

    ArrayList rows;
    if (variables == null || variables.isEmpty()) {
      rows = this.select(sql);
    } else {
      rows = this.select(sql, variables);
    }

    Iterator it = rows.iterator();

    if (it.hasNext()) {
      answer = (EntityBean) this.getEntityFromHashMap((HashMap) it.next());
    }

    return answer;
  }