java.util.Date vs. java.sql.Date


답변:


585

축하합니다. JDBC : Date class handling으로 제가 가장 좋아하는 애완 동물을 맞이했습니다.

기본적으로 데이터베이스는 일반적으로 날짜, 시간 및 시간 소인 인 세 가지 형식의 날짜 시간 필드를 지원 합니다. 이것들 각각은 JDBC에 대응하는 클래스를 가지고 있으며 각각은 extendjava.util.Date 합니다. 이 세 가지 각각의 빠른 의미는 다음과 같습니다.

  • java.sql.DateSQL DATE에 해당합니다. 즉 , 시, 분, 초 및 밀리 초 는 무시 하고 연도, 월, 일 을 저장 합니다. 또한 sql.Date시간대와 관련이 없습니다.
  • java.sql.TimeSQL TIME에 해당하며 명백히 시, 분, 초 및 밀리 초 에 대한 정보 만 포함합니다 .
  • java.sql.Timestamp은 사용자 정의 가능한 정밀도로 나노초와 정확한 날짜 인 SQL TIMESTAMP util.Date해당합니다 (밀리 초 만 지원합니다! ).

이 세 가지 유형과 관련하여 JDBC 드라이버를 사용할 때 가장 일반적인 버그 중 하나는 유형이 잘못 처리된다는 것입니다. 이 수단 sql.Date시간대 특정는 sql.Time현재 연도, 월, 일 등등 등등이 포함되어 있습니다.

마지막으로 어느 것을 사용해야합니까?

실제로 필드의 SQL 유형에 따라 다릅니다. , for 및 for PreparedStatement#setDate()중 하나 인 세 값 모두에 대한 세터 가 있습니다.sql.Date#setTime()sql.Time#setTimestamp()sql.Timestamp

ps.setObject(fieldIndex, utilDateObject);실제로 사용하는 경우 util.Date대부분의 JDBC 드라이버에 일반 유형을 제공하여 올바른 유형 인 것처럼 행복하게 삼킬 수 있지만 나중에 데이터를 요청하면 실제로 누락 된 항목이 있음을 알 수 있습니다.

나는 실제로 날짜를 전혀 사용해서는 안된다고 말하고 있습니다.

내가 말하는 것은 밀리 초 / 나노 초를 평범한 길이로 저장하고 사용중인 모든 객체 ( 필수 조다 타임 플러그 ) 로 변환하는 것 입니다. 수행 할 수있는 하나의 해키 방법은 날짜 구성 요소를 다른 하나의 장기 및 구성 요소로 저장하는 것입니다 (예 : 현재 20100221 및 154536123).이 매직 넘버는 SQL 쿼리에 사용될 수 있으며 데이터베이스에서 다른 구성 요소로 이식 가능합니다. JDBC / Java Date API 의이 부분을 완전히 피할 수 있습니다.


17
좋은 대답입니다. 그러나 DBA에 대해 날짜를 조금 비우호적으로 저장하지 않습니까?
cherouvim

26
아마, 그러나 DBA는 : 일반적으로 RDBMS 직접 (그것에 대해없는 선택과 거부 모든 것을 자신의 RDBMS하는 경향이 s의 내가 당신을 찾고 있어요, 오라클 팬 ) Java 응용 프로그램은 그들 모두와 함께 작동하도록 기대하는 동안. 개인적으로 나는 논리를 DB에 전혀 넣고 싶지 않습니다.
Esko

2
내 mysql 열은 날짜 시간이지만 ps.setDate (new java.sql.Date (myObject.getCreatedDate (). getTime ())); 밀리 초 부분을 잃어 버렸습니다.이 문제를 해결하는 방법은 무엇입니까?
Blankman

2
밀리 초를 잃지 않기 위해 : 새로운 java.sql.Timestamp (utilDate.getTime ())
Kieveli

3
나는 그것이 사양에 따라해서는 안되는 것은 TZ에 특정한 버그 라고 언급했다 .
Esko 2016 년

60

늦은 편집 : Java 8부터는 피할 수 있거나 사용하지 java.util.Date않아야 java.sql.Date하며 대신 java.timeJoda 기반 패키지 를 선호 합니다. Java 8을 사용하지 않는 경우 원래 응답은 다음과 같습니다.


java.sql.Date-JDBC를 사용하는 라이브러리의 메소드 / 생성자를 호출 할 때. 아니, 그렇지. JDBC를 명시 적으로 처리하지 않는 응용 프로그램 / 모듈의 데이터베이스 라이브러리에 대한 종속성을 도입하지 않으려 고합니다.

java.util.Date-그것을 사용하는 라이브러리를 사용할 때. 그렇지 않으면 몇 가지 이유로 가능한 한 적게 :

  • 변경 가능하므로 메소드로 전달하거나 메소드에서 리턴 할 때마다 방어 사본을 작성해야합니다.

  • 날짜를 잘 처리하지 못하므로 실제로 당신과 같은 사람들은 날짜 처리 수업을해야한다고 생각합니다.

  • 이제 juD가 잘하지 않기 때문에 굉장히 많은 Calendar수업이 소개되었습니다. 또한 변경 가능하고 작업하기가 끔찍하며, 선택 사항이 없으면 피해야합니다.

  • Joda Time API 와 같은 더 나은 대안 이 있습니다 ( Java 7로 만들 수도 있고 새로운 공식 날짜 처리 API가 될 수도 있습니다 - 빠른 검색 은 그렇지 않습니다).

Joda와 같은 새로운 의존성을 도입하는 것이 과도하다고 생각한다면 long객체의 타임 스탬프 필드에 사용하는 것이 나쁘지는 않습니다.하지만 일반적으로 객체를 전달할 때 jud로 감싸거나 유형 안전과 문서로 사용합니다.


5
데이터베이스에 저장할 때 java.sql보다 java.time을 선호해야하는 이유는 무엇입니까? 나는 성명서에서 정말로 흥미롭지 만 왜 그런지 이해하고 싶다 :)
Jean-François Savard

@ Jean-FrançoisSavard 나는 당신이 그 의견을 게시 한 이후 질문에 대한 답변을 찾았기를 바랍니다. 그러나 여기에 완전성을위한 답변이 있습니다 : 그것은 여전히 ​​완벽하게 OK java.sql.Date 입니다 PreparedStatement! 그러나 당신이 그것을 지나갈 때, 당신이 LocalDate사용 java.sql.Date.valueOf하고 변환 java.sql.Date.valueOf할 때 사용하는 변환을 사용 하고 가능한 한 빨리 다시 변환하십시오 java.sql.Date.toLocalDate -java.sql을 가능한 한 적게 관련시키고 변경하기 때문에 가능합니다.
gustafc

19

사용하는 유일한 시간 java.sql.Date은입니다 PreparedStatement.setDate. 그렇지 않으면을 사용하십시오 java.util.Date. 는를 ResultSet.getDate반환한다고 java.sql.Date말하지만 a 에 직접 할당 할 수 있습니다 java.util.Date.


3
Ehm, ResultSet # getDate ()는 sql.Date (util.Date를 확장)를 반환합니다.
에스코

3
@Esko는 - "흠은"나는 당신이 주석 전에 (그리고을 downvoted)한다는 고정.
Paul Tomblin

1
java.sql.Date가 java.util.Date에 지정 될 수있는 이유는 첫 번째가 두 번째의 서브 클래스이기 때문입니다.
dj18

2
전자가 후자를 확장 할 때에 java.sql.Date할당 될 수 있다는 것이 왜 '알고' java.util.Date있습니까? 당신이 만들고자하는 요점이 무엇입니까?
Lorne의 후작

11

나는 같은 문제가 있었다. 현재 날짜를 준비된 진술에 삽입하는 가장 쉬운 방법은 다음과 같다.

preparedStatement.setDate(1, new java.sql.Date(new java.util.Date().getTime()));

2
이것으로 시간대를 얻을 수 없습니다.
erhanasikoglu

4

tl; dr

둘 다 사용하지 마십시오.

둘 다

java.util.Date vs. java.sql.Date : 언제, 왜 사용합니까?

이 두 클래스는 끔찍하고 디자인과 구현에 결함이 있습니다. 전염병 코로나 바이러스 처럼 피하십시오 .

대신 JSR 310에 정의 된 java.time 클래스를 사용 하십시오. 이 클래스는 날짜-시간 처리 작업을위한 업계 최고의 프레임 워크입니다. 이 대신하는 완전히 피 묻은 끔찍한 기존 클래스와 같은 Date, Calendar, SimpleDateFormat, 등을.

java.util.Date

첫 번째 java.util.Date는 UTC의 순간을 나타내는 것으로, UTC에서 0 시간-분-초의 오프셋을 의미합니다.

java.time.Instant

이제로 대체되었습니다 java.time.Instant.

Instant instant = Instant.now() ;  // Capture the current moment as seen in UTC.

java.time.OffsetDateTime

Instantjava.time 의 기본 빌딩 블록 클래스입니다 . 더 유연성을 위해 사용 OffsetDateTime으로 설정 ZoneOffset.UTCUTC의 순간을 나타내는 : 같은 목적을 위해.

OffsetDateTime odt = OffsetDateTime.now( ZoneOffset.UTC ) ;

당신은 사용하여 데이터베이스에이 객체를 보낼 수 PreparedStatement::setObjectJDBC 이후 4.2.

myPreparedStatement.setObject(  , odt ) ;

검색.

OffsetDateTime odt = myResultSet.getObject(  , OffsetDateTime.class ) ;

java.sql.Date

java.sql.Date클래스는 끔찍한 및 사용되지 않습니다.

이 클래스는 시간과 시간대가없는 날짜 만 나타냅니다. 불행히도, 디자인의 끔찍한 해킹 에서이 클래스는 java.util.Date순간 (UTC로 날짜를 나타내는 날짜)을 나타내는 상속 합니다. 따라서이 클래스는 단순히 날짜 전용 인 것처럼 보이지만 실제로는 UTC로 암시 적으로 오프셋됩니다. 이것은 너무 많은 혼란을 야기합니다. 이 클래스를 사용하지 마십시오.

java.time.LocalDate

대신 java.time.LocalDate시간이나 시간대 또는 오프셋없이 날짜 (년, 월, 일) 만 추적 하는 데 사용하십시오 .

ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
LocalDate ld = LocalDate.now( z ) ;    // Capture the current date as seen in the wall-clock time used by the people of a particular region (a time zone).

데이터베이스에 전송합니다.

myPreparedStatement.setObject(  , ld ) ;

검색.

LocalDate ld = myResultSet.getObject(  , LocalDate.class ) ;

Java (레거시 및 현대) 및 표준 SQL의 날짜-시간 유형 테이블


java.time에 대하여

java.time의 프레임 워크는 나중에 자바 8에 내장되어 있습니다. 이 클래스는 까다로운 기존에 대신 기존 과 같은 날짜 - 시간의 수업을 java.util.Date, Calendar, SimpleDateFormat.

자세한 내용은 Oracle Tutorial을 참조하십시오 . 많은 예제와 설명을 보려면 스택 오버플로를 검색하십시오. 사양은 JSR 310 입니다.

Joda 타임 프로젝트는 지금에 유지 관리 모드 의로 마이그레이션을 조언 java.time의 클래스.

java.time 객체를 데이터베이스와 직접 교환 할 수 있습니다 . JDBC 4.2 이상을 준수 하는 JDBC 드라이버를 사용하십시오 . 문자열이 필요없고 수업이 필요 없습니다 .java.sql.*

java.time 클래스는 어디서 구할 수 있습니까?

Java 또는 Android 버전과 함께 사용할 java.time 라이브러리 표


1
Plague reference를 Corona virus로 대체하기위한 공감 더 관련성이 높아졌습니다.
ankuranurag

2

Java의 java.util.Date 클래스는 특정 시점 (예 : 2013 년 11 월 25 일 16:30:45에서 밀리 초까지)을 나타내지 만 DB의 DATE 데이터 유형은 날짜 만 나타냅니다 (예 : 2013 년 11 월 25 일). 실수로 DB에 java.util.Date 오브젝트를 제공하지 못하게하기 위해 Java에서는 SQL 매개 변수를 java.util.Date로 직접 설정할 수 없습니다.

PreparedStatement st = ...
java.util.Date d = ...
st.setDate(1, d); //will not work

그러나 여전히 강제 / 의도로 그렇게 할 수 있습니다 (그러면 시간과 분은 DB 드라이버에서 무시됩니다). 이것은 java.sql.Date 클래스로 수행됩니다.

PreparedStatement st = ...
java.util.Date d = ...
st.setDate(1, new java.sql.Date(d.getTime())); //will work

java.sql.Date 객체는 특정 시점을 저장할 수 있으므로 (java.util.Date에서 쉽게 구성 할 수 있음) 몇 시간 동안 요청하면 예외가 발생합니다 ( 날짜 만). DB 드라이버는이 클래스를 인식하고 시간 동안 0을 사용합니다. 이 시도:

public static void main(String[] args) {
  java.util.Date d1 = new java.util.Date(12345);//ms since 1970 Jan 1 midnight
  java.sql.Date d2 = new java.sql.Date(12345);
  System.out.println(d1.getHours());
  System.out.println(d2.getHours());
}

0

java.util.Date밀리 초 단위로 특정 순간을 나타냅니다. 시간대가없는 날짜 및 시간 정보를 나타냅니다. java.util.Date 클래스는 Serializable, Cloneable 및 Comparable 인터페이스를 구현합니다. 그것은 상속 java.sql.Date, java.sql.Timejava.sql.Timestamp인터페이스.

java.sql.Date시간 정보없이 날짜를 나타내는 java.util.Date 클래스를 확장하며 데이터베이스를 처리 할 때만 사용해야합니다. SQL DATE의 정의를 준수하려면 java.sql.Date인스턴스와 연관된 특정 시간대에서 시간, 분, 초 및 밀리 초를 0으로 설정하여 인스턴스에 의해 랩핑 된 밀리 초 값을 '정규화'해야합니다.

그것은 모든 public 메소드 상속 java.util.Date등을 getHours(), getMinutes(), getSeconds(), setHours(), setMinutes(), setSeconds(). 으로는 java.sql.Date그것의 모든 시간 작업을 무시, 시간 정보를 저장하지 않는 java.util.Date이들 방법 모두 던져 java.lang.IllegalArgumentException자신의 구현 세부 사항에서 증거로 호출합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.