У меня есть странная проблема при попытке выполнить инструкцию select for update, а затем выполнить впоследствии вставку или обновление. Я получаю исключение ORA-01461. Это происходит только при использовании последнего драйвера ojdbc (12.1.0.2), а в старшем - отлично (12.1.0.1).
В частности, последний драйвер, похоже, имеет какой-то предел в длине первичного ключа (ограничен 32 символами), хотя соответствующий столбец объявлен более чем 32 символами. Образец кода для репликации проблемы следующий:
CREATE TABLE "TEST_TABLE" (
"TEST_ID" VARCHAR2(40 CHAR) NOT NULL ENABLE,
"TEST_COMMENT" VARCHAR2(200 CHAR),
CONSTRAINT "TEST_TABLE_PK" PRIMARY KEY ("TEST_ID")
);
И некоторые java:
public class DemoUpdatableResultSet {
private static final String DB_URL = "jdbc:oracle:thin:@xxxx:1521/xxxxx";
private static final String DB_USER = "xxx";
private static final String DB_PASS = "xxx";
public static Connection getConnection() throws Exception {
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASS);
return conn;
}
public static void main(String[] args) {
final String uuid = UUID.randomUUID().toString();
ResultSet rs = null;
Connection conn = null;
PreparedStatement pstmt = null;
try {
conn = getConnection();
String query = "SELECT t.* FROM TEST_TABLE t WHERE t.TEST_ID=? FOR UPDATE";
pstmt = conn.prepareStatement(query, ResultSet.TYPE_SCROLL_SENSITIVE,
ResultSet.CONCUR_UPDATABLE);
pstmt.setString(1, uuid); // set input values
rs = pstmt.executeQuery(); // create an updatable ResultSet
// insert column values into the insert row.
rs.moveToInsertRow(); // moves cursor to the insert row
rs.updateString("TEST_ID", uuid); // updates the 2nd column
rs.updateString("TEST_COMMENT", "Comment for: " + uuid);
rs.insertRow();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
rs.close();
pstmt.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
Первая строка основного метода создает uuid
UUID.randomUUID().toString();
длина которого составляет 36 символов. Запуск этого класса образца приведет к ошибке ORA-01461, но изменив указанную выше строку на
UUID.randomUUID().toString().replaceAll("-", "");
который дает 32 строки символов, будет корректно работать и вставить строку в базу данных. Обратите внимание, что столбец "TEST_ID", в котором сохранена эта строка, является VARCHAR2 (40 CHAR) и может содержать как 32, так и 36 строк символов. Увеличение длины столбца до еще большего числа ничего не изменит.
Надеюсь, что мой примерный код прост для чтения и понимания, и я с нетерпением жду решения или объяснения этой проблемы.
Спасибо!
Информация о базе данных:
Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
PL/SQL Release 12.1.0.2.0 - Production
"CORE 12.1.0.2.0 Production"
TNS for Linux: Version 12.1.0.2.0 - Production
NLSRTL Version 12.1.0.2.0 - Production
Немного изменилось, чтобы запустить оператор insert с теми же данными, чтобы показать, что эта проблема более странная, чем кажется (относительно длины строки uuid). Следующий пример кода выполняется правильно с новейшим драйвером oracle:
public static void main(String[] args) {
final String uuid = UUID.randomUUID().toString();
ResultSet rs = null;
Connection conn = null;
PreparedStatement pstmt = null;
try {
conn = getConnection();
String query = "INSERT INTO TEST_TABLE (TEST_ID, TEST_COMMENT) VALUES (?, ?)";
pstmt = conn.prepareStatement(query);
pstmt.setString(1, uuid); // set input values
pstmt.setString(2, "Comment for: " + uuid); // set input values
rs = pstmt.executeQuery();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
rs.close();
pstmt.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}