Какая хорошая схема проектирования для достижения этого без бесконечного кода?
Учитывая сценарий, при котором пользователь может вводить 1... 100 столбцов, возможно, 23 один раз, 32 на другой вкладке и 99 полей на другой вставке и т.д. Все они могут быть разными полями каждый раз.
PreparedStatement в Java должен знать, какие column names
следует вводить первым, сколько ?
для ввода значений в запрос INSERT
типы данных имен полей базы данных для обеспечения правильного setInt
и setString
т.д.
Для менее чем около 10 столбцов вы можете обойти эту проблему со следующей логикой;
1) Если variableEnteredForFieldName не является нулевым, добавьте его в соответствующие части запроса в форме установки типа строкового типа;
fieldName_1
?
2) Сделайте то же самое для всех введенных имен полей
3) Измените конечный трейлинг ,
который, естественно, будет присутствовать как в field names
и в ?
s
4) Создайте PreparedStatement
5) Повторите те же параметры ввода снова, чтобы определить значение переменнойEnteredForFieldName не равно null, если не null, затем запустите setInt или setString на основе известного типа данных, который требуется базе данных, и установите это для правильного номера индекса для?,
До тех пор, пока логика построителя запросов и логика заливки запроса имеют имена/значения в правильном порядке в частях 1 и 2, все работает хорошо. Тем не менее, это означает дублирование всего кода, который относится к этой логике, один для генерации SQL для использования при создании PreparedStatement, а другой для заполнения PreparedStatement.
Это можно использовать для небольшого количества входных параметров, но это скоро становится неуправляемым для большего количества входных параметров.
Есть ли лучший дизайн для достижения той же логики?
Нижеприведенный код представляет собой схему всего вышеперечисленного для справки;
String fieldName1 = request.getParameter("fieldName1");
String fieldName2 = request.getParameter("fieldName2");
//Build Query
String fieldNames = "";
String fieldQuestionMarks = "";
if (fieldName1 != null) {
fieldNames = fieldNames + " FIELD_NAME_1 ,";
fieldQuestionMarks = fieldQuestionMarks + " ? ,";
}
if (fieldName2 != null) {
fieldNames = fieldNames + " FIELD_NAME_2 ,";
fieldQuestionMarks = fieldQuestionMarks + " ? ,";
}
//Trim the trailing ,
fieldNames = fieldNames.substring(1, fieldNames.length() - 1);
fieldQuestionMarks = fieldQuestionMarks.substring(1, fieldQuestionMarks.length() - 1);
try {
String completeCreateQuery = "INSERT INTO TABLE_NAME ( " + fieldNames + " ) VALUES ( " + fieldQuestionMarks + " );";
Connection con = DriverManager.getConnection(connectionURL, user, password);
PreparedStatement preparedStatement = con.prepareStatement(completeCreateQuery);
int parameterIndex = 1;
//Fill Query
if (fieldName1 != null) {
preparedStatement.setString(parameterIndex, fieldName1);
parameterIndex++;
}
if (fieldName2 != null) {
preparedStatement.setInt(parameterIndex, Integer.parseInt(fieldName2));
parameterIndex++;
}
}
Как вы можете видеть, он умеет. Но даже с двумя необязательными полями этот код огромен.
Как я вижу это, если пользователь может опустить любой из столбцов из списка, то все столбцы являются необязательными и могут быть безопасно установлены в NULL во время вставки. Таким образом, все, что вам нужно, это одно подготовленное выражение с "монстром" INSERT, причем все столбцы перечислены; то во время фактической операции вставки вы выполняете петлю, используя предоставленные пользователем данные, устанавливая значения для предоставленных столбцов и вызываете setNull()
для опущенных столбцов. Вам нужно будет поддерживать структуру где-нибудь (скорее всего, ваш класс DAO), сопоставляя имена столбцов с их порядком в инструкции SQL.