Java 在PreparedStatement中使用setDate
为了使我们的代码更加标准,我们被要求将所有将SQL变量硬编码到准备好的语句中的地方都更改为绑定变量 但是,我在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
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
。e、 g:yyyy-[m]m-[d]d
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
。e、 g:yyyy-[m]m-[d]d hh:mm:ss[.f..]
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
将抛出:
-如果给定的日期不是JDBC日期转义格式(IllegalArgumentException
)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类
- 然后
- 内置的
- 标准的一部分