Java 在PreparedStatement中使用setDate

Java 在PreparedStatement中使用setDate,java,sql,oracle,jdbc,prepared-statement,Java,Sql,Oracle,Jdbc,Prepared Statement,为了使我们的代码更加标准,我们被要求将所有将SQL变量硬编码到准备好的语句中的地方都更改为绑定变量 但是,我在setDate()中遇到了一个问题 代码如下: DateFormat dateFormatYMD = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); DateFormat dateFormatMDY = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss"); Dat

为了使我们的代码更加标准,我们被要求将所有将SQL变量硬编码到准备好的语句中的地方都更改为绑定变量

但是,我在
setDate()
中遇到了一个问题

代码如下:

        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));
在执行SQL时,我会遇到以下错误:

    java.lang.IllegalArgumentException
    at java.sql.Date.valueOf(Date.java:138)
    at com.cmsi.eValuate.TAF.TAFModuleMain.CallTAF(TAFModuleMain.java:1211)
我应该使用
setString()
来代替
to_date()

❐ 使用
java.sql.Date
如果您的表有一列类型为
DATE

  • java.lang.String

    该方法收到一个表示日期的字符串,格式为
    yyyy-[m]m-[d]d
    。e、 g:

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

    假设您有一个类型为
    java.util.Date
    的变量
    endDate
    ,您可以这样进行转换:

    ps.setDate(2, new java.sql.Date(endDate.getTime());
    
    ps.setTimestamp(2, new java.sql.Timestamp(endDate.getTime()));
    
  • 当前

    如果要插入当前日期:

    ps.setDate(2, new java.sql.Date(System.currentTimeMillis()));
    
    // Since Java 8
    ps.setDate(2, java.sql.Date.valueOf(java.time.LocalDate.now()));
    
❐ 使用
java.sql.Timestamp
如果表中的列类型为
时间戳
日期时间

  • java.lang.String

    该方法收到一个表示日期的字符串,格式为
    yyyy-[m]m-[d]d hh:mm:ss[.f..]
    。e、 g:

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

    假设您有一个类型为
    java.util.Date
    的变量
    endDate
    ,您可以这样进行转换:

    ps.setDate(2, new java.sql.Date(endDate.getTime());
    
    ps.setTimestamp(2, new java.sql.Timestamp(endDate.getTime()));
    
  • 当前

    如果需要当前时间戳:

    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()));
    
    • 明确表示
      java.sql.Date
      将抛出:

      • IllegalArgumentException
        -如果给定的日期不是JDBC日期转义格式(
        yyyy-[m]m-[d]d
      此外,您不需要将日期转换为
      字符串,然后再转换为
      sql.date
      ,这似乎是多余的(而且容易出现错误!)。相反,你可以:

      java.sql.Date sqlDate := new java.sql.Date(now.getTime());
      prs.setDate(2, sqlDate);
      prs.setDate(3, sqlDate);
      

      您遇到的问题是,您正在从格式化的java.util.Date传递不兼容的格式,以构造
      java.sql.Date
      的实例,这些实例在使用
      valueOf()
      时的行为方式不同,因为它们使用不同的格式

      我还可以看到,您的目标是持续数小时和数分钟,我认为您最好将数据类型更改为
      java.sql.Timestamp
      ,它支持数小时和数分钟,同时将数据库字段更改为DATETIME或类似值(取决于您的数据库供应商)

      无论如何,如果您想从
      java.util.Date更改为java.sql.Date
      ,我建议使用

      java.util.Date date = Calendar.getInstance().getTime();
      java.sql.Date sqlDate = new java.sql.Date(date.getTime()); 
      // ... more code here
      prs.setDate(sqlDate);
      

      不确定,但我认为您正在寻找的是从字符串创建java.util.Date,然后将该java.util.Date转换为java.sql.Date

      试试这个:

      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;
          }
      
      }    
      
      将为setDate()返回java.sql.Date对象

      上述功能将打印一个长值:


      1375934400000

      如果要将当前日期添加到数据库中,我将避免首先用Java计算日期。如果客户端配置错误、时间错误、时区错误等,在Java(客户端)端确定“现在”可能会导致数据库中出现不一致。相反,可以在服务器端以如下方式设置日期:

      requestSQL = "INSERT INTO CREDIT_REQ_TITLE_ORDER ("   +
                      "REQUEST_ID, ORDER_DT, FOLLOWUP_DT) " +
                      "VALUES(?, SYSDATE, SYSDATE + 30)";
      
      ...
      
      prs.setInt(1, new Integer(requestID));
      
      这样,只需要一个bind参数,并且在服务器端计算的日期将是一致的。更好的做法是在
      CREDIT\u REQ\u TITLE\u ORDER
      中添加一个insert触发器,并让触发器插入日期。这有助于加强不同客户端应用程序之间的一致性(例如,有人试图通过sqlplus进行修复)。

      tl;dr 对于JDBC 4.2或更高版本和java 8或更高版本:

      myPreparedStatement.setObject( … , myLocalDate  )
      
      ……还有

      myResultSet.getObject( … , LocalDate.class )
      
      LocalDate localDate = myResultSet.getObject( 1 , LocalDate.class );
      
      细节 Vargas的回答很好地提到了java.time类型,但只提到转换为java.sql.Date。如果驱动程序更新,则无需转换

      java.time 该框架内置于Java 8及更高版本中。这些类取代了旧的麻烦的日期时间类,如
      Java.util.date
      .Calendar
      ,&
      Java.text.SimpleDataFormat
      。该团队还建议迁移到Java.time

      要了解更多信息,请参阅.和搜索堆栈溢出以获取许多示例和说明

      大部分java.time功能都在中向后移植到Java6和Java7,并在中进一步适应Android

      LocalDate
      在java.time中,该类表示一个只包含日期的值,不包含一天中的时间,也不包含时区

      如果使用符合或更高版本的规范,则无需使用旧类。您可以通过和直接向数据库传递/获取
      LocalDate
      对象

      ……还有

      myResultSet.getObject( … , LocalDate.class )
      
      LocalDate localDate = myResultSet.getObject( 1 , LocalDate.class );
      
      在JDBC4.2之前,转换 如果您的驱动程序无法直接处理java.time类型,请退回到转换为java.sql类型,但尽量减少它们的使用,您的业务逻辑只使用java.time类型

      新方法已添加到旧类中,用于与java.time类型进行转换

      ……还有

      LocalDate localDate = sqlDate.toLocalDate();
      
      占位符值 请小心使用
      0000-00-00
      作为问题代码中显示的占位符值。并非所有数据库和其他软件都能处理追溯到那么远的时间。我建议使用类似于1970年常用的方法,
      1970-01-01

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

      关于java.time 该框架内置于Java8及更高版本中。这些类取代了麻烦的旧日期时间类,如,&

      该项目现已启动,建议迁移到类

      要了解更多信息,请参阅.和搜索堆栈溢出以获取许多示例和解释。规范为

      您可以直接与数据库交换java.time对象。使用兼容的或更高版本。不需要字符串,也不需要
      java.sql.*
      classes

      从哪里获得java.time类

      • 然后
        • 内置的
        • 标准的一部分