Основным исследованием в этой статье является Hibernate's Session_flush и уровень изоляции. Конкретное введение и примеры заключаются в следующем.
Сначала посмотрим на некоторые концепции:
1. Грязное чтение: грязное чтение также называется чтением недействительных данных. Это означает, что во время доступа к базе данных Thing T1 изменяет определенное значение, а затем Thing T2 читает значение. После этого T1 отменяет модификацию значения по какой -то причине, что приводит к недействительным данные, которые считываются T2. Грязное чтение означает, что когда что -то вступает в данные и изменяет данные, и эта модификация не была представлена в базу данных, другая вещь также обращается к этим данным, а затем использует эти данные. Поскольку эти данные до сих пор не представлены, данные, прочитанные другим, являются грязными данными, а операции, выполняемые на основе грязных данных, неверны.
2. Не повторяется чтение: например, когда я читал пост, данные, которые я нашел, были Чжан Сан и Ли Си. Затем, после того, как я обновился, я обнаружил, что начальный Чжан Сан стал Чжан Б.А. Это так называемое неповторимое чтение, потому что данные, которые я прочитал, не повторялись.
3. Fantasy Reading: Когда я искал данные, я начал находить 3 записи. Когда я обновил это, я обнаружил, что записи стали 8. Это фантастическое чтение.
4. Отправьте чтение: Вы можете прочитать только после отправки. Оракул по умолчанию к этому. Там нет грязного чтения таким образом.
5. Повторяемость: это, очевидно, противоположность неповдосленному чтению. Это может избежать неповторимого чтения, но это не может избежать фантомного чтения.
6. Сериализация: этот метод очень строгий. С точки зрения непрофессионала, когда я что -то делаю, никто другой не может сделать это. Это очень безопасно, но это чрезвычайно неэффективно.
Ниже мы используем практические примеры для понимания применения очистки кеша Hibernate.
База данных Hibernate Mapping связана со стратегией первичной генерации ключей.
Примеры генерации первичных ключей в UUID:
Общедоступный класс user {private String uid; Private String uname; Private Date Grentle; public String getUid () {return uid;} public void setuid (string uid) {this.uid = uid;} public String getuname () {return uname;} public void setUname (String uname) {this.unam SetBirthDay (дата рождения) {this.birthDay = день рождения;}}User.hbm.xml:
<? xml version = "1.0"?> <! Doctype Hibernate Mapping Public "-// Hibernate/Hibernate Mapping Dtd 3.0 // en" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <!-Пакет. package = "com.lixue.bean"> <!-Имя узела класса представляет собой имя класса объекта, а таблица представляет имя объекта, отображаемое с таблицей в базе данных-> <class name = "table" table = "t_user"> <id name = "uid"> <!-Generation через uuid-> <generator/> </id> <der name> <der> <der> name = "День рождения"/> </class> </hibernate-mapping>
Метод испытаний:
/ ***Проверьте стратегию генерации первичных ключей UUID*/ public void testSave1 () {/*Определенный сеанс и вещи*/ session session = null; Транзакция транзакции = null; попробуйте { /*получить сеанс и вещи* / session = hibernateutils.getsession (); Transaction = session.beginTransaction (); /*Создать пользователь*/ user user = new user (); user.setuname ("xi jinping"); user.setBirthDay (new Date ()); / *** Поскольку стратегия генерации первичных ключей пользователя является UUID, после вызова сохраните, она просто включает в себя пользователя в управлении сеансом* оператор INSERT не будет выпущен, но идентификатор был сгенерирован, а существование indateBase в PersistEnceContext - false*/ session.save (пользователь); /** * Вызов Flush, Hibernate очистит кэш (вставьте объекты во временную сбору в сеансе-> вставки в базу данных, очищая временную сбору) * В настоящее время данные не могут быть замечены в базе данных, но если уровень изоляции базы данных устанавливается на то, чтобы не представить. session.flush (); /** * Отправить вещи * По умолчанию операция коммита будет выполнять кэш чистки промывки, * поэтому данные не могут быть откатываны после вызова промывки без отображения * Commit * Transaction.commit (); } catch (Exception e) {e.printstackTrace (); Transaction.rollback (); } наконец {hibernateutils.closesession (Session); }} Мы можем отлаживать программу через точки останова:
1. Поскольку побочная скорость первичной генерации ключей пользователя является UUID, после вызова метода save (), пользовательский объект может быть включен только в управление сеансом, а оператор INSERT не будет выпущен, но идентификатор был сгенерирован (Примечание: два места очень важны после сохранения. Во-первых, есть элемент в сессии. PersistenceContext-> EntityEntries-> MAP-> Table-> Определенный элемент массива-> Значение сохраняет объект. Как показано на картинке:
2. После вызова метода flush (), временное сохраненное значение ActionQueue в сеансе будет очищено, и затем значение существующего Indatabase в PersistenceContext установлено на True, указывая на то, что в базе данных есть соответствующие данные, но при открытии базы данных и открытию таблицы вы не можете увидеть данные, потому что на уровне дефолта, что вы не можете прочитать, что наверняка является чтением. данные. После вызова метода Commit () в базе данных есть данные.
Пример создания первичных ключей нативным образом:
открытый класс user1 {private integer uid; частная строка uname; частная дата день рождения; public integer getUid () {return uid;} public void setuid (integer uid) {this.uid = uid;} public String getunam день рождения;} public void setBirthday (дата рождения) {this.birthday = день рождения;}}User1.hbm.xml:
<? xml version = "1.0"?> <! Doctype Hibernate Mapping Public "-// Hibernate/Hibernate Mapping Dtd 3.0 // en" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <!-Пакет. package = "com.lixue.bean"> <!-Имя узла класса представляет собой имя класса объекта (не забудьте изменить имя класса при назначении файла отображения, в противном случае возникнет ошибка), таблица представляет имя объекта, отображаемое с таблицей в базе данных-> <class = "user1" таблица = "T_USER1"> <ID name = "uid"> <! <name Property = "Uname"/> <name = "name =" День рождения "/> </class> </hibernate-mapping>
Метод испытаний:
/ ***Проверка нативная стратегия генерации первичных ключей*/ public void testsave2 () {/*определенный сеанс и вещи*/ session session = null; Транзакция транзакции = null; попробуйте { /*получить сеанс и вещи* / session = hibernateutils.getsession (); Transaction = session.beginTransaction (); /*Создать пользователь*/ user1 user = new user1 (); user.setuname ("li keqiang"); user.setBirthDay (new Date ()); / *** Поскольку стратегия генерации первичных ключей пользователя1 является собственной, после вызова session.save () будет выполнена оператор INSERT, а объект временного сбора будет очищен* Возвращает идентификатор, сгенерированный базой данных, включен в управление сеансом, и изменяется в статусе существования. Transaction.commit (); } catch (Exception e) {e.printstackTrace (); Transaction.rollback (); } наконец {hibernateutils.closesession (Session); }} Отлаживать программу через точку останова:
1. Поскольку стратегия генерации первичной ключей является собственной, после вызова метода save () будет выполнена оператор INSERT, а данные во временном объекте сбора будут очищены, и будет возвращен идентификатор, сгенерированный базой данных.
2. Включите объект в управление сеансом, измените свойство EastingIstAtaBase в PersistEnceContext True (указывает на то, что в базе данных есть соответствующие данные, но его нельзя увидеть из -за области изоляции).
Давайте проверим другой метод Hibernate, который является Exict (), что означает исключение объекта из сеанса.
Для программы, которая генерирует стратегию первичного ключа UUID, вот метод испытания:
/ ***Проверьте стратегию генерации первичных ключей UUID*/ public void testSave3 () {/*Определенный сеанс и вещи*/ session Session = null; Транзакция транзакции = null; попробуйте { /*получить сеанс и вещи* / session = hibernateutils.getsession (); Transaction = session.beginTransaction (); /*Создать пользователь*/ user user = new user (); user.setuname ("hu jintao"); user.setBirthDay (new Date ()); /*** Поскольку стратегия генерации первичного ключа пользователя является UUID, после вызова Save, просто включив пользователя в управление сеансом*, не выпускает оператор INSERT, но идентификатор был сгенерирован. Статус EasticIstIndateBase в сеансе является false */ session.save (пользователь); /*Выселение объект пользователя из сеанса, то есть исключен из свойства EntityEntries PersistenceContext*/ session.evict (user); /** * не может успешно отправиться, потому что, когда Hibernate очищает кэш, пользовательский объект выводится из сеанса вставки временной коллекции для вставки * после операции, существование имущество в собственности EntityEntries должно быть обновлено до истинного, и мы называем злодее * выселение пользователя из EntityEntries/Search, поэтому не может быть основан, и не может быть основан, и не может быть основан, что не может быть основан, что не может быть. Transaction.commit (); } catch (Exception e) {e.printstackTrace (); Transaction.rollback (); } наконец {hibernateutils.closesession (Session); }} Отладка через точки останова:
1. Поскольку используется стратегия генерации первичной ключа UUID, оператор INSERT не будет отправлена после вызова метода save (). Объект включен в управление сеансом. Идентификатор был сгенерирован, и в базе данных нет соответствующих данных (то есть значение атрибута EasticIstAtaTabase является false).
2. После вызова exict (), изгнайте пользовательский объект из сеанса, то есть исключен из свойства EntityEntries в PeristenceContext.
3. Когда я снова вызову метод Commit (), мы обнаружим, что наши данные не могут быть сохранены, потому что в начале наше свойство существования IndeAtabase было ложным, то есть в базе данных нет соответствующих данных. Затем мы назвали Evil (), чтобы удалить все свойства объекта в PersistEnceContext (также включено свойство «Существование ииндатабаза»), но временные хранимые данные в ActionQueue не были удалены. Когда мы вызовываем метод Commit (), мы сначала неявно назваем метод flush (). Функция этого метода также упоминалась ранее. Он вставит временный объект в ActionQueue, а затем установит значение свойства indistAtaBase в PersistEnceContext True. К сожалению, в PersistEnceContext не существует свойства IndiaStaTabase, поэтому возникнет ошибка, что приведет к неспособности сохранить.
Для этого мы улучшаем вышеуказанную процедуру:
/ ***Проверьте стратегию генерации первичных ключей UUID*/ public void testSave4 () {/*Определенный сеанс и вещи*/ session Session = null; Транзакция транзакции = null; попробуйте { /*получить сеанс и вещи* / session = hibernateutils.getsession (); Transaction = session.beginTransaction (); /*Создать пользователь*/ user user = new user (); user.setuname ("hu jintao"); user.setBirthDay (new Date ()); /*** Поскольку стратегия генерации первичного ключа пользователя является UUID, после вызова Save, просто включив пользователя в управление сеансом*, не выпускает оператор INSERT, но идентификатор был сгенерирован. Статус существования в PersistenceContext является false */ session.save (user); / ***После промывки, Hibernate очистит кэш, сохраняет пользовательский объект в базу данных, очистите объект пользователя во вставках в сеансе*и установит статус ExistingDatabase в PersistEnceContext true*/ session.flush (); / * Высечь объект пользователя из сеанса, то есть исключен из свойства EntityEntries PersistenceContext */ session.evict (пользователь); / *** Может быть успешно представлен, потому что Hibernate не может быть в сборе вставки сеанса при очистке кэша* Пользовательский объект был найден (очищен при вызове промывки), поэтому оператор INSERT не будет выпущен, а статус ExisthisthistAtabase в сессии не будет обновлен*/ Transaction.commit (); } catch (Exception e) {e.printstackTrace (); Transaction.rollback (); } наконец {hibernateutils.closesession (Session); }} ПРИМЕЧАНИЕ. После сохранения мы называем метод flush (), а затем вызовываем метод Evict () после измененной программы.
Отладка через точки останова:
1. Поскольку это все еще стратегия генерации UUID, после вызова Save, оператор INSERT не будет выпущен, но объект включен в управление сеансом. Свойство EastingIndataBase в PersistEnceContext является ложным.
2. После вызова save () мы снова вызовываем метод flush (). Функция этого метода состоит в том, чтобы очистить кэш, то есть выпустить оператор INSERT, вставить временный объект во вставки в сеанс в базу данных, затем очистить временную сбору и установить свойство EastingIstAtaBase в PersistEnceContext True.
3. После вызова flush () метод Exict () вызывается. Его функция состоит в том, чтобы очистить объект пользователя из сеанса, то есть очистить свойство EntityEntries в PersistenceContext.
4. После вызова метода Evict () метод Commit () неявно вызовет метод flush () сначала. Функция промывки состоит в том, чтобы очистить кэш, то есть вставить объект в временную коллекцию сеанса-> вставки в базу данных, но мы называли метод flush () ранее (примечание: после вызова этого метода, временная коллекция будет очищена), поэтому временная коллекция вообще не имеет объектов, поэтому оператор INSERT не будет выпущен. Он не будет обновлять статус EastingIstAtaBase в PersistEnceContext. Отправить успешно.
Давайте рассмотрим использование метода Exict () в стратегии нативного первичного генерации:
/ ***Проверка нативная стратегия генерации первичных ключей*/ public void testsave5 () {/*определенный сеанс и вещи*/ session session = null; Транзакция транзакции = null; попробуйте { /*получить сеанс и вещи* / session = hibernateutils.getsession (); Transaction = session.beginTransaction (); /*Создать пользователь*/ user1 user = new user1 (); user.setuname ("ma ying-jeou"); user.setBirthDay (new Date ()); / *** Поскольку первичная стратегия генерации ключей user1 является собственной, после вызова session.save () будет выполнена оператор INSERT,* возвращает идентификатор, сгенерированный базой данных, включенным в управление сеансом, изменить состояние существования IndataBase в сеанс в True, и очистите временный набор*, если уровень изоляции DataBase не будет установлен на прочитание, тогда мы сможем увидеть сохраненные данные; /* Высечь объект пользователя из сеанса, то есть исключен из свойства EntityEntries PersistenceContext*/ session.evict (пользователь); / *** Может быть успешно представлен, потому что Hibernate находится в сборе вставки сеанса при очистке кэша* Пользовательский объект не может быть найден, поэтому оператор INSERT не будет выпущен, и статус существует IndaTabase в сеансе не будет обновлен*/ transaction.commit (); } catch (Exception e) {e.printstackTrace (); Transaction.rollback (); } наконец {hibernateutils.closesession (Session); }} Благодаря отладке:
1. Поскольку стратегия генерации первичной ключей является собственной, после вызова метода сохранения, оператор INSERT будет немедленно выдан, возвращая идентификатор, сгенерированный базой данных, включающий объект в управление сеансом, изменяя свойство «Существование IndeAtabase» в PersistEnceContext True, то есть есть соответствующие данные в базе данных, и объекты во временном сборе будут очищены. Однако из -за уровня изоляции MySQL мы не можем увидеть данные, прежде чем их совершить.
2. После вызова Save объект вызывается, и объект исключен из сеанса, то есть он исключен из объектов в PersistenceContext.
3. После вызова метода Evict () метод Commit () может быть успешно назван. Коммит может быть успешно сохранен, потому что перед вызовом Commit () метод flush () будет называться неявно, то есть очистить кэш и искать объекты во временной коллекции для вставки в базу данных. Тем не менее, вы обнаружите, что во временном сборе нет данных, поэтому оператор INSERT не будет выпущена, а свойство существования IndistenceContext не будет обновлено.
Через вышеупомянутые случаи мы видим, что иногда нам нужно вызвать метод промывки () для очистки кэша. Кроме того, мы также нашли проблему из вышеизложенного, то есть, когда мы сохраняем () данные, мы не можем видеть данные перед его отправкой, то есть уровень изоляции базы данных ограничен. Теперь давайте поговорим о уровне изоляции MySQL:
1. Проверьте текущий уровень изоляции базы данных MySQL:
Выберите @@ tx_isolation;
ПРИМЕЧАНИЕ. Из рисунка мы видим, что уровень изоляции по умолчанию базы данных MySQL повторяется, что означает, что не будет никакого невозвращаемого чтения, то есть оно должно быть отправлено, прежде чем его можно будет прочитать.
2. Измените текущий уровень изоляции MySQL (при условии, что он не представлен для чтения, то есть его можно прочитать без коммита):
set transaction isolation level read uncommited;
Выше приведено подробное объяснение кода hibernate session_flush и уровня изоляции. Я надеюсь, что это будет полезно для всех. Заинтересованные друзья могут продолжать ссылаться на другие связанные темы на этом сайте. Если есть какие -либо недостатки, пожалуйста, оставьте сообщение, чтобы указать это. Спасибо, друзья, за вашу поддержку на этом сайте!