시간 경과에 따른 현재 상황

JDBC가 발명되고 인터페이스가 표준화된 이후 20년이라는 시간이 흘렀고 그 사이 많은 것이 변했다.

첫째, 세계는 글로벌화되었으며 이제 하나의 서버가 전 세계 사용자에게 서비스를 제공할 수 있습니다. 인터넷 속도가 빨라졌습니다. 따라서 다른 데이터 유형이 시간과 함께 작동하도록 SQL에 추가되었습니다 . 이제 유형은 다음과 같습니다.

  • DATE - 날짜를 저장합니다: 년, 월, 일.
  • TIME - 시간 저장: 시, 분, 초.
  • TIMESTAMP - 특정 시점(날짜, 시간 및 밀리초)을 저장합니다.
  • TIMESTAMP WITH TIME ZONE - TIMESTAMP 및 시간대(구역 이름 또는 오프셋).

둘째, Java는 전역 시간 관리를 위해 DateTime API를 도입했습니다. 다음과 같은 클래스가 있습니다.

  • 날짜 및 시간 :
    • 현지 날짜
    • 현지 시각
  • 정확한 순간 :
    • java.time.Instant
    • java.time.LocalDateTime
    • java.time.OffsetDateTime
    • java.time.ZonedDateTime
  • 시간대가 포함된 시간 :
    • java.time.OffsetDateTime
    • java.time.ZonedDateTime

세 번째 흥미로운 점은 많은 SQL 클라이언트가 이미 로컬 영역에 있는 서버에서 시간을 받기를 원한다는 것입니다 . 물론 즉석에서 시간을 변환할 수 있지만 편리하지 않고 실수가 있습니다.

예를 들어 데이터베이스에서 오늘의 모든 작업을 가져오고 싶습니다. SQL Server에는 이를 위한 CURDATE() 함수가 있습니다. 여기에서만 서버가 미국에 있고 저는 일본에 있습니다. 그리고 나는 그가 "그의 오늘"이 아니라 "나의 오늘"에 대한 모든 기록을 반환하기를 바랍니다.

일반적으로 SQL 서버는 다른 시간대에 있는 클라이언트와도 스마트하게 작업할 수 있어야 합니다.

현대 문제에는 현대적인 솔루션이 필요합니다

원칙적으로 Java DateTime API의 새 유형과 SQL의 유형을 편리하게 매핑할 수 있습니다. Java에서 DATE 유형을 나타내려면 JDK 8 DateTime API의 java.time.LocalDate 클래스를 사용해야 합니다 .

데이터베이스의 TIME 유형은 Java의 두 가지 유형인 java.time.LocalTimejava.time.OffsetTime 으로 나타낼 수 있습니다 . 복잡한 것도 없습니다.

데이터베이스에서 TIMESTAMP 유형 으로 표시되는 특정 시점은 Java에서 4가지 유형으로 표시될 수 있습니다.

  • java.time.Instant
  • java.time.LocalDateTime
  • java.time.OffsetDateTime
  • java.time.ZonedDateTime

마지막으로 TIMESTAMP WITH TIME ZONE은 두 가지 유형으로 나타낼 수 있습니다.

  • java.time.OffsetDateTime
  • java.time.ZonedDateTime

이미 DateTime API에 익숙하기 때문에 이 문제를 기억하는 것은 어렵지 않을 것입니다 :)

표 형식으로 작성하므로 더 쉬울 것입니다.

SQL 유형 자바 유형
날짜 java.time.LocalDate
시간 java.time.LocalTime
java.time.OffsetTime
타임스탬프 java.time.Instant
java.time.LocalDateTime
java.time.OffsetDateTime
java.time.ZonedDateTime
시간대가 있는 타임스탬프 java.time.OffsetDateTime
_

날짜 받기

좋은 소식이 있습니다. 오랜만에. java.sql 날짜 유형을 반환하는 getDate() 메서드 의 한계를 극복할 수 있습니다 .

요점은 개체결과 집합또 다른 흥미로운 방법이 있습니다 - getObject() . 이 메서드는 열과 유형의 두 매개 변수를 사용하고 지정된 유형으로 변환된 열의 값을 반환합니다. 방법의 일반적인 형식은 다음과 같습니다.

ClassName Name = getObject(column, ClassName);

그리고 DATE 유형을 java.time.LocalDate 유형 으로 변환하려면 다음과 같이 작성해야 합니다.

LocalDate localDate = results.getObject(4, LocalDate.class);

그리고 일반적으로 모든 TIMESTAMP는 여러 유형으로 변환될 수 있습니다.

java.time.Instant instant = results.getObject(9, java.time.Instant.class);
java.time.LocalDateTime local = results.getObject(9, java.time. LocalDateTime.class);
java.time.OffsetDateTime offset = results.getObject(9, java.time. OffsetDateTime.class);
java.time.ZonedDateTime zoned = results.getObject(9, java.time. ZonedDateTime.class);

중요한! 이 코드는 오래된 MySQL JDBC 드라이버가 있는 경우 작동하지 않습니다 . pom.xml에 작성되었거나 프로젝트 설정의 라이브러리에 추가된 "mysql-connector-java" 버전에 주의하십시오.

그건 그렇고, 같은 방식으로 기본 유형에 대해 null을 저장할 수 없는 문제를 해결할 수 있습니다. 테이블 열이 INT 유형인 경우 두 가지 방법으로 null을 가져올 수 있습니다. 아래 예를 참조하십시오.

Integer id1 = results.getObject(8, Integer.class);    	 // this will work
Integer id2 = results.getObject(8, int.class);                 //this will also work
int id3 = results.getObject(8,  Integer.class);            	//method will return null, JVM will throw NPE
int id4 = results.getObject(8,  int.class);                    	//method will return null, JVM will throw NPE

MySQL의 시간대 설정

MySQL에서도 많은 흥미로운 일들이 일어났습니다. 아시다시피 MySQL 연결을 생성할 때 다양한 매개변수를 추가할 수 있습니다 .
mysql://localhost:3306/db_scheme?Name=meaning&Name=meaning

따라서 MySQL에서 시간대 작업을 위해 세 개의 매개변수가 추가되었습니다. 서버에 대한 연결을 설정할 때 이러한 매개변수를 전달할 수 있습니다.

아래에서 나는 그들과 함께 표를 줄 것입니다 :

모수 가치 기본값
연결 시간대 지역 | 서버 | 사용자 영역 섬기는 사람
forceConnectionTimeZoneToSession 사실 | 거짓 진실
보존 인스턴스 사실 | 거짓 거짓

connectionTimeZone 매개변수를 사용하여 모든 요청이 실행될 시간대(시간대)를 선택합니다. 클라이언트의 관점에서 서버는 지정된 시간대로 실행됩니다.

forceConnectionTimeZoneToSession 매개변수 로 인해 세션 time_zone 변수가 무시되고 connectionTimeZone으로 대체됩니다.

마지막으로, preserveInstants 매개변수는 JVM의 timeZone과 connectionTimeZone 사이의 정확한 시간 변환을 제어합니다.

가장 일반적인 구성은 다음과 같습니다.

  • connectionTimeZone=LOCAL & forceConnectionTimeZoneToSession=false - useLegacyDatetimeCode=true인 이전 MySQL JDBC 드라이버 버전 5.1에 해당합니다.

  • connectionTimeZone=LOCAL & forceConnectionTimeZoneToSession=true는 날짜 및 시간 값을 처리하는 가장 자연스러운 방법을 제공하는 새로운 모드입니다.

  • connectionTimeZone=SERVER & preserveInstants=true - useLegacyDatetimeCode=false인 이전 MySQL JDBC 드라이버 버전 5.1에 해당합니다.

  • connectionTimeZone=user_defined & preserveInstants=true - 서버의 표준 시간대가 CET/CEST와 같은 일반 약어로 설정되어 커넥터에서 인식할 수 없는 상황을 극복하는 데 도움이 됩니다.

예, 날짜는 흥미로운 주제이며 많은 문제가 있습니다. 속담처럼 : 물론 무섭지 만 화도 안나요! :)