vs
: quand utiliser qui et pourquoi ?
Réponses
Trop de publicités?Félicitations, vous avez touché mon préféré bête noire avec JDBC: Date de la gestion de classe.
Fondamentalement, les bases de données prennent généralement en charge d'au moins trois formes de datetime champs qui sont la date, l'heure et la date. Chacun d'eux a un correspondant de la classe JDBC et chacun d'eux s'étendre java.util.Date
. Rapide de la sémantique de chacun de ces trois sont les suivantes:
-
java.sql.Date
correspond à SQL DATE qui signifie qu'il stocke les années, les mois et les jours tandis que les heures, les minutes, les secondes et les millisecondes sont ignorés. En outre,sql.Date
n'est pas liée à des fuseaux horaires. -
java.sql.Time
correspond à SQL TEMPS et comme cela devrait être évident, ne contient que les informations sur les heures, les minutes, les secondes et les millisecondes. -
java.sql.Timestamp
correspond à SQL TIMESTAMP qui est la date exacte de l'ordre de la nanoseconde (notez queutil.Date
prend uniquement en charge les millisecondes!) avec personnalisable de précision.
Un des plus fréquents bugs dans les pilotes JDBC dans le cadre de ces trois types est que les types ne sont pas traitées correctement. Cela signifie qu' sql.Date
est le fuseau horaire spécifique, sql.Time
contient de l'année en cours, le mois et le jour, et cetera, et cetera.
Enfin: Lequel utiliser?
Dépend du type SQL du champ, vraiment. PreparedStatement
a-setters pour tous les trois valeurs, #setDate()
étant l'un pour l' sql.Date
, #setTime()
pour sql.Time
et #setTimestamp()
pour sql.Timestamp
.
Notez que si vous utilisez ps.setObject(fieldIndex, utilDateObject);
vous pouvez effectivement donner un normal util.Date
pour la plupart des pilotes JDBC qui seront heureux de vous dévorer, comme si c'était du type correct, mais lorsque vous demandez les données par la suite, vous remarquerez peut-être que vous êtes réellement en manque des trucs.
Je suis vraiment en disant qu'aucun des Dates doit être utilisé à tout.
Ce que je suis en train de dire que sauver les millisecondes/nanosecondes, la plaine de longs et de les convertir en ce que les objets que vous utilisez (obligatoire joda-time plug). Un hacky manière qui peut être fait est de stocker la date composant comme un long et composant comme un autre, par exemple en ce moment serait 20100221 et 154536123. Ces nombres magiques peuvent être utilisées dans des requêtes SQL et sera portable à partir de la base de données à l'autre et qui vous permettra d'éviter cette partie de JDBC/Java Date de l'API:s entièrement.
java.sql.Date
- lorsque vous appelez les méthodes/constructeurs de bibliothèques qui l'utilisent (comme JDBC). Non pas le contraire. Vous ne voulez pas introduire des dépendances pour les bibliothèques de base de données pour les applications/modules qui ne sont pas explicitement traiter avec JDBC.
java.util.Date
- lors de l'utilisation de bibliothèques qui l'utilisent. Sinon, aussi peu que possible, et ce pour plusieurs raisons:
C'est mutable, ce qui signifie que vous avez à faire une défensive copie de celui-ci chaque fois que vous passez à retourner ou à partir d'une méthode.
Il ne gère pas les dates très bien, ce qui renverse les gens aiment sincèrement, pensez à la date de la manipulation des classes.
Maintenant, parce que j.u.D ne pas le faire c'est le travail très bien, les affreux
Calendar
des classes ont été introduites. Ils sont aussi mutable, et terrible de travailler avec, et doit être évitée si vous n'avez pas le choix.Il existe de meilleures alternatives, comme le Joda Time API (
qui pourrait même faire ça en Java 7 et devenir la nouvelle date officielle de la manipulation de l'API- une recherche rapide dit qu'il ne va pas).
Si vous vous sentez que c'est trop d'introduire une nouvelle dépendance comme Joda, long
s ne sont pas si mauvais que ça à utiliser pour les champs d'horodatage dans les objets, bien que j'ai moi-même généralement les envelopper dans j.u.D lors de leur passage autour de, pour la sécurité du type et de la documentation.
La java.util.Date de classe en Java représente un moment particulier dans le temps (e,.g., 2013 Nov 25 16:30:45 vers le bas à quelques millisecondes), mais le type de données DATE dans la base de données représente une date (par exemple, 2013 Nov 25). Pour vous empêcher de vous fournir un java.util.Date objet de la DB par erreur, Java ne permet pas de définir un paramètre SQL en java.util.Date directement:
PreparedStatement st = ...
java.util.Date d = ...
st.setDate(1, d); //will not work
Mais elle permet tout de même de le faire par la force/l'intention (puis les heures et les minutes seront ignorés par le pilote de base de données). Cela se fait avec le java.sql.Classe Date:
PreparedStatement st = ...
java.util.Date d = ...
st.setDate(1, new java.sql.Date(d.getTime())); //will work
Un java.sql.Date objet peut stocker un moment dans le temps (de sorte qu'il est facile à construire à partir de java.util.La Date) mais lève une exception si vous essayez de lui demander pour le nombre d'heures (à appliquer son concept d'être un jour le seul). Le pilote de base de données devrait reconnaître cette classe et il suffit d'utiliser 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());
}