Java ora-01830 Изображение формата даты заканчивается перед преобразованием всей входной строки Временная метка SQL - PullRequest
0 голосов
/ 11 июня 2018

У меня проблемы с получением дат из моей базы данных при использовании Oracle через Java.Если я использую это в 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'))

, я получаю ошибку 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;
}

Ответы [ 2 ]

0 голосов
/ 11 июня 2018

Do not такие параметры передачи.

"' AND BEGINNING >= (TO_TIMESTAMP('" + tsBeginning + "', 'YYYY-MM-DD HH24:MI')) будет использовать метод Java toString() для преобразования экземпляра Timestamp в строку - и это, скорее всего, не будет соответствовать маске формата, которую вы указали.

Используйте заполнители и передайте экземпляры Timestamp напрямую:

Сначала вам нужно выполнить запрос SQL, который использует заполнители ? вместо значений напрямую:

String sql = "SELECT * from HA2_BOOKINGS WHERE ROOM = ? AND BEGINNING >= ? and END <= ?"

Затем подготовьте оператор:

PreparedStatement pstmt = aCon.prepareStatement(sql);

альтернативно используйте его без переменной:

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

Укажите значения:

pstmt.setString(1, 'R1');
pstmt.setTimestamp(2, tsBeginning);
pstmt.setTimestamp(3, tsEnd);

Выполните запрос (используя предоставленныйзначения) и обработать набор результатов.

resultSet = pstmt.executeQuery();
while (resultSet.next()) {
  ..
}

Помимо повышения производительности (поскольку вы избегаете дорогостоящего анализа в Oracle), это также безопасный способ сделать это, поскольку он предотвращает внедрение SQL.

Обратите внимание, что я заменил бесполезный оператор LIKE на =, потому что LIKE 'R1' совпадает с = 'R1'.

0 голосов
/ 11 июня 2018

X в модели формата является локальным символом радиуса .Ваши сеансы Java и 'oracle' (какой бы клиент ни ссылался), похоже, имеют разные настройки NLS.

Вы могли бы увидеть то же самое, скажем, в SQL * Plus, если бы вы запустили это первым:

alter session set nls_numeric_characters=',.';

Вы можете изменить настройки так, чтобы Java вел себя одинаково, возможно, через локаль;но лучше не полагаться на настройки NLS и не принимать их, если вы можете их избежать.Если у ваших литералов всегда есть точка, вы также можете использовать их в модели формата вместо NLS-зависимой X:

SELECT * 
from HA2_BOOKINGS 
WHERE ROOM like 'R1' 
  AND BEGINNING >= TO_TIMESTAMP('2018-06-11 15:11:43.208', 'YYYY-MM-DD HH24:MI:SS.FF')
  AND END <= TO_TIMESTAMP('2018-06-11 15:11:43.208', 'YYYY-MM-DD HH24:MI:SS.FF')

Или, что еще лучше, использовать переменные связывания и напрямую передавать значение метки времени,как предложил @a_horse_with_no_name.


Теперь, увидев свой код Java и то, как вы встраиваете литералы с конкатенацией, определенно следуйте этому совету;это просто объясняет, почему вы получили ошибку ...

...