Хотя это кажется очень простой проблемой, единственное решение, которое я придумал, приведено ниже. Любые предложения для чего-то менее уродливого с меньшей временной сложностью?
Мое приложение находится на Java и извлекается с помощью базы данных MS-sql с использованием skife.jdbi
.
Скажем, у меня есть Table
со столбцами A
, B
и C
, где A
и B
образуют первичный ключ. И я хочу получить C
, особенно учитывая A
и B
. Это легко осуществить. Но что, если мои требования к пропускной способности очень высоки, поэтому я хочу делать эти Select
операторов пакетами. Я получаю что-то вроде следующего:
Учитывая Set
из Objects
со значениями A
и B
, я перебираю список, компилируя все значения A
и B
. Затем я запускаю запрос типа SELECT A, B, C FROM tbl WHERE A IN :listOfAs AND B IN :listOfBs
. Затем я повторяю результаты запроса, сопоставляя результат с исходным объектом, сравнивая значения A
и B
. Все это звучит разумно, но в итоге код выглядит так, как показано ниже, что кажется уродливым и неоптимальным?
class MyObject {
String A;
String B;
String C;
Object otherData;
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
} else if (!(other instanceof MyObject)) {
return false;
} else {
return A.equals(other.A) && B.equals(other.B);
}
}
@Override
public int hashCode() {
return 31 * A.hashCode() + B.hashCode();
}
}
// populates the of objects with their proper C value
void retrieveC(Set<MyObject> input) {
Set<String> aValues = new HashSet<>();
Set<String> bValues = new HashSet<>();
for (MyObject object : input) {
aValues.add(object.A);
bValues.add(object.B);
}
// the dao executes the query mentioned above, and returns a Set of
// MyObject instances with members A, B, and C populated from the results.
// Any results that do not contain a value for A, B, and C (which
// shouldn't exit) are filtered out by the dao.
Set<MyObject> results = dao.selectC(aValues, bValues);
// ewww... O(n^2)
for (MyObject object : input) {
boolean resultFound = false;
for (MyObject result : results) {
if (object.equals(result)) {
object.C = result.C;
resultFound = true;
break;
}
}
if (!resultFound) {
// handle this case
}
}
}