날짜 매핑

All lectures for KO purposes
레벨 1 , 레슨 843
사용 가능

4.1 역사 속으로의 소풍

Java 개체를 데이터베이스에 저장하는 작업은 Java 언어가 생성된 직후에 관련이 있었습니다. 당시 Java 언어에는 UNIX 시간 표준(1970년 이후의 밀리초 수)에 따라 시간을 저장하는 날짜라는 데이터 유형이 하나뿐이었습니다.

글쎄, 그 당시 데이터베이스에는 이미 날짜에 대한 다른 데이터 유형이 있었고 최소한 날짜, 시간 및 날짜 + 시간에 대한 별도의 유형이 있었습니다.

  • 날짜
  • 시간
  • 타임스탬프

따라서 Java 언어의 작성자는 클래스가 포함된 java.sql이라는 특수 패키지를 추가했습니다.

  • java.sql.날짜
  • java.sql.시간
  • java.sql.타임스탬프

이러한 클래스를 매핑하는 것은 정말 즐거운 일입니다.


@Entity
public class TemporalValues {
 
	@Basic
    private java.sql.Date sqlDate;
 
	@Basic
    private java.sql.Time sqlTime;
 
    @Basic
    private java.sql.Timestamp sqlTimestamp;
}

그러나 프로그래머들은 클래스로 작업하곤 했기 때문에 Hibernate는 Date 유형의 매핑을 제어하기 위해 java.util.Date특별한 주석을 추가했습니다 .@Temporal

예:

// If the annotation is missing, then the database will have a TIMESTAMP type
Date dateAsTimestamp;

@Temporal(TemporalType.DATE) // will be mapped to DATE type
Date dateAsDate;

@Temporal(TemporalType.TIME) // will be mapped to TIME type
Date dateAsTime;

유형 java.util.Calendarjava.util.Date기본 유형은 TIMESTAMP 유형을 사용하여 데이터베이스에서 이를 나타냅니다.

4.2 새로운 시간

현재 매핑을 사용하면 모든 것이 훨씬 간단하고 좋습니다. 모든 데이터베이스는 시간과 관련된 4가지 유형의 데이터를 지원합니다.

  • 날짜 - 날짜: 년, 월, 일.
  • TIME - 시간: 시, 분, 초.
  • TIMESTAMP - 날짜, 시간 및 나노초.
  • TIMESTAMP WITH TIME ZONE - TIMESTAMP 및 시간대(구역 이름 또는 오프셋).

유형을 나타내기 위해 날짜java.time.LocalDateJava에서는 JDK 8 DateTime API의 클래스를 사용해야 합니다 .

유형시간데이터베이스에서 Java의 두 가지 유형인 java.time.LocalTime및 로 나타낼 수 있습니다 java.time.OffsetTime. 복잡한 것은 없습니다.

그리고 유형으로 표시되는 정확한 날짜와 시간타임스탬프기본적으로 Java에서는 4가지 유형으로 나타낼 수 있습니다.

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

그리고 마지막으로시간대가 있는 타임스탬프두 가지 유형으로 나타낼 수 있습니다.

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

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

그것들을 매핑하는 것은 순수한 즐거움입니다.

@Basic
private java.time.LocalDate localDate;

@Basic
private java.time.LocalTime localTime;

@Basic
private java.time.OffsetTime offsetTime;

@Basic
private java.time.Instant instant;

@Basic
private java.time.LocalDateTime localDateTime;

@Basic
private java.time.OffsetDateTime offsetDateTime;

@Basic
private java.time.ZonedDateTime zonedDateTime;

주석은 @Basic필드가 자동 으로 처리되어야 함을 의미합니다 . Hibernate는 이 필드가 매핑되어야 하는 열과 유형을 결정합니다.

4.3 시간대 작업

시간대가 날짜의 일부인 경우 데이터베이스에 저장하는 것은 일반 날짜와 마찬가지로 간단합니다.

@Basic
private java.time.OffsetDateTime offsetDateTime;

@Basic
private java.time.ZonedDateTime zonedDateTime;

그러나 날짜와 별도로 시간대를 저장하려면 다음을 수행하십시오.

@Basic
private java.time.TimeZone timeZone;

@Basic
private java.time.ZoneOffset zonedOffset;

그런 다음 Hibernate는 기본적으로 VARCHAR 유형에 저장합니다. TimeZone에는 일반적으로 "UTC + 3" 또는 "Cairo"와 같은 문자열 이름이 있기 때문에 이는 논리적입니다.

4.4 나만의 시간대 설정

데이터베이스에 날짜를 저장하는 작업을 할 때 현재 시간대를 설정할 수 있는 위치가 이미 4개 있다는 사실을 알게 될 것입니다.

  • 서버 운영체제;
  • DBMS;
  • 자바 애플리케이션
  • 최대 절전 모드.

DBMS가 시간대(TimeZone)를 지정하지 않으면 운영 체제 설정에서 가져옵니다. 백업 DBMS는 자체 시간대가 있는 다른 데이터 센터에 있는 경우가 많기 때문에 이는 불편할 수 있습니다.

따라서 거의 모든 DBMS 관리자는 한 서버에서 다른 서버로 데이터를 쉽게 전송할 수 있도록 단일 영역을 설정합니다.

상황은 Java 애플리케이션과 유사합니다. 또한 다른 데이터 센터의 다른 서버에서 실행될 수 있으므로 일반적으로 명시적인 시간대가 있습니다.


java -Duser.timezone=UTC ...

또는 프로그램이 실행되는 동안:

TimeZone.setDefault(TimeZone.getTimeZone("UTC"));

그리고 물론 Hibernate는 시간대를 명시적으로 설정할 수 있게 해준다.

첫째, SessionFactory를 구성할 때 지정할 수 있습니다.

settings.put(
    AvailableSettings.JDBC_TIME_ZONE,
    TimeZone.getTimeZone("UTC")
);

둘째, 시간대를 지정할 수 있습니다.특정 세션에 대해:

Session session = sessionFactory()
    .withOptions()
    .jdbcTimeZone(TimeZone.getTimeZone("UTC"))
    .openSession();

4.5 @TimeZoneStorage 주석

프로그래머가 한 국가(및 한 시간대)에서 작업하는 것을 기반으로 데이터베이스 설계를 시작한 다음 몇 년 후에 다른 시간대에서 작업하기 위한 지원을 추가해야 하는 경우가 종종 있습니다.

따라서 시간대를 저장하기 위해 별도의 열을 데이터베이스에 추가했습니다. 이는 Hibernate가 특정 날짜의 TimeZone을 별도의 열에 저장할 수 있도록 하는 특수 주석을 추가한 일반적인 상황입니다.

예:

@TimeZoneStorage(TimeZoneStorageType.COLUMN)
@TimeZoneColumn(name = "birthday_offset_offset")
@Column(name = "birthday_offset")
private OffsetDateTime offsetDateTimeColumn;

@TimeZoneStorage(TimeZoneStorageType.COLUMN)
@TimeZoneColumn(name = "birthday_zoned_offset")
@Column(name = "birthday_zoned")
private ZonedDateTime zonedDateTimeColumn;

이것은 목발입니다. 그러나 이에 대한 변명도 있습니다. DateTime API가 아직 존재하지 않았을 때 나타났습니다. 그리고 클래스에 TimeZone을 저장하는 것은 불가능했습니다 java.util.Date.

나는 당신이 당신의 코드에서 이것을 자주 보지 않기를 정말로 바랍니다.

코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION