code: public static void prepareDataSource(DataSource ds) throws SQLException {
      Connection con = null;
      String sql;
      try {
        con = ds.getConnection();
        con.setAutoCommit(false);
  
        DatabaseMetaData meta = con.getMetaData();
        ResultSet rs = meta.getTables(null, null, null, new String[]{"TABLE"});
        int tableNameColumn = rs.findColumn("TABLE_NAME");
        int count = 0;
        while (rs.next()) {
          String tableName = rs.getString(tableNameColumn);
          if (tableName.equalsIgnoreCase("CachedClasses")) {
            count++;
          }
        }
  
        if (count == 0) {
          String blobType = DbUtil.getTypeName(Types.BLOB, con);
          String nameType = DbUtil.getTypeName(Types.VARCHAR, 1024, con);
          String md5Type = DbUtil.getTypeName(Types.BINARY, 16, con);
  
          sql =  "CREATE TABLE CachedClasses ( \n" +
              "  Name " + nameType + " NOT NULL, \n" +
              "  MD5 " + md5Type + " NOT NULL, \n" +
              "  Definition " + blobType + " NOT NULL, \n" +
              "  PRIMARY KEY (Name, MD5) \n" +
              ")";
          DbUtil.update(ds, sql);
          con.commit();
        }
  
        con.setAutoCommit(true);
      } catch (SQLException e) {
        DbUtil.rollback(con);
        throw e;
      } finally {
        DbUtil.close(con);
      }
    }
docs: Prepares the data source to store cached class definitions.
  @param ds The <code>DataSource</code> to prepare.
  @throws SQLException If an error occurs while communicating with the
  database.