Java.util.Date vs java.SQL.Date

java.util.Date vs java.sql.Date : quand et pourquoi utiliser?

456
demandé sur Jonas 2010-02-21 16:16:40
la source

5 ответов

félicitations, vous avez frappé mon préféré pet peeve avec JDBC: Date class handling.

fondamentalement, les bases de données prennent généralement en charge au moins trois formes de champs datetime qui sont date, heure et horodatage. Chacun d'eux ont une classe correspondante dans JDBC et chacun d'eux étendent java.util.Date . La sémantique rapide de chacun de ces trois termes est la suivante:

  • java.sql.Date correspond à la date SQL qui signifie qu'il stocke années, mois et jours tandis que Heure, minute, seconde et milliseconde sont ignorés. De plus sql.Date n'est pas lié aux fuseaux horaires.
  • java.sql.Time correspond au temps SQL et comme devrait être évident, contient seulement des informations sur heure, minutes, secondes et millisecondes .
  • java.sql.Timestamp correspond à L'horodatage SQL qui est la date exacte de la nanoseconde ( notez que util.Date supporte seulement les millisecondes! ) avec une précision personnalisable.

L'un des bugs les plus fréquents lors de l'utilisation des pilotes JDBC en relation avec ces trois types est que les types ne sont pas manipulés correctement. cela signifie que sql.Date est en fonction du fuseau horaire, sql.Time contient l'année, le mois et le jour en cours, etc.

Enfin: Lequel utiliser?

dépend du type SQL du champ, vraiment. PreparedStatement a des réglages pour les trois valeurs, #setDate() étant celui de sql.Date , #setTime() pour sql.Time et #setTimestamp() pour sql.Timestamp .

notez que si vous utilisez ps.setObject(fieldIndex, utilDateObject); vous pouvez réellement donner une util.Date à la plupart des pilotes JDBC qui le dévoreront avec plaisir comme s'il s'agissait du bon type, mais lorsque vous demanderez les données par la suite, vous remarquerez peut-être que vous manquez des choses.

je dis vraiment qu'aucune des Dates ne devrait être utilisée du tout.

ce que je dis qui sauver les millisecondes / nanosecondes comme simples longs et les convertir à tous les objets que vous utilisez ( Joda-Time obligatoire plug ). Une façon hacky qui peut être fait est de stocker le composant date comme un long et le composant temps comme un autre, par exemple dès maintenant serait 20100221 et 154536123. Ces nombres magiques peuvent être utilisés dans les requêtes SQL et seront transférables d'une base de données à une autre et vous permettront d'éviter complètement cette partie de L'API Date JDBC/Java.

543
répondu Esko 2015-03-04 22:21:52
la source

édition tardive: à partir de Java 8, Vous ne devez utiliser ni java.util.Date ni java.sql.Date si vous pouvez l'éviter, et préférez plutôt utiliser le paquet java.time (basé sur Joda) plutôt que n'importe quoi d'autre. Si vous N'êtes pas sur Java 8, Voici la réponse originale:


java.sql.Date - lorsque vous appelez des méthodes / constructeurs de bibliothèques qui l'utilisent (comme JDBC). Non pas le contraire. Vous ne voulez pas introduire de dépendances aux bibliothèques de base de données pour les applications / modules qui ne traitent pas explicitement avec JDBC.

java.util.Date - lorsque vous utilisez des bibliothèques qui l'utilisent. Autrement, aussi peu que possible, pour plusieurs raisons:

  • c'est mutable, ce qui signifie que vous devez en faire une copie défensive à chaque fois que vous la Passez ou la retournez d'une méthode.

  • il ne gère pas très bien les dates, qui à l'envers les gens comme le vôtre truly, pensent que les classes de manipulation de date devrait.

  • maintenant, parce que J. U. D ne fait pas très bien son travail, les terribles classes Calendar ont été introduites. Ils sont également mutables, et affreux de travailler avec, et devrait être évitée si vous n'avez pas le choix.

  • Il ya mieux alternatives, comme le Joda Time API ( qui pourrait même le faire en Java 7 et devenir la nouvelle date officielle de manipulation API - a quick search dit qu'il ne sera pas).

si vous pensez qu'il est exagéré d'introduire une nouvelle dépendance comme Joda, long s ne sont pas si mauvais à utiliser pour les champs de timestamp dans les objets, bien que je moi-même habituellement envelopper dans J. U. D Lors de leur passage autour, pour la sécurité de type et comme documentation.

52
répondu gustafc 2017-05-23 15:26:38
la source

le seul moment pour utiliser java.sql.Date est dans un PreparedStatement.setDate . Sinon, utilisez java.util.Date . Il est dit que ResultSet.getDate renvoie un java.sql.Date mais il peut être assigné directement à un java.util.Date .

17
répondu Paul Tomblin 2016-08-30 19:45:02
la source

j'ai eu le même problème, la façon la plus facile que j'ai trouvé pour insérer la date actuelle dans une déclaration préparée est celle-ci:

preparedStatement.setDate(1, new java.sql.Date(new java.util.Date().getTime()));
10
répondu Israelm 2014-07-17 00:16:24
la source

La java.util.La classe Date en Java représente un moment particulier dans le temps (e,.G., 2013 Nov 25 16: 30: 45 down to millisecondes), mais le type de données DATE dans le DB représente une date seulement (par exemple, 2013 Nov 25). Pour vous empêcher de fournir un java.util.Date objet à la base de données par erreur, Java ne vous permet pas de définir un paramètre SQL à java.util.Date directement:

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

mais il vous permet toujours de le faire par force / intention (alors heures et minutes seront ignoré par le pilote de base de données). Cela se fait avec le java.SQL.Classe de Date:

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

Une java.SQL.L'objet Date peut stocker un moment dans le temps (de sorte qu'il est facile de construire à partir d'un java.util.Date) mais va jeter une exception si vous essayez de lui demander pour les heures (pour renforcer son concept d'être une date seulement). On s'attend à ce que le pilote de freinage rhéostatique reconnaisse cette classe et utilise seulement 0 pour les heures. Essayez ceci:

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());
}
2
répondu Kent Tong 2013-11-22 08:26:17
la source

Autres questions sur