Лучше сделать разбивку на / и проверить все отдельные части. Но если вы действительно хотите использовать регулярное выражение, вы можете попробовать следующее:
#\A(?:(?:(?:(?:0?[13578])|(1[02]))/31/(19|20)?\d\d)|(?:(?:(?:0?[13-9])|(?:1[0-2]))/(?:29|30)/(?:19|20)?\d\d)|(?:0?2/29/(?:19|20)(?:(?:[02468][048])|(?:[13579][26])))|(?:(?:(?:0?[1-9])|(?:1[0-2]))/(?:(?:0?[1-9])|(?:1\d)|(?:2[0-8]))/(?:19|20)?\d\d))\Z#
Объяснение:
\A # start of string
(?: # group without capture
# that match 31st of month 1,3,5,7,8,10,12
(?: # group without capture
(?: # group without capture
(?: # group without capture
0? # number 0 optionnal
[13578] # one digit either 1,3,5,7 or 8
) # end group
| # alternative
(1[02]) # 1 followed by 0 or 2
) # end group
/ # slash
31 # number 31
/ # slash
(19|20)? #numbers 19 or 20 optionnal
\d\d # 2 digits from 00 to 99
) # end group
|
(?:(?:(?:0?[13-9])|(?:1[0-2]))/(?:29|30)/(?:19|20)?\d\d)
|
(?:0?2/29/(?:19|20)(?:(?:[02468][048])|(?:[13579][26])))
|
(?:(?:(?:0?[1-9])|(?:1[0-2]))/(?:(?:0?[1-9])|(?:1\d)|(?:2[0-8]))/(?:19|20)?\d\d)
)
\Z
Я объяснил первую часть, оставив остальное как упражнение.
Это соответствует одной недействительной дате: 02/29/1900, но подходит для любых других дат между 01/01/1900 и 12/31/2099
Используя подготовленные операторы, нет «запроса SQL»:
Но нет никакого воссоздания реального реального SQL-запрос - ни на стороне Java, ни на стороне базы данных.
Таким образом, получить SQL подготовленного оператора невозможно - такого SQL нет.
Для целей отладки решения следующие:
Для этого вам потребуется соединение JDBC и / или драйвер, который поддерживает ведение журнала sql на низком уровне.
Взгляните на log4jdbc
Если вы используете MySQL, вы можете регистрировать запросы с помощью MySQL's query log. Я не знаю, предоставляют ли другие производители такую возможность, но есть вероятность, что да.
Это нигде не определено в контракте JDBC API, но если вам повезет, то данный JDBC драйвер может вернуть полный SQL, просто вызвав PreparedStatement#toString()
. Т.е.
System.out.println(preparedStatement);
По крайней мере, драйверы MySQL 5.x и PostgreSQL 8.x JDBC поддерживают это. Однако большинство других JDBC драйверов не поддерживают его. Если у вас есть такой, то лучшим вариантом будет использование Log4jdbc или P6Spy.
В качестве альтернативы можно также написать общую функцию, которая принимает Connection
, строку SQL и значения оператора и возвращает PreparedStatement
после регистрации строки SQL и значений. Начальный пример:
public static PreparedStatement prepareStatement(Connection connection, String sql, Object... values) throws SQLException {
PreparedStatement preparedStatement = connection.prepareStatement(sql);
for (int i = 0; i < values.length; i++) {
preparedStatement.setObject(i + 1, values[i]);
}
logger.debug(sql + " " + Arrays.asList(values));
return preparedStatement;
}
и использовать его как
try {
connection = database.getConnection();
preparedStatement = prepareStatement(connection, SQL, values);
resultSet = preparedStatement.executeQuery();
// ...
Другой альтернативой является реализация пользовательского PreparedStatement
, который обертывает (декорирует) real PreparedStatement
при построении и переопределяет все методы так, чтобы он вызывал методы real PreparedStatement
и собирает значения во всех методах setXXX()
и лениво строит "фактическую" строку SQL каждый раз, когда вызывается один из методов executeXXX()
(довольно сложная работа, но большинство IDE предоставляют автогенераторы для методов декораторов, Eclipse тоже). Наконец, просто используйте его вместо этого. Это также практически то, что P6Spy и консоль уже делают под капотом.