Использование JdbcTemplate для вставки больших CLOB в Oracle не удается

Я взаимодействую с базой данных Oracle через служебный класс Spring JdbcTemplate, и я пробовал эти два варианта кода:

jdbcTemplate.update("INSERT INTO my_table (title, content) VALUES (?, ?)", title, content);

-- or --

jdbcTemplate.update(new PreparedStatementCreator() {
    @Override
    public PreparedStatement createPreparedStatement(Connection conn) throws SQLException {
        OraclePreparedStatement ps = (OraclePreparedStatement)conn.prepareStatement("INSERT INTO my_table (title, content) VALUES (?, ?)");
        ps.setString(1, title);
        ps.setStringForClob(2, content);
        return ps;
    }
});

Где title — это традиционный VARCHAR2, а content — это CLOB.

Любой из этих вариантов работает для меньших значений content. Однако, когда у меня есть большее количество content, в столбец CLOB ничего не вставляется.

Интересно, что в обоих случаях title обновляется. Как будто запрос просто игнорирует content, если их слишком много, но никогда не выдает ошибку.

Кто-нибудь знает, как я должен это решить?

Спасибо.

ИЗМЕНИТЬ:

Согласно ответу @GreyBeardedGeek, я пытался использовать OracleLobHandler и DefaultLobHandler с тем же эффектом. Все работает, пока мои CLOB не достигнут определенного размера.

Я также попробовал следующий код, снова с тем же эффектом:

Connection conn = db.getDataSource().getConnection();
CLOB clob = CLOB.createTemporary(conn, false, CLOB.DURATION_SESSION);
clob.setString(1, myString);

OraclePreparedStatement ps = (OraclePreparedStatement)conn.prepareStatement("UPDATE my_table SET blob = ?");
ps.setCLOB(1, clob);
ps.execute();

Я сбит с толку тем, почему каждый из этих методов будет работать для меньших CLOB, но затем внезапно перестанет работать для больших. Есть ли какая-то конфигурация в БД, которую мне не хватает? Или проблема в коде?


person Jrop    schedule 19.03.2014    source источник


Ответы (3)


Ладно, я чувствую себя довольно глупо. Как оказалось, даже этот простой код правильно сохранял CLOB:

jdbcTemplate.update("UPDATE my_table SET title = ?, content = ? WHERE id = ?", getTitle(), getContentString(), getId());

Проблема заключалась в том, что мой код извлек CLOB обратно из базы данных. Ниже приводится мое предположение, основанное на моем коде (и исправлении): кажется, что меньшие CLOB кэшируются в памяти и могут быть прочитаны позже (а именно, после закрытия соединения их все еще можно прочитать). Однако для более крупных CLOB их необходимо считывать, пока соединение еще открыто.

Для меня это означало, что исправление было таким же простым, как чтение содержимого CLOB, как только оно стало доступно для моего объекта. В моем случае меня не очень беспокоят проблемы с памятью, потому что я не ожидаю, что мои CLOB будут содержать содержимое чрезмерного размера, и поэтому немедленное чтение значения в память является приемлемым подходом.

person Jrop    schedule 20.03.2014
comment
Итак, чтобы уточнить (мне также приходится иметь дело с этой проблемой), шаблоны jdbc уже обрабатывают clobs, просто передавая их в запросе на обновление? - person Stupid.Fat.Cat; 25.07.2014
comment
@Stupid.Fat.Cat - я думаю, что ответ на ваш вопрос - да. Прошло некоторое время с тех пор, как я просматривал этот код, но проблема заключалась в том, что мой вызов getContentString() был отложен и больше не мог читать CLOB. Решение состояло в том, чтобы кэшировать CLOB сразу после его первой доступности. Надеюсь, это не запутало. - person Jrop; 25.07.2014

Сколько я себя помню, Oracle требовала специальной обработки BLOB и CLOB. Spring JDBC имеет org.springframework.jdbc.support.lob.OracleLobHandler для установки значения BLOB и CLOB.

На http://techdive.in/spring/spring-handling-blobclob, но в основном вместо ps.setStringForClob вы бы сделали

oracleLobHandler.getLobCreator().setClobAsString(ps, 2, content);

person GreyBeardedGeek    schedule 20.03.2014
comment
Спасибо за чаевые. Я обновил свой вопрос с подробностями. К сожалению, использование OracleLobHandler (и даже DefaultLobHandler) не сработало. Я также пытался просто установить соединение, а затем делать что-то вручную с тем же эффектом. Может ли это быть неправильной настройкой в ​​базе данных, а не проблемой с моим кодом? Тут у меня начинают заканчиваться идеи... - person Jrop; 20.03.2014
comment
если бы это было так, ни один из CLOB не работал бы. В OP они работают в некоторых случаях, поэтому я не вижу, как это может быть проблемой. - person eis; 20.03.2014

SqlLobValue(String content) можно использовать для CLOB.

Перейдите по ссылке: http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/jdbc/core/support/SqlLobValue.html

.

person Sravanthi    schedule 18.01.2016