public synchronized void create(String... primaryKeyNames) {
    PrimaryKeyInfo<B> primaryKeyInfo =
        PrimaryKeyInfo.getInstance(beanClass, primaryKeyNames, referencedFactories);
    Property[] primaryKeyProperties = primaryKeyInfo.getProperties();
    Property[] properties =
        Property.deriveProperties(beanClass, primaryKeyInfo, referencedFactories);

    String primaryKeyColumnNamesCommaSeparated =
        appendColumnNamesCommaSeparated(new StringBuffer(), primaryKeyInfo.getProperties())
            .toString();

    // Make main table
    StringBuffer b = new StringBuffer();
    b.append("create table ");
    b.append(tableName);
    b.append(" (");
    for (int i = 0; i < properties.length; i++) {
      if (i > 0) b.append(", ");
      Property prop = properties[i];
      if (prop.isPrimaryKeyProperty()
          && prop.getType() == int.class
          && primaryKeyInfo.getProperties().length == 1) {
        b.append(prop.getName());
        b.append(" INT NOT NULL AUTO_INCREMENT");
      } else if (prop.isPrimaryKeyProperty()
          && prop.getType() == long.class
          && primaryKeyInfo.getProperties().length == 1) {
        b.append(prop.getName());
        b.append(" BIGINT NOT NULL AUTO_INCREMENT");
      } else if (prop.isArray()) {
        b.append(prop.getName());
        b.append(" BOOLEAN NOT NULL DEFAULT 0");
      } else {
        String[] columnNames = prop.getColumnNames();
        Class<?>[] columnTypes = prop.getColumnTypes();
        int[] columnStrLens = prop.getColumnMaxStrLens();
        for (int j = 0; j < columnNames.length; j++) {
          if (j > 0) b.append(", ");
          b.append(columnNames[j]);
          b.append(' ');
          b.append(javaToSql(columnTypes[j], prop, columnStrLens[j]));
        }
      }
    }

    if (primaryKeyProperties.length > 0) {
      b.append(", PRIMARY KEY(");
      b.append(primaryKeyColumnNamesCommaSeparated);
      b.append(')');
    }

    b.append(')');

    Connection con;
    try {
      con = connectionPool.getConnection();
    } catch (ConnectionException e) {
      throw new BeanFactoryException(e);
    }

    try {
      Statement stmt = con.createStatement();
      if (printSQL != null) printDebug("createTable: " + b);
      stmt.executeUpdate(b.toString());
      stmt.close();
    } catch (SQLException e) {
      try {
        con.close();
      } catch (SQLException e2) {
        /* ignore */
      }
      throw new BeanFactoryException(
          "Error creating table \"" + tableName + "\": " + e.getMessage());
    }

    // If there are any array columns, make auxiliary tables to hold their data
    for (Property prop : properties) {
      if (prop.isArray()) {
        try {
          Statement stmt = con.createStatement();
          StringBuffer sql = new StringBuffer();
          sql.append("CREATE TABLE ").append(tableName).append('_');
          sql.append(prop.getName().toLowerCase()).append(" (");
          for (int i = 0; i < primaryKeyProperties.length; i++) {
            if (i > 0) sql.append(", ");
            String[] priKeyColumnNames = primaryKeyProperties[i].getColumnNames();
            Class<?>[] priKeyColumnTypes = primaryKeyProperties[i].getColumnTypes();
            int[] priKeyColStrLens = primaryKeyProperties[i].getColumnMaxStrLens();
            for (int j = 0; j < priKeyColumnNames.length; j++) {
              if (j > 0) sql.append(", ");
              sql.append(priKeyColumnNames[j]);
              sql.append(' ');
              sql.append(
                  javaToSql(priKeyColumnTypes[j], primaryKeyProperties[i], priKeyColStrLens[j]));
            }
          }
          sql.append(", ");
          sql.append(ARRAY_POS_COLUMN_NAME);
          sql.append(" INTEGER NOT NULL");
          String[] columnNames = prop.getColumnNames();
          Class<?>[] columnTypes = prop.getColumnTypes();
          int[] columnStrLens = prop.getColumnMaxStrLens();
          for (int j = 0; j < columnNames.length; j++) {
            sql.append(", ");
            sql.append(columnNames[j]);
            sql.append(' ');
            sql.append(javaToSql(columnTypes[j], prop, columnStrLens[j]));
          }
          sql.append(", PRIMARY KEY(");
          sql.append(primaryKeyColumnNamesCommaSeparated);
          sql.append(',');
          sql.append(ARRAY_POS_COLUMN_NAME);
          sql.append("))");
          if (printSQL != null) printDebug("createTable: " + sql);
          stmt.executeUpdate(sql.toString());
          stmt.close();
        } catch (SQLException e) {
          try {
            con.close();
          } catch (SQLException e2) {
            /* ignore */
          }
          throw new BeanFactoryException(
              "Error creating auxiliary table \""
                  + tableName
                  + '_'
                  + prop.getName()
                  + "\": "
                  + e.getMessage());
        }
      }
    }
    connectionPool.releaseConnection(con);
  }