Java ora-01830日期格式图片在转换整个输入字符串Timestamp SQL之前结束

Hol*_*ola 0 java sql oracle timestamp ora-01830

我在通过java使用Oracle时从数据库中获取日期时遇到问题.如果我在Java中使用它:

SELECT * 
from HA2_BOOKINGS 
WHERE ROOM like 'R1' 
  AND BEGINNING >= (TO_TIMESTAMP('2018-06-11 15:11:43.208', 'YYYY-MM-DD HH24:MI:SSXFF')) 
  AND END <=  (TO_TIMESTAMP('2018-06-11 15:11:43.208', 'YYYY-MM-DD HH24:MI:SSXFF'))
Run Code Online (Sandbox Code Playgroud)

我得到ora-01830错误但是当我在oracle本身使用完全相同的东西时,代码可以工作.有谁知道为什么?

我的java代码:

public Collection<Booking> getAllBookingsForRoomInPeriod(Room r, String startDate, String endDate) {
        Collection<Booking> bookingsForRoomInPeriod = new ArrayList<Booking>();
        SimpleDateFormat parser = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        parser.setLenient(false);

        Date dateBeginning = new Date();
        Date dateEnd = new Date();
        try {
            dateBeginning = parser.parse(startDate);
        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        try {
            dateEnd = parser.parse(endDate);
        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        Timestamp tsBeginning = new Timestamp(dateBeginning.getTime());
        Timestamp tsEnd = new Timestamp(dateEnd.getTime());

        bookingList.clear();

        Connection aCon = Persistence.getConnection();
        ResultSet resultSet = null;

        // Raeume lesen
        try {
            resultSet = Persistence.executeQueryStatement(aCon, "SELECT * from HA2_BOOKINGS WHERE ROOM like '" + r.getRoomNr() + "' AND BEGINNING >= (TO_TIMESTAMP('" + tsBeginning + "', 'YYYY-MM-DD HH24:MI')) AND END <=  (TO_TIMESTAMP('" + tsEnd + "', 'YYYY-MM-DD HH24:MI'))");
            while (resultSet.next()) {
                Booking a = new Booking();
                a.setRoom(resultSet.getString("ROOM"));
                a.setUsername(resultSet.getString("USERNAME"));
                a.setDescription(resultSet.getString("DESCRIPTION"));
                a.setBeginning(resultSet.getTimestamp("BEGINNING"));
                a.setEnd(resultSet.getTimestamp("END"));
                this.bookingList.add(a);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            Persistence.closeConnection(aCon);
        }
        System.out.println(bookingList);

        return bookingList;
}
Run Code Online (Sandbox Code Playgroud)

a_h*_*ame 6

不要经过这样的参数.

"' AND BEGINNING >= (TO_TIMESTAMP('" + tsBeginning + "', 'YYYY-MM-DD HH24:MI'))将使用Java的toString()方法将Timestamp实例转换为String - 这很可能与您指定的格式掩码不匹配.

使用占位符并Timestamp直接传递实例:

首先,您需要一个使用占位符?而不是直接使用值的SQL查询:

String sql = "SELECT * from HA2_BOOKINGS WHERE ROOM = ? AND BEGINNING >= ? and END <= ?"
Run Code Online (Sandbox Code Playgroud)

然后准备声明:

PreparedStatement pstmt = aCon.prepareStatement(sql);
Run Code Online (Sandbox Code Playgroud)

或者在没有变量的情况下使用它

PreparedStatement pstmt = aCon.prepareStatement("SELECT * from HA2_BOOKINGS WHERE ROOM = ? AND BEGINNING >= ? and END <= ?");
Run Code Online (Sandbox Code Playgroud)

提供价值:

pstmt.setString(1, 'R1');
pstmt.setTimestamp(2, tsBeginning);
pstmt.setTimestamp(3, tsEnd);
Run Code Online (Sandbox Code Playgroud)

执行查询(使用提供的值)并处理结果集.

resultSet = pstmt.executeQuery();
while (resultSet.next()) {
  ..
}
Run Code Online (Sandbox Code Playgroud)

除了性能改进之外(因为您在Oracle中避免了昂贵的硬解析),这也是一种安全的方法,因为它可以防止SQL注入.

请注意,我替换了无用的LIKE运算符,=因为LIKE 'R1' 它是相同的= 'R1'.