ТЛ; др
myPreparedStatement.setObject(
… ,
LocalDate.parse( "2018-11-20")
) ;
Подробнее
Вы используете ужасно разработанный класс java.sql.Date
. Этот класс, к сожалению, является подклассом java.util.Date
, хотя документация странным образом говорит нам игнорировать этот факт наследования. Таким образом, в то время как java.sql.Date
делает вид, что представляет только дату, на самом деле это момент, дата с временем суток, установленным на полночь в некоторой зоне и затем настроенным на UTC. Это ужасный дизайн, и это одна из многих причин, по которым никогда не следует использовать устаревшие классы даты и времени.
Для столбца DATE
в SQL используйте современный класс LocalDate
.
LocalDate
Класс LocalDate
действительно представляет значение только для даты, без времени суток и без часового пояса или смещения от UTC .
Для столбца базы данных типа, подобного стандарту SQL DATE
, используйте класс LocalDate
в Java.
LocalDate ld = LocalDate.parse( "2018-11-20" );
JDBC 4.2
Начиная с JDBC 4.2, мы можем напрямую обмениваться объектами java.time с базой данных.
myPreparedStatement.setObject( … , ld ) ;
индексирование:
LocalDate ld = myResultSet.getObject( … , LocalDate.class ) ;
Без учета часового пояса полученное значение будет таким же 2018-11-20
, которое вы сохранили.
Пример приложения
Вот полный пример приложения, использующего H2 Database Engine . В качестве демонстрации я настроил запись в базу данных в памяти, а не на сохранение в реальном хранилище.
Мы создаем базу данных с одной таблицей, с двумя столбцами:
- первичный ключ с порядковым номером с именем
pkey_
- a
DATE
столбец с именем when_
Мы вставляем пару LocalDate
объектов, а затем извлекаем строки для выгрузки в консоль.
package com.basilbourque.example;
import java.sql.*;
import java.time.LocalDate;
import java.util.List;
public class EventDate {
public static void main ( String[] args ) {
EventDate app = new EventDate();
app.doIt();
}
private void doIt ( ) {
final String driverName = "org.h2.Driver";
final String catalogName = "event_demo_db";
final String jdbcPath = "jdbc:h2:mem:" + catalogName + ";DB_CLOSE_DELAY=-1"; // Set delay to keep in-memory database even after last connection closed.
// Verify JDBC driver.
try {
Class.forName( driverName );
} catch ( ClassNotFoundException e ) {
e.printStackTrace();
}
// Connect, and create database.
try (
Connection conn = DriverManager.getConnection( jdbcPath ) ;
) {
String sql = null;
// Create table.
try ( Statement stmt = conn.createStatement() ; ) {
sql = "CREATE TABLE " + "event_" + " ( \n" +
" pkey_ IDENTITY PRIMARY KEY , \n" +
" when_ DATE NOT NULL \n" +
") ; \n";
System.out.println( "TRACE - SQL:\n" + sql );
stmt.execute( sql );
}
System.out.println( "TRACE - Created table `event_`." );
// Add rows
sql = "INSERT INTO event_ ( when_ ) \n" +
"VALUES ( ? ) " +
"; ";
List < LocalDate > dates = List.of( LocalDate.parse( "2018-11-10" ) , LocalDate.parse( "2018-12-31" ) );
System.out.println( "Inserting list of LocalDate objects: " + dates );
try (
PreparedStatement ps = conn.prepareStatement( sql ) ;
) {
for ( LocalDate localDate : dates ) {
ps.setObject( 1 , localDate );
ps.executeUpdate();
}
}
// Retrieve rows
sql = "SELECT * FROM " + "event_" + " ;";
try (
Statement stmt = conn.createStatement() ;
ResultSet rs = stmt.executeQuery( sql ) ;
) {
while ( rs.next() ) {
int pkey = rs.getInt( "pkey_" );
LocalDate when = rs.getObject( "when_" , LocalDate.class );
System.out.println( "Row pkey_: " + pkey + " when_: " + when );
}
}
} catch ( SQLException e ) {
e.printStackTrace();
}
}
}
При запуске.
Вставка списка объектов LocalDate: [2018-11-10, 2018-12-31]
Строка pkey_: 1 когда_: 2018-11-10
Строка pkey_: 2 когда_: 2018-12-31
О java.time
Платформа java.time встроена в Java 8 и более поздние версии. Эти классы вытесняют проблемные старые устаревшие классы даты и времени, такие как java.util.Date
, Calendar
, & SimpleDateFormat
.
Проект Joda-Time , теперь в режиме обслуживания , рекомендует выполнить переход на классы java.time .
Чтобы узнать больше, см. Oracle Tutorial . И поиск переполнения стека для многих примеров и объяснений. Спецификация JSR 310 .
Вы можете обмениваться java.time объектами напрямую с вашей базой данных. Используйте драйвер JDBC , совместимый с JDBC 4.2 или более поздней версии. Нет необходимости в строках, нет необходимости в java.sql.*
классах.
Где получить классы java.time?
Проект ThreeTen-Extra расширяет java.time дополнительными классами. Этот проект является полигоном для возможных будущих дополнений к java.time. Здесь вы можете найти некоторые полезные классы, такие как Interval
, YearWeek
, YearQuarter
и more .