在 java 中设置参数时,准备好的语句查询构建不起作用

Prepared Statement query building not working when the parameters are setting in java

我正在尝试使用 PreparedStatement 构建查询,但我认为在使用 PreparedStatement 时出现问题,因为它 return 什么都没有。然后我尝试传递直接 sql 查询,它成功了。 同样的查询我是 运行 在 Oracle SQL Developer 中,它也成功了。

我需要知道我的代码有什么问题。

我的想法有问题sql正在构建查询,当使用 PreparedStatement 设置参数时。

这里我使用的是Oracle作为后端。

public List<Hotel> getAvailableHotelsDA(ReservationDetails resevationDetails) throws SQLException, ParseException
{
    List<Hotel> hotelList  =  new ArrayList<Hotel>();

    int idCountry =  resevationDetails.getIdCountry();
    int idState =  resevationDetails.getIdState();


    String query =  "SELECT h.idHotel , h.Name , h.Description  FROM hotel h"+
                    " INNER JOIN contract c ON h.idHotel = c.idHotel"+
                    " INNER JOIN country cn ON h.idCountry = cn.idCountry"+
                    " INNER JOIN state st ON cn.idCountry = st.idCountry"+
                    " WHERE c.startDate <= TO_DATE(?,'yyyy-MM-dd') "+
                    " AND c.endDate >= TO_DATE(?,'yyyy-MM-dd') "+
                    " AND c.isCurrentContract=?"+
                    " AND h.idState = ?"+
                    " AND h.idCountry = ?"+
                    " GROUP BY (h.idHotel , h.Name , h.Description)";


    PreparedStatement prepStatement = null;
    ResultSet resultSet = null;
    try
    {

        SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy");
        format.setLenient(false);
        Date checkIn =  format.parse(resevationDetails.getCheckInDate());
        Date checkOut = format.parse(resevationDetails.getCheckOutDate());


        connection = DBUtility.getConnection();
        //connection = DBUtility.getMySQLConnection();
        prepStatement =  connection.prepareStatement(query);
        int count = 0;
        prepStatement.setDate(++count, convertFromJAVADateToSQLDate(checkIn));
        prepStatement.setDate(++count, convertFromJAVADateToSQLDate(checkOut));
        prepStatement.setInt(++count, CONTRACT_STATE.CURRENT.getValue());
        prepStatement.setInt(++count, idState);
        prepStatement.setInt(++count, idCountry);

        //prepStatement =  connection.prepareStatement("SELECT h.idHotel , h.Name , h.Description  FROM hotel h INNER JOIN contract c ON h.idHotel = c.idHotel INNER JOIN country cn ON h.idCountry = cn.idCountry INNER JOIN state st ON cn.idCountry = st.idCountry WHERE c.startDate <= TO_DATE('2015-02-25','yyyy-MM-dd')  AND c.endDate >= TO_DATE('2015-03-05','yyyy-MM-dd')  AND c.isCurrentContract=1 AND h.idState = 1 AND h.idCountry = 1 GROUP BY (h.idHotel , h.Name , h.Description)");

        resultSet  =  prepStatement.executeQuery();



        Hotel hotel;
        while(resultSet.next())
        {
            hotel =  new Hotel();

            hotel.setHotelID(resultSet.getInt("idHotel"));
            hotel.setName(resultSet.getString("Name"));
            hotel.setDescription(resultSet.getString("Description"));

            hotelList.add(hotel);
        }


    }
    catch(SQLException ex)
    {
        System.out.println("Error : SQL Exception : Method : getAvailableHotels ");
        ex.printStackTrace();
        throw ex;
    }
    finally
    {
        DBUtility.close(resultSet, prepStatement, connection);
    }

    return hotelList;

}

如果你要绑定一个Date,调用to_date是没有意义的。 to_date 不接受 date 作为输入,它只接受 varchar2。如果传入 date,Oracle 必须首先将 date 隐式转换为 varchar2,然后将 varchar2 传递给 to_date,以便获得字符串转换回 date。隐式 datevarchar2 的转换将使用您会话的 nls_date_format。如果这恰好与您传递给 to_date 的显式格式掩码不匹配,您将得到一个错误,或者您将得到一个您不期望的 date

由于您绑定的是 Date,您的查询应该类似于

" WHERE c.startDate <= ? "+
" AND c.endDate >= ? "+

如果 startDateendDate 中有您想忽略的时间部分,您可能想要 trunc 日期(这可能涉及创建一些基于函数的索引) .

我使用下面的方法在没有使用to_date的情况下转换日期和解析日期,这次成功了

private java.sql.Date convertFromDateStringToSQLDate(String dateString)
{
    java.sql.Date sqlDate = null;

    try 
    {

        SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
        Date dateNotFormat;

        dateNotFormat = sdf.parse(dateString);


        sdf.applyPattern("dd-MMM-yyyy");
        String dateFormatString = sdf.format(dateNotFormat);

        DateFormat formatter = new SimpleDateFormat("dd-MMM-yyyy");
        Date dateFormat = (Date)formatter.parse(dateFormatString); 


        if (dateFormat != null)
        {
            sqlDate = new java.sql.Date(dateFormat.getTime());
        }

        System.out.println(sqlDate);

    } 
    catch (ParseException e) 
    {

        e.printStackTrace();
    }

    return sqlDate;
} 

这是查询和绑定...

    String query =  "SELECT h.idHotel , h.Name , h.Description  FROM hotel h"+
                    " INNER JOIN contract c ON h.idHotel = c.idHotel"+
                    " INNER JOIN country cn ON h.idCountry = cn.idCountry"+
                    " INNER JOIN state st ON cn.idCountry = st.idCountry"+
                    " WHERE c.startDate <= ? "+
                    " AND c.endDate >= ? "+
                    " AND c.isCurrentContract=?"+
                    " AND h.idState = ?"+
                    " AND h.idCountry = ?"+
                    " GROUP BY (h.idHotel , h.Name , h.Description)";


    PreparedStatement prepStatement = null;
    ResultSet resultSet = null;
    try
    {           

        connection = DBUtility.getConnection();
        //connection = DBUtility.getMySQLConnection();
        prepStatement =  connection.prepareStatement(query);
        int count = 0;
        prepStatement.setDate(++count, convertFromDateStringToSQLDate(resevationDetails.getCheckInDate()));
        prepStatement.setDate(++count, convertFromDateStringToSQLDate(resevationDetails.getCheckOutDate()));