【问题标题】:Java Date - Insert into databaseJava 日期 - 插入数据库
【发布时间】:2010-11-08 01:11:41
【问题描述】:

我需要想办法将带有 java.util.Date 字段的记录插入数据库,但我被卡住了。

有人知道我该怎么做吗? 现在我有类似的东西。

        java.util.Date myDate = new java.util.Date("01/01/2009");

        sb.append("INSERT INTO USERS");
        sb.append("(USER_ID, FIRST_NAME, LAST_NAME, SEX, DATE) ");
        sb.append("VALUES ( ");
        sb.append("  '" + userId + "'");
        sb.append(", '" + myUser.GetFirstname() + "' ");
        sb.append(", '" + myUser.GetLastname() + "' ");
        sb.append(", '" + myUser.GetSex() + "' ");
        sb.append(", '" + myDate  + "'");
        sb.append(")");

        Util.executeUpdate(sb.toString());

但是当我运行这样的事情时,我得到了错误: 日期时间值的字符串表示的语法不正确。

下面是sql语句的样子:

INSERT INTO USERS (USER_ID
    , FIRST_NAME
    , LAST_NAME
    , SEX
    , CRDATE) 
VALUES (   
    'user'
    , 'FirstTest' 
    , 'LastTest' 
    , 'M'
    , 'Thu Jan 01 00:00:00 CST 2009')

谢谢

【问题讨论】:

    标签: java sql date


    【解决方案1】:

    在回答您的问题之前,我想提一下,您可能应该考虑使用某种 ORM 解决方案(例如 Hibernate),包裹在数据访问层之后。您所做的似乎非常反OO。我承认我不知道你的代码的其余部分是什么样的,但一般来说,如果你开始看到自己使用了很多实用程序类,那么你可能采用了过于结构化的方法。

    要回答您的问题,正如其他人所提到的,请查看java.sql.PreparedStatement,并使用java.sql.Datejava.sql.Timestamp。类似的东西(为了尽可能多地使用您的原始代码,您可能希望对其进行更多更改):

    java.util.Date myDate = new java.util.Date("10/10/2009");
    java.sql.Date sqlDate = new java.sql.Date(myDate.getTime());
    
    sb.append("INSERT INTO USERS");
    sb.append("(USER_ID, FIRST_NAME, LAST_NAME, SEX, DATE) ");
    sb.append("VALUES ( ");
    sb.append("?, ?, ?, ?, ?");
    sb.append(")");
    
    Connection conn = ...;// you'll have to get this connection somehow
    PreparedStatement stmt = conn.prepareStatement(sb.toString());
    stmt.setString(1, userId);
    stmt.setString(2, myUser.GetFirstName());
    stmt.setString(3, myUser.GetLastName());
    stmt.setString(4, myUser.GetSex());
    stmt.setDate(5, sqlDate);
    
    stmt.executeUpdate(); // optionally check the return value of this call
    

    这种方法的另一个好处是它会自动为您转义您的字符串(例如,如果要插入姓氏“O'Brien”的人,您的原始实现会遇到问题)。

    【讨论】:

    • 为什么会被认为是anti oop?你可以解释吗。我是新手,所以会有所帮助。谢谢!
    • @Jack Leow:这不是反 OO,它可能只是具有不同级别的 OO 抽象。 Martin Fowler 在他的《PEAA as Domain Logic Patterns》一书中出色地解释了这一点:martinfowler.com/eaaCatalog 虽然某些系统可能会发现使用 TransactionScript(几乎是 zSysop 正在使用的东西)对其他系统很有帮助,但维护和使用它可能太难甚至不可能“域模型”代替。对于小型应用程序,“域模型”可能是矫枉过正。这是一个非常有趣的主题。
    【解决方案2】:

    PreparedStatement

    您绝对应该使用PreparedStatement。 (Tutorial)

    这样你就可以调用:

    pstmt.setDate( 1, aDate );
    

    JDBC driver 将针对您的特定数据库进行日期时间处理。

    此外,PreparedStatement 可以阻止任何 SQL injection 黑客尝试 - 非常重要! (humor)

    应该是这样的:

    SimpleDateFormat format = new SimpleDateFormat( "MM/dd/yyyy" );  // United States style of format.
    java.util.Date myDate = format.parse( "10/10/2009" );  // Notice the ".util." of package name.
    
    PreparedStatement pstmt = connection.prepareStatement(
    "INSERT INTO USERS ( USER_ID, FIRST_NAME, LAST_NAME, SEX, DATE ) " +
    " values (?, ?, ?, ?, ? )");
    
    pstmt.setString( 1, userId );
    pstmt.setString( 3, myUser.getLastName() ); 
    pstmt.setString( 2, myUser.getFirstName() ); // please use "getFir…" instead of "GetFir…", per Java conventions.
    pstmt.setString( 4, myUser.getSex() );
    java.sql.Date sqlDate = new java.sql.Date( myDate.getTime() ); // Notice the ".sql." (not "util") in package name.
    pstmt.setDate( 5, sqlDate ); 
    

    就是这样,JDBC 驱动程序将为您创建正确的 SQL 语法。

    检索

    在检索 Date 对象时,您可以使用 SimpleDateFormat 创建日期时间值的格式化字符串表示形式。

    这是一个简单的示例行,但在 StackOverflow 中搜索 很多 更多。

    String s = new SimpleDateFormat("dd/MM/yyyy").format( aDate ); 
    

    【讨论】:

    • 方法 setDate 接受 java.sql.Date 而不是 java.util.Date。
    • @CD1:谢谢。现在已更正。 @zSisop:java.sql.Date 和 java.sql.TimeStamps 是不同的对象,如果你想存储日期和小时,你应该使用后者。
    • 这应该是公认的答案。使用PreparedStatement 可以解决 SQL 注入黑客的问题,因此几乎总是应该使用它。使用java.sql.Date 而不是字符串是更好的做法。
    • 我对这个答案进行了一些重要的编辑,例如替换不推荐使用的代码。此外,Java 8 及更高版本的用户应阅读 [我自己的答案] 作为此答案的附录(使用新的 java.time 包)。
    【解决方案3】:

    当然,PreparedStatement 将使您的代码更好,但要回答您的问题,您需要告诉 DBMS 您的日期字符串表示的格式。在 Oracle(您不指定数据库供应商)中,使用 TO_DATE() 函数将字符串日期转换为 Date

    INSERT INTO TABLE_NAME(
      date_column
    )values(
      TO_DATE('06/06/2006', 'mm/dd/yyyy')
    )
    

    【讨论】:

    • 你知道是否有办法让 java.util.Date 以 '01/01/2009' 格式输出日期?
    • @zSyspo: 是 String s = new SimpleDateFormat("dd/MM/yyyy").format(aDate);会做
    • 警告:SimpleDateFormat 不是线程安全的。制作一个您自己的简单包装器,它是线程安全的。公共类 ThreadSafeSimpleDateFormat { 私有 DateFormat df;公共 ThreadSafeSimpleDateFormat(String 格式) { this.df = new SimpleDateFormat(format); } public synchronized String format(Date date) { return df.format(date); } 公共同步日期解析(字符串字符串)抛出 ParseException { 返回 df.parse(字符串); } }
    • 非常感谢布赖恩!你非常乐于助人。 :D
    • 在数据库上强加任何格式都不好——格式是纯粹的演示责任
    【解决方案4】:

    OscarRyz 的The Answer 是正确的,应该是公认的答案。但是现在这个答案已经过时了。

    java.time

    在 Java 8 及更高版本中,我们有了新的java.time package(灵感来自Joda-Time,由JSR 310 定义,tutorial,由ThreeTen-Extra 项目扩展)。

    避免使用旧的日期时间类

    旧的 java.util.Date/.Calendar、SimpleDateFormat 和 java.sql.Date 类令人困惑。一方面,j.u.Date 具有日期 时间,而 j.s.Date 是仅日期 没有 时间。哦,除了 j.s.Date 只有 假装 没有时间。作为 j.u.Date 的子类,j.s.Date 继承了时间,但会自动将该时间调整为午夜 (00:00:00.000)。令人困惑?是的。坦率地说,这是一个糟糕的 hack。

    出于这个以及更多的原因,应该避免使用那些旧课程,仅在最后的手段下使用。尽可能使用 java.time,并以 Joda-Time 作为后备。

    LocalDate

    在 java.time 中,LocalDate 类清楚地表示没有任何时间或时区的仅日期值。这就是我们对这个问题的解决方案所需要的。

    为了获取该 LocalDate 对象,我们解析输入字符串。但是 java.time 并没有使用旧的 SimpleDateFormat 类,而是在 java.time.format package 中提供了一个新的 DateTimeFormatter 类。

    String input = "01/01/2009" ;
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern( "MM/dd/yyyy" ) ;
    LocalDate localDate = LocalDate.parse( input, formatter ) ;
    

    符合JDBC 4.2 或更高版本的JDBC 驱动程序可以通过PreparedStatement::setObjectResultSet::getObject 方法直接使用java.time 类型。

    PreparedStatement pstmt = connection.prepareStatement(
        "INSERT INTO USERS ( USER_ID, FIRST_NAME, LAST_NAME, SEX, DATE ) " +
        " VALUES (?, ?, ?, ?, ? )");
    
    pstmt.setString( 1, userId );
    pstmt.setString( 3, myUser.getLastName() ); 
    pstmt.setString( 2, myUser.getFirstName() ); // please use "getFir…" instead of "GetFir…", per Java conventions.
    pstmt.setString( 4, myUser.getSex() );
    pstmt.setObject( 5, localDate ) ;  // Pass java.time object directly, without any need for java.sql.*. 
    

    但在您拥有如此更新的 JDBC 驱动程序之前,请回退使用 java.sql.Date 类。幸运的是,Java 8 赋予了旧的java.sql.Date 类一个新的方便的转换静态方法valueOf( LocalDate )

    the sibling Answer by OscarRyz的示例代码中,将其“sqlDate =”行替换为这一行:

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

    【讨论】:

      【解决方案5】:

      如果您使用 mysql .. 例如,您可以将日期保存为“2009-12-31”。

      更新人设生日日期 = '2009-12-31'

      但我更喜欢使用 jdbc,尽管你必须创建 java.sql.Date ...

      *日期在这个世界上是一种邪恶... :)

      【讨论】:

        【解决方案6】:

        使用准备好的语句,它们具有为每种原生 Java 类型正确设置参数的方法。

        查看setDateexamples 的api

        【讨论】:

          【解决方案7】:

          您应该使用 java.sql.Timestamp 而不是 java.util.Date。 使用 PreparedStatement 也可以省去您对格式的担忧。

          【讨论】:

            【解决方案8】:
            pst.setDate(6, new java.sql.Date(txtDate.getDate().getTime()));
            

            这是我使用 jdbc 将日期保存到数据库中的代码,对我来说效果很好

            • pst 是preparedstatement 的变量
            • txtdate 是 JDateChooser 的名称

            【讨论】:

              【解决方案9】:

              你可以使用这个代码日期和时间时间是24小时

              INSERT INTO TABLE_NAME(
                date_column
              )values(
                TO_DATE('2016-10-05 10:53:56', 'SYYYY-MM-DD HH24:MI:SS')
              )
              

              【讨论】:

                【解决方案10】:
                VALUES ('"+user+"' , '"+FirstTest+"'  , '"+LastTest+"'..............etc)
                

                您可以使用它来将变量插入到 sql 查询中。

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 2011-04-06
                  • 2020-08-11
                  • 2011-02-28
                  • 1970-01-01
                  • 2016-04-22
                  • 1970-01-01
                  相关资源
                  最近更新 更多