public static <C> List<C> fetch(Class<C> cls, DatabaseObject filteredBy) {
    Database database = filteredBy.getDatabase();

    @SuppressWarnings("unchecked")
    AnnotatedRecordMapper<DatabaseObject> parentMapper =
        (AnnotatedRecordMapper<DatabaseObject>) create(filteredBy.getClass());
    AnnotatedRecordMapper<?> mapper = create(cls);

    List<String> relationColumnNames = mapper.getRelationColumnNames(filteredBy.getClass());
    List<String> idColumnNames = parentMapper.getIdColumnNames();
    Map<String, Object> values = parentMapper.extractIds(filteredBy);

    String relationExpression = "";
    Object[] parameters = new Object[relationColumnNames.size()];

    for (int i = 0; i < relationColumnNames.size(); i++) {
      relationExpression += relationColumnNames.get(i) + "=?";
      parameters[i] = values.get(idColumnNames.get(i));

      if (parameters[i] == null) {
        return new ArrayList<>();
      }
    }

    try (Transaction transaction = database.beginReadOnlyTransaction()) {
      transaction.associate(filteredBy);

      return transaction.select(cls, relationExpression, parameters);
    }
  }