Choosing between java.util.Date or java.sql.Date

前端 未结 4 1561
-上瘾入骨i
-上瘾入骨i 2020-12-14 09:52

Should I use java.util.Date or java.sql.Date?

I have a VisualFox database and I have retrieved the entities with the IntelliJ Idea wizard using an appropiate jdbc ty

相关标签:
4条回答
  • 2020-12-14 10:02

    In general, I find it advisable to use the java.util.Date, since you can use it anywhere in your program without either converting the type or polluting your application with SQL-specific code.

    I am not aware of a scenario where 'java.sql.Date' would be a better fit.

    0 讨论(0)
  • 2020-12-14 10:06

    According to Java doc, it is suggested to use appropriate Date type as per underlying database. However, with Java 8, a rich set of classes under java.time package have been provided and it must be used if application is written with Java 8.

    The class javaxjava.sql.Date extends java.util.Date with minor changes for miliseconds container so that it can support the Database DATE type effectively. This, we can save the @Temporal annotation typing from entity class.

    However, java.util.Date could be used for better scalability in entire application so that it can be easily used to store time along with date.

    0 讨论(0)
  • 2020-12-14 10:12

    tl;dr

    Should I use java.util.Date or java.sql.Date?

    Neither.

    Both are obsolete as of JDBC 4.2 and later. Use java.time classes instead.

    • date-only value
      For a database type akin to SQL-standard DATE, use java.time.LocalDate.
      • LocalDate ld = myResultSet.getObject( … , LocalDate.class ) ;
      • myPreparedStatement.setObject( ld , … ) ;
    • date with time-of-day in UTC value
      For a database type akin to SQL-standard TIMESTAMP WITH TIME ZONE, use java.time.Instant.
      • Instant instant = myResultSet.getObject( … , Instant.class ) ;
      • myPreparedStatement.setObject( instant , … ) ;

    Details

    The question and other answers seem to be over-thinking the issue. A java.sql.Date is merely a java.util.Date with its time set to 00:00:00.

    From the java.sql.Date doc (italicized text is mine)…

    Class Date

    java.lang.Object

        java.util.Date        ← Inherits from j.u.Date

            java.sql.Date

    A thin wrapper around a millisecond value that allows JDBC to identify this as an SQL DATE value. A milliseconds value represents the number of milliseconds that have passed since January 1, 1970 00:00:00.000 GMT.  ← Time-of-day set to Zero, midnight GMT/UTC

    To conform with the definition of SQL DATE, the millisecond values wrapped by a java.sql.Date instance must be 'normalized' by setting the hours, minutes, seconds, and milliseconds to zero in the particular time zone with which the instance is associated.

    Date-Only versus Date-Time

    The core problem is:

    • SQL
      In SQL, the DATE data type stores a date-only, without a time-of-day.
    • JAVA
      In the badly designed date-time library bundled with the early versions of Java, they failed to include a class to represent a date-only.

    Instead of creating a date-only class, the Java team made a terrible hack. They took their date-time class (the misnamed java.util.Date class, containing both date and time) and extended it to have an instance set its time-of-day to midnight UTC, 00:00:00. That hack, that subclass of j.u.Date, is java.sql.Date.

    All this hacking, poor design, and misnaming has made a confusing mess.

    Which To Use

    So when to use which? Simple, after cutting through the confusion.

    • When reading or writing to a database’s date-only column, use java.sql.Date as it clumsily tries to mask its time-of-day.
    • Everywhere else in Java, where you need a time-of-day along with your date, use java.util.Date.
    • When you have a java.sql.Date in hand but need a java.util.Date, simply pass the java.sql.Date. As a subclass, a java.sql.Date is a java.util.Date.

    Even Better

    In modern Java, you now have a choice of decent date-time libraries to supplant the old and notoriously troublesome java.util.Date, Calendar, SimpleTextFormat, and java.sql.Date classes bundled with Java. The main choices are:

    • Joda-Time
    • java.time
      (inspired by Joda-Time, defined by JSR 310, bundled with Java 8, extended by the ThreeTen-Extra project)

    Both offer a LocalDate class to represent a date only, with no time-of-day and no time zone.

    A JDBC driver updated to JDBC 4.2 or later can be used to directly exchange java.time objects with the database. Then we can completely abandon the ugly mess that is the date-time classes in the java.util.* and java.sql.* packages.

    setObject | getObject

    This article published by Oracle explains that the JDBC in Java 8 has been updated transparently to map a SQL DATE value to the new java.time.LocalDate type if you call getObject and setObject methods.

    In obtuse language, the bottom of the JDBC 4.2 update spec confirms that article, with new mappings added to the getObject and setObject methods.

    myPreparedStatement.setObject( … , myLocalDate ) ;
    

    …and…

    LocalDate myLocalDate = myResultSet.getObject( … , LocalDate.class ) ;
    

    Convert

    The spec also says new methods have been added to the java.sql.Date class to convert back and forth to java.time.LocalDate.

    • public java.time.instant toInstant()
    • public java.time.LocalDate toLocalDate()
    • public static java.sql.Date valueOf(java.time.LocalDate)

    Time Zone

    The old java.util.Date, java.sql.Date, and java.sql.Timestamp are always in UTC. The first two (at least) have a time zone buried deep in their source code but is used only under-the-surface such as the equals method, and has no getter/setter.

    More confusingly, their toString methods apply the JVM’s current default time zone. So to the naïve programmer it seems like they have a time zone but they do not.

    Both the buried time zone and the toString behavior are two of many reasons to avoid these troublesome old legacy classes.

    Write your business logic using java.time (Java 8 and later). Where java.time lacks, use Joda-Time. Both java.time and Joda-Time have convenient methods for going back and forth with the old classes where need be.

    Replacements:

    • java.util.Date is replaced by java.time.Instant
    • java.sql.Timestamp is replaced by java.time.Instant
    • java.sql.Date is replaced by java.time.LocalDate.
    • java.sql.Time is replaced by java.time.LocalTime.

    The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).

    All three java.time.Local… classes are all lacking any concept of time zone or offset-from-UTC.


    About java.time

    The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

    The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

    To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

    You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.

    Where to obtain the java.time classes?

    • Java SE 8, Java SE 9, Java SE 10, and later
      • Built-in.
      • Part of the standard Java API with a bundled implementation.
      • Java 9 adds some minor features and fixes.
    • Java SE 6 and Java SE 7
      • Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
    • Android
      • Later versions of Android bundle implementations of the java.time classes.
      • For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….

    The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

    0 讨论(0)
  • 2020-12-14 10:21

    Well, according to this article you can use javax.sql.Date without @Temporal annotation which can save some coding from you. However java.util.Date is easier to use across your whole application.

    So I would use

    @Column(name = "date")
    @Temporal(TemporalType.DATE)
    private java.util.Date date;
    
    0 讨论(0)
提交回复
热议问题