Utilisation de setDate dans la préparation

afin de rendre notre code plus standard, nous avons été invités à changer tous les endroits où nous avons hardcoded nos variables SQL à des déclarations préparées et à lier les variables à la place.

je suis cependant confronté à un problème avec le setDate() .

voici le code:

        DateFormat dateFormatYMD = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
        DateFormat dateFormatMDY = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
        Date now = new Date();
        String vDateYMD = dateFormatYMD.format(now);
        String vDateMDY = dateFormatMDY.format(now);
        String vDateMDYSQL =  vDateMDY ;
        java.sql.Date date = new java.sql.Date(0000-00-00);

   requestSQL = "INSERT INTO CREDIT_REQ_TITLE_ORDER (REQUEST_ID," + 
                " ORDER_DT, FOLLOWUP_DT) " +  "values(?,?,?,)";


                prs = conn.prepareStatement(requestSQL);

                prs.setInt(1,new Integer(requestID));

                prs.setDate(2,date.valueOf(vDateMDYSQL));
                prs.setDate(3,date.valueOf(sqlFollowupDT));

j'obtiens cette erreur quand le SQL est exécuté:

    java.lang.IllegalArgumentException
    at java.sql.Date.valueOf(Date.java:138)
    at com.cmsi.eValuate.TAF.TAFModuleMain.CallTAF(TAFModuleMain.java:1211)

si j'utilise setString() à la place de to_date() ?

36
demandé sur Kevin Panko 2013-09-04 17:12:26

6 réponses

utilisation de java.sql.Date

si votre table a une colonne de type DATE :

  • java.lang.String

    La méthode java.sql.Date.valueOf(java.lang.String) a reçu une chaîne de caractères représentant une date au format yyyy-[m]m-[d]d . par exemple:

    ps.setDate(2, java.sql.Date.valueOf("2013-09-04"));
    
  • java.util.Date

    supposons que vous ayez une variable endDate de type java.util.Date , vous faites la conversion ainsi:

    ps.setDate(2, new java.sql.Date(endDate.getTime());
    
  • Actuel

    si vous voulez insérer la date actuelle:

    ps.setDate(2, new java.sql.Date(System.currentTimeMillis()));
    
    // Since Java 8
    ps.setDate(2, java.sql.Date.valueOf(java.time.LocalDate.now()));
    

utilisation de java.sql.Timestamp

si votre table a une colonne de type TIMESTAMP ou DATETIME :

  • java.lang.String

    La méthode java.sql.Timestamp.valueOf(java.lang.String) a reçu une chaîne de caractères représentant une date au format yyyy-[m]m-[d]d hh:mm:ss[.f...] . par exemple:

    ps.setTimestamp(2, java.sql.Timestamp.valueOf("2013-09-04 13:30:00");
    
  • java.util.Date

    supposons que vous ayez une variable endDate de type java.util.Date , vous faites la conversion ainsi:

    ps.setTimestamp(2, new java.sql.Timestamp(endDate.getTime()));
    
  • Actuel

    si vous avez besoin de l'horodatage actuel:

    ps.setTimestamp(2, new java.sql.Timestamp(System.currentTimeMillis()));
    
    // Since Java 8
    ps.setTimestamp(2, java.sql.Timestamp.from(java.time.Instant.now()));
    ps.setTimestamp(2, java.sql.Timestamp.valueOf(java.time.LocalDateTime.now()));
    
112
répondu Paul Vargas 2017-05-02 12:40:39

tl; dr

avec JDBC 4.2 ou plus tard et java 8 ou plus tard:

myPreparedStatement.setObject( … , myLocalDate  )

... et ...

myResultSet.getObject( … , LocalDate.class )

détails

la réponse de Vargas est bonne à propos de java.les types de temps mais se réfère uniquement à la conversion en java.SQL.Date. Pas besoin de convertir si votre pilote est mis à jour.

de java.temps

Le de java.time framework est intégré à Java 8 et plus tard. Ces classes supplantent les anciennes classes de date ennuyeuses telles que java.util.Date , .Calendar , & java.text.SimpleDateFormat . L'équipe Joda-Time conseille également la migration vers java.temps.

pour en savoir plus, voir le Oracle Tutorial . Et rechercher le débordement de la pile pour de nombreux exemples et explications.

une grande partie de la java.la fonctionnalité time est rétroportée à Java 6 & 7 en ThreeTen-Backport et adapté pour Android dans ThreeTenABP .

LocalDate

en java.heure, la classe java.time.LocalDate représente une date sans Heure de la journée et sans fuseau horaire.

si vous utilisez un conducteur JDBC conforme à JDBC 4.2 ou une spécification ultérieure, il n'est pas nécessaire d'utiliser le vieux java.sql.Date de la classe. Vous pouvez passer / récupérer des objets LocalDate directement à / depuis votre base de données via PreparedStatement::setObject et ResultSet::getObject .

LocalDate localDate = LocalDate.now( ZoneId.of( "America/Montreal" ) );
myPreparedStatement.setObject( 1 , localDate  );

... et ...

LocalDate localDate = myResultSet.getObject( 1 , LocalDate.class );

avant JDBC 4.2, convertir

si votre pilote ne peut pas gérer le java.les types de temps directement, retombent à la conversion en java.les types sql. Mais minimisent leur utilisation, avec votre logique d'entreprise en utilisant seulement java.les types d'heures.

de nouvelles méthodes ont été ajoutées aux anciennes classes pour la conversion en/à partir de java.les types d'heures. Pour java.sql.Date voir les méthodes valueOf et toLocalDate .

java.sql.Date sqlDate = java.sql.Date.valueOf( localDate );

... et ...

LocalDate localDate = sqlDate.toLocalDate();

valeur de l'espace Réservé

méfiez - vous de l'utilisation 0000-00-00 comme une valeur de placeholder comme indiqué dans le code de votre Question. Toutes les bases de données et tous les autres logiciels ne peuvent pas remonter aussi loin dans le temps. Je suggère d'utiliser quelque chose comme la date de référence Unix/Posix epoch de 1970, 1970-01-01 .

LocalDate EPOCH_DATE = LocalDate.ofEpochDay( 0 ); // 1970-01-01 is day 0 in Epoch counting.

à Propos de de java.heure

Le de java.temps cadre est intégré dans Java 8 et plus tard. Ces classes remplacent les anciennes classes de date legacy telles que java.util.Date , Calendar , & SimpleDateFormat .

le Joda-Time projet, maintenant en mode maintenance , conseille la migration vers le java.time classe.

pour en savoir plus, voir le Oracle Tutorial . Et rechercher le débordement de la pile pour de nombreux exemples et explications. La spécification est JSR 310 .

vous pouvez échanger java.temps objets directement avec votre base de données. Utiliser un JDBC driver conforme à JDBC 4.2 ou plus tard. Pas besoin de les chaînes, pas besoin de java.sql.* des classes.

où obtenir le java.les classes de temps?

Le ThreeTen-Extra le projet s'étend java.temps avec des cours supplémentaires. Ce projet est un terrain d'expérimentation pour d'éventuelles futures additions à java.temps. Vous pouvez trouver des classes utiles ici telles que Interval , YearWeek , YearQuarter , et plus .

15
répondu Basil Bourque 2018-06-06 21:19:32

le problème que vous avez est que vous passez des formats incompatibles à partir d'un java formaté.util.Date pour construire une instance de java.sql.Date , qui ne se comportent pas de la même manière en utilisant valueOf() puisqu'ils utilisent des formats différents.

je peux aussi voir que vous visez à persister des heures et des minutes, et je pense que vous feriez mieux de changer le type de données à java.sql.Timestamp , qui prend en charge des heures et des minutes, ainsi que de changer votre champ de base de données en DATETIME ou similaire (selon votre fournisseur de base de données).

de toute façon, si vous voulez changer de java.util.Date to java.sql.Date , je vous suggère d'utiliser

java.util.Date date = Calendar.getInstance().getTime();
java.sql.Date sqlDate = new java.sql.Date(date.getTime()); 
// ... more code here
prs.setDate(sqlDate);
3
répondu Cristian Meneses 2013-09-04 13:32:53

le docs dit explicitement que java.sql.Date lancera:

  • IllegalArgumentException - si la date indiquée n'est pas dans le format JDBC date escape ( yyyy-[m]m-[d]d )

aussi vous ne devriez pas avoir besoin de convertir une date à un String puis à un sql.date , cela semble superflu (et bug-prone!). Au lieu de cela, vous pourriez:

java.sql.Date sqlDate := new java.sql.Date(now.getTime());
prs.setDate(2, sqlDate);
prs.setDate(3, sqlDate);
2
répondu Vincent Malgrat 2013-09-04 13:31:55

si vous voulez ajouter la date courante dans la base de données, j'éviterais de calculer la date en Java pour commencer. Déterminer "maintenant" du côté Java (client) mène à des incohérences possibles dans la base de données si le côté client est mal configuré, a le mauvais moment, le mauvais fuseau horaire, etc. Au lieu de cela, la date peut être définie du côté du serveur d'une manière telle que:

requestSQL = "INSERT INTO CREDIT_REQ_TITLE_ORDER ("   +
                "REQUEST_ID, ORDER_DT, FOLLOWUP_DT) " +
                "VALUES(?, SYSDATE, SYSDATE + 30)";

...

prs.setInt(1, new Integer(requestID));

ainsi, un seul paramètre bind est requis et les dates sont calculé sur le côté serveur. Encore mieux serait d'ajouter un insert trigger à CREDIT_REQ_TITLE_ORDER et avoir le trigger insert dates. Cela peut aider à renforcer la cohérence entre les différentes applications client (par exemple, quelqu'un qui essaie de faire une correction via sqlplus.

1
répondu Glenn 2013-09-06 01:31:11

Pas sûr, mais je pense que vous cherchez est de créer un java.util.Dater à partir d'une chaîne, puis convertir ce java.util.Date en java.SQL.Date.

essayez ceci:

private static java.sql.Date getCurrentDate(String date) {

    java.util.Date today;
    java.sql.Date rv = null;
    try {

        SimpleDateFormat format = new SimpleDateFormat("dd-MM-yyyy");
        today = format.parse(date);
        rv = new java.sql.Date(today.getTime());
        System.out.println(rv.getTime());

    } catch (Exception e) {
        System.out.println("Exception: " + e.getMessage());
    } finally {
        return rv;
    }

}    

renvoie un java.SQL.Objet Date pour setDate();

la fonction ci-dessus affichera une valeur longue:

1375934400000

-1
répondu Darth Jon 2014-05-09 06:06:05