Usando setDate en PreparedStatement

Resuelto roymustang86 asked hace 11 años • 6 respuestas

Para hacer que nuestro código sea más estándar, se nos pidió que cambiáramos todos los lugares donde codificamos nuestras variables SQL a declaraciones preparadas y que vinculáramos las variables en su lugar.

Sin embargo, estoy enfrentando un problema con elsetDate() .

Aquí está el código:

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));

Recibo este error cuando se ejecuta el SQL:

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

¿Debería usarlo setString()en su lugar con a to_date()?

roymustang86 avatar Sep 04 '13 20:09 roymustang86
Aceptado

❐ Usandojava.sql.Date

Si su tabla tiene una columna de tipo DATE:

  • java.lang.String

    El método java.sql.Date.valueOf(java.lang.String)recibió una cadena que representa una fecha en el formato yyyy-[m]m-[d]d. p.ej:

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

    Supongamos que tienes una variable endDatede tipo java.util.Date, realizas la conversión así:

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

    Si desea insertar la fecha actual:

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

❐ Usandojava.sql.Timestamp

Si su tabla tiene una columna de tipo TIMESTAMPo DATETIME:

  • java.lang.String

    El método java.sql.Timestamp.valueOf(java.lang.String)recibió una cadena que representa una fecha en el formato yyyy-[m]m-[d]d hh:mm:ss[.f...]. p.ej:

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

    Supongamos que tienes una variable endDatede tipo java.util.Date, realizas la conversión así:

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

    Si necesita la marca de tiempo actual:

    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()));
    
Paul Vargas avatar Sep 04 '2013 13:09 Paul Vargas

tl; dr

Con JDBC 4.2 o posterior y java 8 o posterior:

myPreparedStatement.setObject( … , myLocalDate  )

…y…

myResultSet.getObject( … , LocalDate.class )

Detalles

La respuesta de Vargas es buena al mencionar los tipos java.time, pero se refiere solo a la conversión a java.sql.Date. No es necesario realizar la conversión si su controlador está actualizado.

java.tiempo

El marco java.time está integrado en Java 8 y versiones posteriores. Estas clases reemplazan a las antiguas y problemáticas clases de fecha y hora como java.util.Date, .Calendar, & java.text.SimpleDateFormat. El equipo de Joda-Time también recomienda la migración a java.time.

Para obtener más información, consulte el Tutorial de Oracle . Y busque Stack Overflow para obtener muchos ejemplos y explicaciones.

Gran parte de la funcionalidad java.time está adaptada a Java 6 y 7 en ThreeTen-Backport y se adapta aún más a Android en ThreeTenABP .

LocalDate

En java.time, la java.time.LocalDateclase representa un valor de solo fecha sin hora del día y sin zona horaria.

Si utiliza un controlador JDBC compatible con la especificación JDBC 4.2 o posterior, no es necesario utilizar la java.sql.Dateclase anterior. Puede pasar/obtener LocalDateobjetos directamente desde/hacia su base de datos a través de PreparedStatement::setObjecty ResultSet::getObject.

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

…y…

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

Antes de JDBC 4.2, convierta

Si su controlador no puede manejar los tipos java.time directamente, recurra a la conversión a tipos java.sql. Pero minimice su uso, y su lógica empresarial utilice únicamente tipos java.time.

Se han agregado nuevos métodos a las clases antiguas para la conversión hacia/desde tipos java.time. Para java.sql.Datever los métodos valueOfy toLocalDate.

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

…y…

LocalDate localDate = sqlDate.toLocalDate();

Valor del marcador de posición

Tenga cuidado al utilizar 0000-00-00como valor de marcador de posición el que se muestra en el código de su pregunta. No todas las bases de datos y otros programas pueden soportar retroceder tanto en el tiempo. Sugiero usar algo como la fecha de referencia de la época Unix/Posix de uso común de 1970 1970-01-01.

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

Acerca de java.time

El marco java.time está integrado en Java 8 y versiones posteriores. Estas clases reemplazan a las antiguas y problemáticas clases de fecha y hora heredadas , como java.util.Date, Calendary SimpleDateFormat.

El proyecto Joda-Time , ahora en modo de mantenimiento , aconseja la migración a las clases java.time .

Para obtener más información, consulte el Tutorial de Oracle . Y busque Stack Overflow para obtener muchos ejemplos y explicaciones. La especificación es JSR 310 .

Puede intercambiar objetos java.time directamente con su base de datos. Utilice un controlador JDBC compatible con JDBC 4.2 o posterior. No hay necesidad de cadenas, no hay necesidad de java.sql.*clases.

¿Dónde obtener las clases java.time?

  • Java SE 8 , Java SE 9 , Java SE 10 y posteriores
    • Incorporado.
    • Parte de la API de Java estándar con una implementación incluida.
    • Java 9 agrega algunas características y correcciones menores.
  • Java SE 6 y Java SE 7
    • Gran parte de la funcionalidad java.time está adaptada a Java 6 y 7 en ThreeTen-Backport .
  • Androide
    • Versiones posteriores de implementaciones de paquetes de Android de las clases java.time.
    • Para Android anterior (<26), el proyecto ThreeTenABP adapta ThreeTen-Backport (mencionado anteriormente). Consulte Cómo utilizar ThreeTenABP… .

El proyecto ThreeTen-Extra amplía java.time con clases adicionales. Este proyecto es un campo de pruebas para posibles adiciones futuras a java.time. Puede encontrar algunas clases útiles aquí, como , Interval, y más .YearWeekYearQuarter

Basil Bourque avatar Aug 07 '2016 00:08 Basil Bourque