Какую ORM вы используете? Если вы не используете его, сейчас самое время начать - у вас создается впечатление, что у вас есть все эти подготовленные операторы, разбросанные по всему коду, которые в любом случае нуждаются в улучшении.
Использование чего-то вроде Hibernate означает, что вы можете просто активировать его ведение журнала и сохранить данные запроса / параметра. Это может также заставить вас сфокусировать ваши данные позже немного (если они немного хаотично структурированы прямо сейчас).
Если вы не желаете переходить на использование ORM, подумайте о создании собственного класса, возможно, с именем LoggingPreparedStatement, который идентичен обычному PreparedStatement (подклассу или оболочке PreparedStatement, так что он использует все те же имена методов и т. Д.). c так что это капля замены) и записывает все, что вы хотите. Используйте поиск / замену по всей базе кода, чтобы переключиться на его использование.
В качестве альтернативы выполнению этого на стороне клиента, вы можете заставить базу данных это сделать. Для SQL сервера есть отслеживание изменений, не знаю, что есть для MySQL, но это будет что-то запатентованное. Для чего-то непротиворечивого, большинство БД имеют триггеры, которые имеют некоторый механизм идентификации старых и новых данных, и вы можете сохранить sh в таблицах истории, чтобы увидеть, что было изменено и когда. Триггеры, которые хранят историю, имеют регулярность в своем коде, что означает, что они могут быть программно сгенерированы из списка столбцов таблицы и типов данных, так что вы можете запросить в БД имена столбцов (большинство БД имеют некоторые виртуальные таблицы, которые сообщают вам информацию о настоящие таблицы) et c и генерируйте свои триггеры в коде и (повторно) применяйте их при каждом изменении схемы. Преимущество использования триггеров в том, что они действительно легко идентифицируют данные, которые были изменены. Недостаток в том, что это все, что они могут видеть, поэтому, если вы хотите, чтобы ваш триггер знал больше, вам нужно добавить эту информацию в таблицу или сеанс, чтобы триггер мог получить к ней доступ - например, кто выполнял запрос, каким был запрос. Если вы не желаете добавлять бесполезные столбцы в таблицу (и действительно, зачем вам это нужно), вы можете переименовать все свои таблицы и предоставить набор представлений, которые выбираются из новых имен и называются старыми именами. Эти новые представления могут предоставлять дополнительные столбцы, которые может обновлять клиентская часть, а сами представления могут иметь триггеры INSTEAD OF, которые обновляют реальные таблицы. Не помогает при выборе, потому что удаление данных не требует никаких данных от клиента, так что все это беспорядок. Если вы планируете оптовую продажу вашей БД, вы просто переключитесь на использование хранимых процедур для ваших изменений данных и приступите к масштабной работе по изменению вызовов на стороне клиента. Альтернативой, которая также хорошо используется для SQL Сервера, является переменная CONTEXT_INFO, 128-байтовый блок переменных двоичных данных, который живет в течение всего времени вашего соединения / сеанса, или его более новое обновление SESSION_CONTEXT, набор пар ключей-значений 256 КБ. Если вы создаете что-то на стороне клиента, которое регистрирует данные пользователя, запроса и параметра, а также вы создаете триггер, который регистрирует изменение данных, вы можете использовать эти переменные, программно установленные в начале каждого оператора модификации данных, чтобы дайте вашему триггеру нечто более сложное, чем «каково текущее время», чтобы определить, какой запущенный набор данных относится к какому запросу в журнале. Генерация guid в клиенте и передача его в базу данных каким-то глобально читаемым способом, что означает, что триггер базы данных может увидеть его и записать в журнальную таблицу, привязав на стороне клиента журнал оператора и параметров к серверу изменения строки