состояние объекта
Состояние объекта в Hibernate:
- временное / переходное состояние
- постоянное состояние
- свободный штат
Изучение состояния объекта HibernateДля того, чтобы яснее узнать конструкторскую идею Hibernate, и основу кэша первого уровня...и конечно немного знаний
временное/переходное состояние
когда мыОбъект непосредственно новый - это временное/переходное состояние..
- Объект не был сохранен [не сохранен в базе данных]
- Не управляется сеансом
постоянное состояние
Когда объект хранится в базе данных, это постоянное состояние.
- При вызове методов сохранения/сохранения или обновления/получения/загрузки/списка сеанса и других методов объект является постоянным состоянием.
- соответствующие данные в базе данных
- Управляется сеансом
- При внесении изменений в свойства объекта они будут отражены в базе данных!
Давайте проверим это:При внесении изменений в свойства объекта они будут отражены в базе данных!
session.save(idCard);
idCard.setIdCardName("我是测试持久化对象");
свободный штат
Когда сеанс закрывается, постоянный объект становится свободным...
- Не в управлении сессиями
- Имеются соответствующие записи в базе данных
Кэш L1
Hibernate имеет кеш первого уровня и кеш второго уровня.Здесь в основном объясняется кеш первого уровня.
Что такое кеш первого уровня?
Кэш первого уровня в Hibernate, также известный как кеш сеанса,Это может уменьшить количество посещений базы данных в рамках сеанса! Действует только в рамках сеанса! Сессия закрыта, кэш первого уровня недействителен!
Пока состояние постоянного объекта управляется сеансом, то есть он будет находиться в кэше сеанса!
Кэш сеанса поддерживается спящим режимом,Пользователь не может управлять кэшированным содержимым; если вы хотите управлять кэшированным содержимым, вы должны использовать метод evit/clear, предоставляемый спящим режимом..
Зачем использовать кеш?
Сократите количество посещений базы данных! Тем самым повышая эффективность выполнения hibernate!
тестовое задание
Давайте посмотрим, как Hibernate сокращает количество обращений к базе данных.
Теперь в моей таблице User есть такая запись:
//把数据放进cache
User user = (User) session.get(User.class, 1);
//发现要修改的字段和cache一样,不执行
user.setUserName("你好2");
То же самое верно для выборки данных
User user = null;
user = (User) session.get(User.class, 1);
user = (User) session.get(User.class, 1);
Методы, связанные с кэшем
Существует три широко используемых метода, связанных с кэшированием:
-
session.flush(); синхронизировать кеш первого уровня с базой данных
-
session.evict(arg0);Очистить указанный объект в кеше первого уровня
-
session.clear(); очищает все объекты, кэшированные в кеше первого уровня
-
clear
User user = null;
user = (User) session.get(User.class, 1);
//清除缓存,那么下面获取的时候,就不能从缓存里面拿了
session.clear();
user = (User) session.get(User.class, 1);
- flush
В случае кеша измените данные той же записи, в зависимости от того, какая из них последняя... Так что есть только одно обновление
User user = null;
user = (User) session.get(User.class, 1);
user.setUserName("我是第一");
user = (User) session.get(User.class, 1);
user.setUserName("我是第二");
я разрешаюЗаставил его и синхронизацию базы данныхЕсли да, то будет два обновления.
User user = null;
user = (User) session.get(User.class, 1);
user.setUserName("我是第一");
session.flush();
user = (User) session.get(User.class, 1);
user.setUserName("我是第二");
Как правило, мыиспользуется в пакетной обработке,потому чтоУ кеша тоже есть размер.Если в кеш вставить 1000 штук данных, то Hibernate может рухнуть....
- Каждое определенное количество записей сначала синхронизируйте с базой данных flush()
- Затем очистите кеш clear()
Стоит отметить, что:Разные сеансы не будут совместно использовать кеш!
Итератор и список
Когда мы используем HQL для запроса всех данных,Вы можете использовать list(), чтобы получить все данные, или вы можете использовать iterator(), чтобы получить итератор, а затем пройти по итератору.... так какая между ними разница?
. . . . Когда я смотрел видео, там было сказано:
Но когда я тестирую:Список также может получать кешированные данные
Конечно, Iterator также может получать кешированные данные.
следовательно,Удобно использовать list() при получении данных!
ленивая загрузка
Ленивая загрузка заключается в получении данных и выполнении соответствующего оператора SQL при использовании данных....Когда данные не использовались, соответствующие данные не будут загружены!
Основная цель состоит в том, чтобыУлучшить производительность Hibernate и повысить эффективность выполнения!
- get: загрузить вовремя, просто вызовите метод get, чтобы немедленно запросить базу данных
- load: по умолчанию используется ленивая загрузка, а запросы к базе данных выполняются только при использовании данных.
Ленивая загрузка снова
User user = (User) session.load(User.class, 1);
System.out.println("________");
System.out.println(user);
Мы можем соответствоватьФайл конфигурации задается с обычным ленивым атрибутом
Отключить ленивую загрузку:
<class name="IdCard" table="IdCard" lazy="false">
lazy имеет три свойства:
- истинное использование ленивой загрузки
- false отключить ленивую загрузку
-
дополнительно (для повышения эффективности при ленивой загрузке данных коллекции) [используется только в тегах коллекции, таких как набор и список]
- SQL-запрос отправляется в базу данных только тогда, когда данные фактически используются;
- Если вы вызываете метод коллекции size()/isEmpty(), это всего лишь статистика, а не запрос данных!
исключение ленивой загрузки
Когда сессия закрыта, отложенная загрузка не может быть использована, иначе будет сообщено об исключении
Exception in thread "main" org.hibernate.LazyInitializationException: could not initialize proxy - no Session
Когда об этом исключении сообщается, у нас есть 4 способа его решения:
- Способ 1: сначала используйте данные
- dept.getDeptName();
- Способ 2: принудительная инициализация прокси-объекта
- Hibernate.initialize(dept);
- Способ 3: отключить ленивую загрузку
- установить ленивый = ложь;
- **Метод 4: После использования данных закройте сеанс! **
Спящий кэш второго уровня
Мы уже объясняли кэш первого уровня ранее.Кэш первого уровня также является кэшем сеанса, который действителен только в рамках сеанса....время действия находится в рамках сеанса,относительно небольшой диапазон
Hibernate предоставляет нам функцию кэширования второго уровня:Кэш второго уровня — это кеш на основе приложений, который может использоваться всеми сессиями.
- Кэш второго уровня, предоставляемый Hibernate, имеет реализацию по умолчанию и являетсяПодключаемый фреймворк кэширования! Если пользователь хочет использовать кеш второго уровня,Просто нужно настроить в hibernate.cfg.xml; Если вы не хотите его использовать, удалите его напрямую, не затрагивая код.
- Если пользователи считают, что инфраструктура, предоставляемая спящим режимом, непроста в использовании,Вы можете перейти на другие фреймворки кэширования или реализовать свою собственную фреймворк кэширования..
Вторичный кэш с гибернацией:Часто используемые классы хранятся
Настроить кеш L2
Так как кеш второго уровня поставляется с Hibernate, то мы можемНайдите соответствующую информацию в файле hibernate.properties...
- #hibernate.cache.use_second_level_cache false [Кэш второго уровня не включен по умолчанию, и его необходимо включить вручную]
- #hibernate.cache.use_query_cache true [Включить кэш запросов]
-
выбрать реализацию кеша [реализация фреймворка кеша второго уровня]
- #hibernate.cache.provider_class org.hibernate.cache.EhCacheProvider
- #hibernate.cache.provider_class org.hibernate.cache.EmptyCacheProvider
- hibernate.cache.provider_class org.hibernate.cache.HashtableCacheProvider реализация по умолчанию
- #hibernate.cache.provider_class org.hibernate.cache.TreeCacheProvider
- #hibernate.cache.provider_class org.hibernate.cache.OSCacheProvider
- #hibernate.cache.provider_class org.hibernate.cache.SwarmCacheProvider
Через файл конфигурации мы можем обнаружить, что кеш второго уровня не включен по умолчанию, и нам нужно включить его вручную.Следующие шаги:
- 1) Включить кеш второго уровня
- 2) Укажите структуру кеша
- 3) Указать, какие классы добавляются в кеш второго уровня
Включить кеш L2
Включить кеш L2 в файле hibernate.cfg.xml
<!-- a. 开启二级缓存 -->
<property name="hibernate.cache.use_second_level_cache">true</property>
Укажите кадр кэша
Просто укажите структуру кэширования второго уровня, которая поставляется с Hibernate.
<!-- b. 指定使用哪一个缓存框架(默认提供的) -->
<property name="hibernate.cache.provider_class">org.hibernate.cache.HashtableCacheProvider</property>
Укажите, какие классы добавляются в кеш второго уровня
<!-- c. 指定哪一些类,需要加入二级缓存 -->
<class-cache usage="read-write" class="zhongfucheng.aa.Monkey"/>
<class-cache usage="read-only" class="zhongfucheng.aa.Cat"/>
тестовое задание:
Мы знаем, что кеш первого уровня — это кеш сеанса, тогда мы находимся вПротестируйте вторичный кеш при использовании двух сеансов, чтобы проверить все в порядке. Если второй сеанс получает кэшированные данные, это доказывает, что кэш второго уровня полезен.
package zhongfucheng.aa;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.classic.Session;
public class App5 {
public static void main(String[] args) {
//获取加载配置管理类
Configuration configuration = new Configuration();
//加载类对应的映射文件!
configuration.configure().addClass(Animal.class);
//创建Session工厂对象
SessionFactory factory = configuration.buildSessionFactory();
//得到Session对象
Session session1 = factory.openSession();
//使用Hibernate操作数据库,都要开启事务,得到事务对象
Transaction transaction = session1.getTransaction();
//开启事务
transaction.begin();
Monkey monkey = (Monkey) session1.get(Monkey.class,"40283f815be67f42015be67f43240001" );
System.out.println(monkey.getName());
System.out.println("-----------------------");
Session session2 = factory.openSession();
Transaction transaction2 = session2.getTransaction();
transaction2.begin();
Monkey monkey2 = (Monkey) session1.get(Monkey.class, "40283f815be67f42015be67f43240001");
System.out.println(monkey2.getName());
//提交事务
transaction.commit();
transaction2.commit();
//关闭Session
session1.close();
session2.close();
}
}
То, что вы получаете, это кешированные данные!
стратегия кэширования
Когда мы помещаем класс Animal в кеш второго уровня, использование доступно только для чтения.
Другими словами, вы можете только читать, а не писать, давайте посмотрим, что происходит, когда вы пишете:
monkey2.setName("小猴子");
Было выброшено исключение....
Есть 4 атрибута использования:
- ** Объекты, помещенные в кэш L2, доступны только для чтения; **
- нестрогое чтение и запись
- Чтение и запись, объекты, помещенные в кэш L2, могут быть прочитаны и записаны;
- (транзакционная стратегия)
Кэш коллекции
Если данные, которые мы запрашиваем в базе данных, представляют собой коллекцию...Hibernate не устанавливает кеш второго уровня для сбора данных по умолчанию... так что вам все еще нужно читать и записывать информацию о базе данных
Далее давайте посмотрим, что делает установка коллекции в качестве кеша второго уровня:
- В hibernate.cgf.xml настроить коллекцию в объекте как кеш второго уровня
<!-- 集合缓存[集合缓存的元素对象,也加加入二级缓存] -->
<collection-cache usage="read-write" collection="cn.itcast.b_second_cache.Dept.emps"/>
- Тестовый код:
public void testCache() {
Session session1 = sf.openSession();
session1.beginTransaction();
// a. 查询一次
Dept dept = (Dept) session1.get(Dept.class, 10);
dept.getEmps().size();// 集合
session1.getTransaction().commit();
session1.close();
System.out.println("------");
// 第二个session
Session session2 = sf.openSession();
session2.beginTransaction();
// a. 查询一次
dept = (Dept) session2.get(Dept.class, 10); // 二级缓存配置好; 这里不查询数据库
dept.getEmps().size();
session2.getTransaction().commit();
session2.close();
}
кэш запросов
list() и iterator() поместят данные в кеш первого уровня, но кеш первого уровня действителен только в рамках сеанса... Если вы хотитеДля использования между сеансами необходимо настроить кеш запросов.
Так же видим в конфиг файлеКэш запросов такой конфигурации..
#hibernate.cache.use_query_cache true 【开启查询缓存】
То есть,Данные запроса по умолчанию не помещаются в кеш второго уровня., если мы хотим поместить запрошенные данные в кеш второго уровня, нам нужновключить в конфигурационном файле
<!-- 开启查询缓存 -->
<property name="hibernate.cache.use_query_cache">true</property>
- Когда запрос с использованием программы, но также также вызовов SETCAACHIBLE () метод, установите кэш запроса.
@Test
public void listCache() {
Session session1 = sf.openSession();
session1.beginTransaction();
// HQL查询 【setCacheable 指定从二级缓存找,或者是放入二级缓存】
Query q = session1.createQuery("from Dept").setCacheable(true);
System.out.println(q.list());
session1.getTransaction().commit();
session1.close();
Session session2 = sf.openSession();
session2.beginTransaction();
q = session2.createQuery("from Dept").setCacheable(true);
System.out.println(q.list()); // 不查询数据库: 需要开启查询缓存
session2.getTransaction().commit();
session2.close();
}
Если в статье есть какие-либо ошибки, пожалуйста, поправьте меня, и мы сможем общаться друг с другом. Учащиеся, привыкшие читать технические статьи в WeChat и желающие получить больше ресурсов по Java, могутОбратите внимание на публичный аккаунт WeChat: Java3y