63474

Java DataBase Connectivity. Уровни изолированности транзакций

Лекция

Информатика, кибернетика и программирование

Есть несколько способов разрешения конфликтов между одновременно выполняющимися транзакциями. Пользователь может задать уровень изолированности, то есть уровень внимания, которое СУБД должна уделить при разрешении возможных конфликтов.

Русский

2014-06-20

84 KB

0 чел.

I. Java DataBase Connectivity                                                                                                    Лекция 9.

Уровни изолированности транзакций

Есть несколько способов разрешения конфликтов между одновременно выполняющимися транзакциями. Пользователь может задать уровень изолированности, то есть уровень внимания, которое СУБД должна уделить при разрешении возможных конфликтов. Например, что будет, если одна транзакция изменит какое-либо значение, а вторая транзакция прочитает его перед тем, как первая выполнит commit или rollback? Допустимо ли это, например, если это значение, будучи уже прочитанным второй транзакцией, окажется некорректным и будет откатано (rolled back) первой? Пользователь JDBC может указать СУБД на возможность чтения измененных значений до того, как выполнится commit («грязное чтение», «dirty reads»). Это делается так (con – это соединение с БД):

con.setTransactionIsolation (TRANSACTION_READ_UNCOMMITTED);

Чем выше уровень изолированности транзакций, тем больше внимания СУБД уделяет устранению конфликтов. Интерфейс Connection определяет пять таких уровней. Минимальный из них соответствует случаю, когда транзакции не поддерживаются вовсе, а максимальный – невозможности существования более одной транзакции в любой момент времени. Обычно, чем выше уровень изолированности, тем медленнее выполняется приложение (из-за избыточной блокировки и уменьшенной конкурентности пользователей). При выборе конкретного уровня изолированности разработчик должен найти золотую середину между потребностями в производительности и требованиями к целостности данных. Очевидно, что реально поддерживаемые уровни зависят от возможностей используемой СУБД.

При создании объекта Connection его уровень изолированности зависит от драйвера или БД. Пользователь может вызвать метод setIsolstionLevel, чтобы изменить уровень изолированности транзакций, и новое значение уровня будет установлено до конца сессии. Чтобы установить уровень изолированности только для одной транзакции, надо установить его перед выполнением транзакции и восстановить прежнее значение после ее завершения. Изменение уровня изолированности во время самой транзакции нежелательно, так как произойдет автоматический вызов commit, что повлечет за собой фиксацию изменений.

public int getTransactionIsolation ( ) throws SQLException

TRANSACTION_NONE

Транзакции не поддерживаются.

TRANSACTION_READ_COMMITTED

«Грязное чтение» предотвращается; разовые чтения и фантомные чтения могут происходить. Это уровень препятствует транзакциям от чтения строк с неподтвержденными изменениями в них.

TRANSACTION_READ_UNCOMMITTED

«Грязное чтение», разовое чтение и фантомное чтение может происходить. Этот уровень позволяет изменять строку с помощью одной транзакции и прочесть ее другой прежде, чем изменения в этой строке будут подтверждены («грязное чтение»). Если изменения будут отменены с помощью rollback ( ), вторая транзакция вернет неправильную строку.

TRANSACTION_REPEATABLE_READ

«Грязное чтение» и разовое чтение предотвращаются; фантомные чтения могут происходить. Этот уровень препятствует транзакции от чтения строки с неподтвержденным изменением в ней, он также предотвращает ситуацию, когда одна транзакция читает строку, а вторая транзакция изменяет ее, при этом первая транзакция перечитывая строку, получает разные значения каждый раз (разовое чтение).

TRANSACTION_SERIALIZABLE

«Грязное чтение», разовое чтение и фантомное чтение предотвращаются. Этот уровень включает предотвращения из TRANSACTION_REPEATABLE_READ, более того предотвращает ситуацию, когда одна транзакция читает все строки, которые удовлетворяют условию WHERE, а вторая транзакция вставляет строку, которая удовлетворяет тому же условию WHERE, и первая транзакция, перечитывая с тем же условием, получает дополнительную «фантомную» строку при втором чтении.

PreparedStatement

Интерфейс PreparedStatement наследует от Statement и отличается от последнего следующим:

  1.  Экземпляры PreparedStatementпомнятскомпилированые SQL-выражения. Именно поэтому они называются “prepared” ( “подготовленные” ).
  2.  SQL-выражения в PreparedStatement могут иметь один или более (IN) входной параметр. Входной параметр – это параметр, чье значение не указывается при создании SQL-выражения. Вместо него в выражении на месте каждого входного параметра ставится знак (“?”). Значение каждого вопросительного знака устанавливается методами sеtXXX перед выполнением запроса.

Поскольку объекты PreparedStatement прекомпилированы, исполнение этих запросов может происходить несколько быстрее, чем в объектах Statement. В результате SQL-выражения, которые исполняются часто, в целях улучшения производительности создают в виде объектов PreparedStatement. 

Оставаясь подклассом класса Statement, класс PreparedStatement наследует все функции от Statement. В дополнении к ним он добавляет методы установки входных параметров. Кроме того, три метода – execute, executeQuery и executeUpdate – модифицированы таким образом, что не имеют аргументов. Старые методы класса Statement ( которые принимают SQL-выражения в качестве единственного аргумента ) не должны использоваться в объекте PreparedStatement.

Создание объектов PreparedStatement

Следующий фрагмент кода, где con – это объект Connection , создает объект PreparedStatement, содержащий SQL-выражение с двумя параметрами:

PreparedStatement pstmt = con. prepareStatement  (

           “UPDATE table4 SET m = ? WHERE x = ?” );

Объект pstmt отныне содержит выражение UPDATE table4 SET m = ? WHERE x = ?” ), которое уже отослано в СУБД и подготовлено для выполнения.

Передача входных ( IN ) параметров  

Перед выполнением объекта PreparedStatement надо установить значения всех его параметров. Это делается с помощью методов setXXX, где XXX – это тип параметра. Например, если параметр имеет Java-тип long, используемый метод будет setLong. Первый аргумент методов setXXX – это порядковый номер параметра, а второй – значение, в которое надо его установить. Например, следующий код устанавливает первый параметр в значение 123456789, a второй – 100000000:

pstmt .steLong ( 1,123456789 );

pstmt .steLong ( 2,100000000 );

После установки параметра его можно использовать при многократном выполнении выражения до тех пор, пока он не очистится методом clearParameters.

В режиме соединения по умолчанию (разрешена автофиксация) – каждый запрос фиксируется или откатывается автоматически.

Один и тот же объект PreparedStatement может выполняться много раз, если нижестоящий драйвер или СУБД  будут сохранять выражение (statement) в открытом состоянии даже после того как произойдет фиксация. Иначе не имеет смысла пытаться улучшить производительность заменой на PreparedStatement.

Используя pstmt из предыдущего примера, следующий код устанавливает значение обоих параметров и выполняет pstmt 10 раз. Как уже было отмечено, БД не должна закрывать pstmt. В этом примере первый параметр устанавливается в “Hi” и остается неизменным. Второй параметр устанавливается в последовательные целые значения, начиная от 0 и заканчивая  9.

pstmt.setString (1, “Hi”);

for (int  i = 0; i < 10; i++)    {

         pstmt.setInt (2, i);

         int rowCount = pstmt.executeUpdate ( );

}

Совместимость типов данных входных параметров

ХХХ в названии методов setXXX – это тип данных Java. Неявно он же является и типом данных JDBC (SQL), так как драйвер отображает тип данных Java на соответствующий JDBC-тип передотсылкой JDBC-типа в БД. Следующий код устанавливает второй параметр объекта PreparedStatement pstmt в 44 с типом данных short:

pstmt.setShort (2, 44);

Драйвер отошлет 44 в БД в виде типа JDBC SMALLINT, который является стандартным для Java-типа short.

На программисте лежит ответственность за совместимость Java-типов входных параметров и ожидаемой базой данных соответствующих JDBC-типов. Рассмотрим случай, когда ожидается SMALLINT. Если используется метод setByte, то драйвер отошлет значение TINYINT в БД. Это вероятно, работать будет, так как многие БД преобразуют «похожие» типы данных друг в друга. Тем не менее, чтобы приложение могло работать как можно с большим количеством СУБД, лучше использовать Java-типы, которые в точности соответствуют ожидаемым JDBC-типам. Если ожидается JDBC-тип данных SMALLINT, то использование именно setShort вместо setByte сделает приложение более переносимым.

Использование объектов

Программист может явно задать конвертирование входных параметров в определенный JDBC-тип с помощью метода setObject. Этот тип может принимать третий аргумент, указывающий целевой JDBC-тип данных. Перед отправкой в БД драйвер преобразует Object в указанный JDBC-тип.

Если JDBC-тип не задан, то драйвер просто преобразует Object в его ближайший JDBC-эквивалент, а затем пошлет его в БД.  Это подобно использованию обычных методов setXXX; в обоих случаях драйвер отображает Java-типы в JDBC-типы данных перед отправкой значений в БД.

В случае использования метода setObject тип данных может быть неизвестен приложения на этапе его компиляции. Используя его, приложение может подавать на вход значения любых типов данных и преобразовывать их в ожидаемый базой данных JDBC-тип.

Отсылка значений NULL в качестве входного параметра

Метод setNull позволяет отсылать значения NULL в БД как входные параметры. Хотя JDBC-тип параметра все же можно задать явно.

JDBC-значение NULL будет отослано в БД также в том случае, если методу setXXX будет предано Java-значение null ( если метод принимает Java-объект в качестве аргумента ). Тем не менее, метод setObject может принимать значение null только в том случае, если задан JDBC-тип.

Отправка очень больших входных параметров

Методы setBytes и setString могут отсылать неограниченное количество данных. Правда, иногда программисту легче передавать большие значения в виде маленьких кусков. Это делается установкой входного параметра в значение Java-потока ввода ( input stream ). Когда выполняется выражение, JDBC-драйвер будет производить последовательные вызовы из этого потока ввода, считывая его содержимое и пересылая его в виде значения параметра.

JDBC предоставляет три метода установки входных параметров в поток ввода: setBinaryStream для потоков, содержащих обычные байты, setAsciiStream для потоков ASCII-символов и setUnicodeStream для потоков Unicode-символов. Эти методы, в отличие от остальных методов setXXX, принимают дополнительный аргумент, равный количеству передаваемых в потоке байтов. Этот аргумент необходим, так как некоторые СУБД требуют указания размера данных перед их отсылкой.

Следующий код иллюстрирует отсылку файла в виде входного параметра запроса:

java.io.File file = new java.io.File (“/tmp/data”);

int fileLength = file.length ( );

java.io.InputStream fin = new java.io.FileInputStream (file);

java.sql.PreparedStatement pstmt = con.preparedStatement ( );

           “UPDATE Table 5 SET stuff = ? WHERE index = 4”);

pstmt.setBinaryStream (1, fin, filelength);

pstmt.executeUpdate ( );

При выполнении запроса для доставки данных последовательно считывается поток ввода fin.

CallableStatement (вызываемый оператор)

Объект CallableStatement  предоставляет унифицированный способ вызова хранимых процедур в любой СУБД. Вызов процедуры осуществляется с помощью escape-синтаксиса в одной из двух форм: с результирующим параметром и без него. Результирующий параметр – это один из типов выходных (OUT) параметров, являющийся возвращаемым значением хранимой процедуры. Обе формы могут иметь переменное число аргументов на входе (параметры IN), выходе (параметры OUT) или входных и выходных параметров одновременно (INOUT-параметры). Вопросительный знак означает местоположение параметра.

Синтаксис вызова хранимой процедуры в JDBC показан ниже. Квадратные скобки означают, что-то, что находиться между ними, необязательно, и сами по себе не являются частью синтаксиса.

{ call имя_процедуры [ (?, ?, . . .) ] }

Синтаксис для процедуры, возвращающей результат:

{ ? = call имя_процедуры [ (?, ?, . . .) ] }

Синтаксис хранимой процедуры без параметров:

{ call имя_процедуры }

Обычно тот, кто использует объект CallableStatement, уже знает, что используемая СУБД поддерживает хранимые процедуры, и какие именно процедуры имеются в БД. Тем не менее, чтобы это выяснить, достаточно вызвать некоторые методы объекта DatabaseMetaData. Например, метод supportsStoredProcedures возвращает true, если СУБД поддерживает хранимые процедуры, а метод getProcedures возвращает описания доступных процедур.

CallableStatement наследует методы Statement общей для обработки SQL-запросов, а также методы PreparedStatement для обработки входных (IN) параметров. Все методы, объявленные в CallableStatement обрабатывают выходные (OUT) параметры следующим образом: указание JDBC-типов данных (т.е. SQL-типов) выходных параметров, извлечение из них значений или проверка их на NULL.

Создание объекта CallableStatement

Объекты CallableStatement создаются методом prepareCall объекта Connection. Приведем пример, который создает экземпляр CallableStatement, содержащий вызов хранимой процедуры getTestData с двумя аргументами и без возвращаемого параметра:

CallableStatement  cstmt = con.prepareCall ( “ {call  getTestData ( ?, ? ) } “ );

Какими именно параметрами ( IN, OUT или INOUT) являются знаки вопроса – зависит от самой хранимой процедуры getTestData.

IN- и OUT-параметры

Передача значений входных параметров объекта CallableStatement осуществляется с помощью методов setXXX, унаследованных от PreparedStatement. Типы передаваемых значений определяются тем, какой из методов setXXX используется ( setFloat для передачи значений float и т.п.).

JDBC-типы всех OUT-параметров хранимых процедур должны быть зарегистрированы перед их вызовом. Это необходимо, так как некоторым СУБД нужно передавать информацию о типах данных. Регистрация типов данных выходного параметра производится методом registerOutParameter. Только в этом случае после выполнения запроса методы getXXX класса CallableStatement смогут получить значения параметров. Необходимо использовать подходящий по типу данных Java метод getXXX в соответствии с зарегистрированными JDBC-типом параметра. Другими словами,  registerOutParameter используют JDBC-тип ( тот, который подходит к JDBC-типу возвращаемого из БД значения ), а getXXX преобразует его в тип Java.

Приведем пример регистрации выходных параметров, выполнения хранимой процедуры cstmt и считывание параметров. Методов getByte извлекает байт из первого выходного параметра, а getBigDecimal возвращает объект BigDecimal ( с тремя цифрами после десятичной точки ) из второго:

CallableStatement cstmt = con.prepareCall ( “ {call getTestData ( ?, ?) }” );

cstmt. registerOutParameter. (1, java.sql.Types.TINYINT);

cstmt. registerOutParameter. (2, java.sql.Types.DECIMAL, 3);

cstmt.executeQUery ( );

byte x = cstmt.getByte (1);

java.math.BigDecimal n = cstmt.getBigDecimal (2, 3);

В отличие от ResultSet, CallableStatement не может считывать большие значения последовательно (в потоке).

Параметры INOUT

В случае параметра, который одновременно является и входным,  и выходным (INOUT), необходимо вызывать как соответствующий метод setXXX (унаследованный от PreparedStatement), так и метод registerOutParameter. Метод setXXX устанавливает входное значение параметра, а registerOutParameter регистрирует тип выходного значения.

Типы входного и выходного значений, зарегистрированных методом registerOutParameter, должны быть одинаковыми. Для чтения выходного значения используется соответствующий метод getXXX. Например, для параметра типа byte нужно использовать метод установки значения setByte, передавать JDBC-тип данных TINYINT методу registerOutParameter и использовать getByte для чтения выходного значения.

В следующем примере вызывается хранимая процедура reviseTotal с единственным INOUT-параметром. Метод setByte устанавливает значение параметра в 25, которое будет представлено базе данных как TINYINT. Далее метод registerOutParameter регистрирует параметр как TINYINT. После выполнения хранимой процедуры возвращается значение типа TINYINT, которое будет считано методом getByte в виде типа byte языка Java.

CallableStatement cstmt = con.prepareCall ( “ {call revisrTotal ( ? ) }” );

cstmt. setByte (1, 25);

cstmt. registerOutParameter. (1, java.sql.Types.TINYINT);

cstmt.executeUpdate ( );

byte x = cstmt.getByte (1);

Возвращение значения NULL в выходных параметрах

Значение, возвращенное в выходной параметр, может быть NULL. При этом методы getXXX возвращают null, 0 или false, в зависимости от типа данных. Как и в случае с ResultSet, единственным способом узнать, вернула ли процедура 0, false или NULL, является вызов метода wasNull, который возвращает true, если последнее значение, считанное одним из методов getXXX было NULL, и false иначе.


 

А также другие работы, которые могут Вас заинтересовать

20754. Устройство поперечно-строгального станка и его настройка 126.1 KB
  Техническая характеристика Наибольший ход ползуна мм 520 Размеры рабочей поверхности стола длинахширина мм 500x360 Частота ходов ползуна ход мин 132150 Горизонтальная подача стола мм дв. Периодически при каждом обратном ходе ползуна стол может перемещаться в поперечном горизонтальном направлении по направляющим поперечины 2 или вместе с поперечиной вертикально по станине. Передвижение гайки от оси вала 1У увеличивает радиус кривошипа а следовательно угол качания кулисы и ход ползуна. Место хода исходное положение ползуна...
20755. Плоскошлифовальный станок и его настройка 169.73 KB
  Распределитель 14 управляется распределителем 21 положение которого зависит от крана реверса 27. В результате распределитель 14 занимает левое положение А. В результате распределитель 14 занимает левое положение А. От расположения упоров зависит длина хода и исходное положение стола.
20756. Определение технологических свойств порошков 1.26 MB
  Универсальная испытательная машина прессформа весы лабораторные волюмометр прибор для определения текучести порошка штангенциркуль секундомер порошки железа меди и нитрида алюминия. Форма частиц порошка: а губчатая б сферическая в осколочная всех частиц порошка взятых в единице объема или массы пик нометрическая плотность фактическая или истинная плотность частиц порошка и микротвердость. Насыпной плотностью ГОСТ 19440 74 порошка унас называется масса единицы объема порошка при свободной насыпке. Насыпная плотность...
20757. Изучение диаграммы состояния сплавов системы железо-углерод 106.72 KB
  Содержание углерода в цементите составляет 667. Графит одна из двух алмаз графит кристаллических модификаций углерода. Ординаты между ними двойным сплавам общее содержание железа и углерода в которых равно 100. В системе FeFe3C возможны жидкая Ж фаза представляющая собой жидкий раствор железа и углерода и четыре твердые: δ феррит γ аустенит α феррит и Fe3C.
20758. Разработка отдельных рекомендаций по технологии изготовления поковки методами горячей объемной штамповки 511.55 KB
  Обработка металлов давлением Практическая работа № 3 Разработка отдельных рекомендаций по технологии изготовления поковки методами горячей объемной штамповки Цель работы: ознакомиться с технологическим процессом горячей объемной штамповки при изготовлении поковки на кривошипном горячештампо вочном прессе и с методикой расчетов заготовки и штампа. Эскиз поковки нанесенный на эскиз детали с указанием плоскости разъема; расчеты припусков допусков штамповочных уклонов и радиусов закругления. Расчеты и эскиз горячей поковки с облоем и...
20759. Определение режима резания лезвийным инструментом 720.87 KB
  Обработка металлов резанием Практическая работа №4 Определение режима резания лезвийным инструментом Цель работы: ознакомиться с методикой определения режима резания для лезвийной обработки точение строгание сверление зенкерование развертывание фрезерование и т. Порядок проведения Необходимым условием для назначения режимов резания является наличие разработанного технологического процесса по операциям и переходам а также паспортных данных станков. Рекомендуется соблюдать определенную последовательность назначения режимов резания....
20760. Определение твердости металлов По Бринеллю и Роквеллу 237.6 KB
  Лабораторная работа № 1 Тема: Определение твердости металлов По Бринеллю и Роквеллу Выполнил: Учащийся гр. Цель работы: ознакомиться с методами и способами испытаний твердости металлов. Методы измерения твердости: статического и ударного вдавливания царапин отскока и другие. Таблица 1 Сравнительные значения твердости...
20761. Определение механических свойств металлов при испытании на растяжение 184.58 KB
  Диаграмма растяжения низкоуглеродистой стали и схемы определения характеристик прочности Для нагрузки Рпц удлинение образца пропорционально усилию растяжения и при его снятии образец восстанавливает свои первоначальные форму и размеры; Рт усилие предела текучести физического соответствует нагрузке когда деформация образца происходит без ее увеличения;т предел текучести физический. Эти показатели определяют когда пластическая деформация образца достигает 02 от его рабочей длины l0. Усилие Pk меньше P max что...
20762. Микроскопический анализ металлов и сплавов 138.25 KB
  Если в задачу изучения микроструктуры входит определение размера зерна то рекомендуется использовать метод визуального сравнения зерен изучаемой микроструктуры при увеличении х100 со стандартной шкалой размеров зерна по ГОСТ 653982 рис. Устанавливается номер балл зерна затем по номеру используя табл.10 определяется поперечный размер зерна мм его площадь мм2 и количество зерен на площади шлифа в 1 мм2.10 Характеристика оценки зерна в зависимости от его номера Продолжение таблицы 1.