Помимо ОРМ ...
Если вы используете подпрограммы rs.getString и rs.getInt, то вы, безусловно, сможете облегчить бремя обслуживания, если будете полагаться на именованные столбцы, а не на пронумерованные столбцы.
В частности, rs.getInt ("id"), а не rs.getInt (1), например.
Редко случалось, что у меня был фактический тип данных изменения столбцов, поэтому будущее обслуживание SQL - это чуть больше, чем добавление новых столбцов, которые были сделаны в таблицу, и их можно просто прикрепить к концу вашего монстра. список привязок в каждом из ваших маленьких объектов DAO.
Затем вы берете эту идиому использования имен столбцов и расширяете ее до плана использования согласованных имен и, в то же время, «уникальных» имен. Предполагается, что с каждым столбцом в вашей базе данных связано уникальное имя. Теоретически он может быть таким же простым (хотя и многословным), как tablename_columnname, поэтому, если у вас есть таблица "member", для столбца id имя столбца будет "member_id".
Что это тебе покупает?
Это дает вам возможность использовать универсальные DAO для любого «действительного» набора результатов.
«Действительный» набор результатов - это набор результатов с именами столбцов с использованием уникальной спецификации именования.
Итак, вы получаете «выбрать идентификатор member_id, имя member_name от члена, где id = 1».
Почему вы хотите это сделать? Зачем идти к этому беспокойству?
Потому что тогда ваши объединения становятся тривиальными.
PreparedStatement = con.prepareStatement("select m.id member_id, m.name member_name, p.id post_id, p.date post_date, p.subject post_subject from member m, post p where m.id = p.member_id and m.id = 123");
ResultSet rs = ps.executeQuery();
Member m = null;
Post p = null;
while(rs.next()) {
if (m == null) {
m = MemberDAO.createFromResultSet(rs);
}
p = PostDAO.createFromResultSet(rs);
m.addPost(p);
}
Смотрите, здесь логика привязки не заботится о содержимом результирующего набора, поскольку она интересует только те столбцы, о которых она заботится.
В ваших DAO вы делаете их немного умнее насчет ResultSet. Оказывается, если вы выполните 'rs.getInt ("member_id") ", а member_id на самом деле не окажется в наборе результатов BE, вы получите исключение SQLException.
Но, немного поработав, используя ResultSetMetaData, вы можете выполнить быструю предварительную проверку (извлекая все имена столбцов заранее), затем вместо вызова rs.getInt вы можете вызвать baseDAO.getInt, который обрабатывает эти детали для вас, чтобы не получить исключение.
Прелесть здесь в том, что как только вы это сделаете, вы можете легко получить неполные DAO.
PreparedStatement = con.prepareStatement("select m.id member_id from member m where m.id = 123");
ResultSet rs = ps.executeQuery();
Member m = null;
if (rs.next()) {
m = MemberDAO.createFromResultSet(rs);
}
Наконец, это действительно (на самом деле) тривиальный сценарий (с использованием, скажем, AWK), который может взять свойства bean-компонента и преобразовать его в надлежащий двоичный код связующего кода для исходного DAO. Подобный сценарий может легко взять оператор таблицы SQL и преобразовать его в Java Bean (по крайней мере, базовые члены), который затем преобразуется в IDE в поток геттеров / сеттеров.
За счет централизации кода привязки в DAO обслуживание на самом деле практически ничего не происходит, поскольку оно изменилось в одном месте. Используя частичное связывание, вы можете безжалостно злоупотреблять им.
PreparedStatement = con.prepareStatement("select m.name member_name, max(p.date) post_date from member m, post p where post.member_id = m.id and m.id = 123");
ResultSet rs = ps.executeQuery();
Member m = null;
Post p = null;
if (rs.next()) {
m = MemberDAO.createFromResultSet(rs);
p = MemberDAO.craateFromResultSet(rs);
}
System.out.println(m.getName() + " latest post was on " + p.getDate());
Ваше бремя, продвигающееся вперед, состоит в основном в написании SQL, но даже это не ужасно Между написанием SQL и EQL нет большой разницы. Имейте в виду, это отчасти отстой, когда приходится писать оператор select с миллиардом столбцов, так как вы не можете (и не должны) использовать «select * from ...» (select * всегда (ВСЕГДА) приводит к беда, IME).
Но это только реальность. Я обнаружил, однако, что (если вы не делаете репортажи), эта проблема просто не бывает много. Это происходит, по крайней мере, один раз для большинства каждой таблицы, но это не происходит снова и снова. И, разумеется, когда он у вас есть один раз, вы можете либо «вырезать и вставить» свой путь к славе, либо изменить его (т.е. "от участника m, сообщение p").
Теперь мне нравятся JPA и ORM, я нахожу их полезными, но я также нахожу их PITA. Там происходят определенные отношения любви / ненависти. И когда дела идут гладко, мальчик, это гладко. Но когда это становится каменистым - ху мальчик. Тогда это может стать ужасным. В целом, однако, я рекомендую их.
Но если вы ищете "легкий" не-фреймворк, этот метод полезен, практичен, требует минимальных накладных расходов и дает вам большой контроль над вашими запросами. Между вашими запросами и вашей БД просто нет чёрной магии или темной материи, и когда что-то не работает, это не какое-то тайное недопонимание фреймворка или условие ошибки в крайнем случае, когда кто-то использует 100 тыс. Строк кода, скорее, ошибка в вашем SQL - где она принадлежит.