- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章详解Java的Hibernate框架中的缓存与二级缓存由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
缓存 。
今天我们就来讲一下hibernate中实体状态和hibernate缓存。 1)首先我们先来看一下实体状态: 实体状态主要分三种:transient,persitent,detached。 看英文应该就大概明白了吧。 transient:是指数据还没跟数据库中的数据相对应。 persistent:是指数据跟数据库中的数据相对应,它的任何改变都会反映到数据库中。 detached:是指数据跟数据库中的数据相对应,但由于session被关闭,它所做的修改不会对数据库的记录造成影响。 下面我们直接代码来:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
Transaction tx = session.beginTransaction();
User user =
new
User();
user.setName(
"shun"
);
//这里的user还未保存到数据库,数据库表中并没有与之对应的记录,它为transient状态
session.save(user);
tx.commit();
//提交之后user变为persistent状态
session.close();
//由于session关闭,此时的user为detached状态,它的所有修改都不会反映到数据库中。
Session session2 = sessionFactory.openSession();
tx = session2.beginTransaction();
user.setName(
"shun123"
);
session2.saveOrUpdate(user);
tx.commit();
//当我们调用了saveOrUpdate之后,user重新变为persistent状态,它的所有修改都会反映到数据库中。
session2.close();
|
我们看到代码,首先我们定义了一个对象user,在未保存之前,它就是transient状态,在数据库中并没有与它相应的记录。而当我们进行保存并提交修改后,user成为persistent状态,在数据库中有相应的一条记录。而当我们把session关闭后,user就变成了detached状态了,它的更改并不会反映到数据库中,除非我们手动调用saveOrUpdate等相应的更新和添加方法。而当我们直接想让它从persistent到transient状态,怎么办呢?直接删除就可以了,删除后对象就在数据库中没有对应的记录,也就成transient状态了。 hibernate的状态转换还是比较简单的,当是transient状态时,数据库没有记录对应,而persistent和detached时都有对应的记录,但唯一的区别是detached是在session关闭之后才有的状态。那么transient和detached的区别又是什么呢?就是有没有数据库表记录对应的问题。 2)看完了状态我们来看一下hibernate的缓存 hibernate的缓存分两种,一级缓存和二级缓存。 一级缓存:所谓的一级缓存也就是内部缓存。 二级缓存:它包括应用级缓存,在hibernate就是所谓的SessionFactory缓存,另外一个是分布式缓存,这个是最安全的缓存方式。 直接来看程序:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
public
static
void
main(String[] args) {
Configuration cfg =
new
Configuration().configure();
SessionFactory sessionFactory = cfg.buildSessionFactory();
Session session = sessionFactory.openSession();
User user = (User)session.load(User.
class
,
new
Long(
29
));
System.out.println(user.getName());
User user2 = (User)session.load(User.
class
,
new
Long(
29
));
System.out.println(user2.getName());
session.close();
}
|
看结果:
1
2
3
|
Hibernate: select user0_.USER_ID as USER1_0_0_, user0_.USER_NAME as USER2_0_0_, user0_.age as age0_0_ from USER user0_ where user0_.USER_ID=?
shun123123
shun123123
|
例子中我们用了两次load,但结果中只有一句SQL语句,这表明它只查询了一次。 为什么呢?这也就是hibernate的缓存起作用了。第一次查询完毕后,hibernate后把查出来的实体放在缓存中,下一次查的时候首先会查缓存,看有没有对应ID的实体存在,如果有则直接取出,否则则进行数据库的查询。 下面我们把代码修改成:
1
2
3
4
5
6
7
8
9
|
User user = (User)session.load(User.
class
,
new
Long(
29
));
System.out.println(user.getName());
session.evict(user);
//把user从缓存中删掉
User user2 = (User)session.load(User.
class
,
new
Long(
29
));
System.out.println(user2.getName());
session.close();
|
看到结果:
1
2
3
4
|
Hibernate: select user0_.USER_ID as USER1_0_0_, user0_.USER_NAME as USER2_0_0_, user0_.age as age0_0_ from USER user0_ where user0_.USER_ID=?
shun123123
Hibernate: select user0_.USER_ID as USER1_0_0_, user0_.USER_NAME as USER2_0_0_, user0_.age as age0_0_ from USER user0_ where user0_.USER_ID=?
shun123123
|
自己我们把user从缓存中删除后,第二次的查询也直接从数据库中取出.
二级缓存小谈 先看实体类:
1
2
3
4
5
6
7
|
public
class
User
implements
Serializable{
public
Long id;
private
String name;
private
int
age;
}
|
映射文件就省略啦,大家应该都会写的。 再来看看hibernate配置文件:
1
2
3
|
<
property
name
=
"hibernate.cache.provider_class"
>org.hibernate.cache.EhCacheProvider</
property
>
<
property
name
=
"hibernate.cache.use_second_level_cache"
>true</
property
>
<
property
name
=
"hibernate.cache.use_query_cache"
>true</
property
>
|
我们看到provider_class中我们指定了ehcache这个提供类,所以我们也需要ehcache.xml放在classpath中:
1
2
3
4
5
6
7
8
9
10
11
|
<?
xml
version
=
"1.0"
encoding
=
"UTF-8"
?>
<
ehcache
>
<
diskStore
path
=
"java.io.path"
/>
<
defaultCache
maxElementsInMemory
=
"10000"
eternal
=
"false"
timeToIdleSeconds
=
"120"
timeToLiveSeconds
=
"120"
overflowToDisk
=
"true"
/>
</
ehcache
>
|
接下来,我们直接看一下测试方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
public
static
void
main(String[] args) {
Configuration cfg =
new
Configuration().configure();
SessionFactory sessionFactory = cfg.buildSessionFactory();
Session session = sessionFactory.openSession();
Query query = session.createQuery(
"from User user where name = 'shun123'"
);
Iterator iter = query.iterate();
while
(iter.hasNext()) {
System.out.println(((User)iter.next()).getName());
}
session.close();
Session session2 = sessionFactory.openSession();
Query query2 = session2.createQuery(
"from User user where name='shun123'"
);
Iterator iter2 = query2.iterate();
while
(iter2.hasNext()) {
System.out.println(((User)iter2.next()).getName());
}
session2.close();
}
|
运行后可以看到:
1
2
3
4
5
|
Hibernate: select user0_.USER_ID as col_0_0_ from USER user0_ where user0_.USER_NAME='shun123'
Hibernate: select user0_.USER_ID as USER1_0_0_, user0_.USER_NAME as USER2_0_0_, user0_.age as age0_0_ from USER user0_ where user0_.USER_ID=?
shun123
Hibernate: select user0_.USER_ID as col_0_0_ from USER user0_ where user0_.USER_NAME='shun123'
shun123
|
我们可以看到它只执行了一句搜索,而在第二次查询时并没有取出ID进行搜索,这主要归功于二级缓存。 下面我们先分析一下测试方法中的代码。测试方法中我们分别打开了两个Session并且分别创建两个Query进行相同的查询。但两次Session可以共用缓存,这也就是二级缓存,SessionFactory级的缓存。只要我们的Session由同一个SessionFactory创建,那么我们就可以共用二级缓存减少与数据库的交互。 我们再来看一下配置文件中的意思:
1
2
3
|
<
property
name
=
"hibernate.cache.provider_class"
>org.hibernate.cache.EhCacheProvider</
property
>
<
property
name
=
"hibernate.cache.use_second_level_cache"
>true</
property
>
<
property
name
=
"hibernate.cache.use_query_cache"
>true</
property
>
|
如果我们需要使用二级缓存,首先需要配置:
1
|
<
property
name
=
"hibernate.cache.use_second_level_cache"
>true</
property
>
|
进行开户二级缓存,然后通过:
1
|
<
property
name
=
"hibernate.cache.provider_class"
>org.hibernate.cache.EhCacheProvider</
property
>
|
指定二级缓存的提供类,一般情况下我们都用ehcache,其他我的暂时没用到,也不太清楚,所以暂时不讲了。 像我们刚才的例子,我们只需要配置上面两个,完全可以正常运行,利用二级缓存。 那么第三句是干什么用的呢?
1
|
<
property
name
=
"hibernate.cache.use_query_cache"
>true</
property
>
|
这个配置指明了我们在查询时需要利用缓存,如果我们需要用到这个要事先调用query.setCacheable(true)这个方法来进行启用。 我们一起来看代码(我们先不启用缓存):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
public
static
void
main(String[] args) {
Configuration cfg =
new
Configuration().configure();
SessionFactory sessionFactory = cfg.buildSessionFactory();
Session session = sessionFactory.openSession();
Query query = session.createQuery(
"from User user where name = 'shun123'"
);
List list = query.list();
for
(
int
i =
0
; i < list.size(); i++){
System.out.println(((User)list.get(i)).getName());
}
session.close();
Session session2 = sessionFactory.openSession();
Query query2 = session2.createQuery(
"from User user where name='shun123'"
);
List list2 = query2.list();
for
(
int
i =
0
; i < list2.size(); i++){
System.out.println(((User)list.get(i)).getName());
}
session2.close();
}
|
这里输出的结果是:
1
2
3
4
|
Hibernate: select user0_.USER_ID as USER1_0_, user0_.USER_NAME as USER2_0_, user0_.age as age0_ from USER user0_ where user0_.USER_NAME='shun123'
shun123
Hibernate: select user0_.USER_ID as USER1_0_, user0_.USER_NAME as USER2_0_, user0_.age as age0_ from USER user0_ where user0_.USER_NAME='shun123'
shun123
|
我们看到,它并没有利用缓存,因为我们这里用了list,而list对缓存是只写不读的。所以这里会进行两次查询。 那么我们来修改一下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
public
static
void
main(String[] args) {
Configuration cfg =
new
Configuration().configure();
SessionFactory sessionFactory = cfg.buildSessionFactory();
Session session = sessionFactory.openSession();
Query query = session.createQuery(
"from User user where name = 'shun123'"
);
<span style=
"background-color: #ffffff;"
><span style=
"color: #ff0000;"
>query.setCacheable(
true
);</span></span>
List list = query.list();
for
(
int
i =
0
; i < list.size(); i++){
System.out.println(((User)list.get(i)).getName());
}
session.close();
Session session2 = sessionFactory.openSession();
Query query2 = session2.createQuery(
"from User user where name='shun123'"
);
<span style=
"color: #ff0000;"
>query2.setCacheable(
true
);</span>
List list2 = query2.list();
for
(
int
i =
0
; i < list2.size(); i++){
System.out.println(((User)list.get(i)).getName());
}
session2.close();
}
|
看到红色的两句代码,这是我们进行添加的两个开启查询缓存的代码,现在我们看到结果:
1
2
3
|
Hibernate: select user0_.USER_ID as USER1_0_, user0_.USER_NAME as USER2_0_, user0_.age as age0_ from USER user0_ where user0_.USER_NAME='shun123'
shun123
shun123
|
只剩一次查询了,为什么呢?就在那两句红色代码处,我们开启了缓存,记住,需要使用两次。把两个query都设成可缓存的才能使用查询缓存。 Criteria也是类似的做法,为免有些童鞋忘记了Criteria怎么写了,我还是放一下代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
public
static
void
main(String[] args) {
Configuration cfg =
new
Configuration().configure();
SessionFactory sessionFactory = cfg.buildSessionFactory();
Session session = sessionFactory.openSession();
Criteria criteria1 = session.createCriteria(User.
class
);
criteria1.setCacheable(
true
);
criteria1.add(Restrictions.eq(
"name"
,
"shun123"
));
List list = criteria1.list();
for
(
int
i =
0
; i < list.size(); i++){
System.out.println(((User)list.get(i)).getName());
}
session.close();
Session session2 = sessionFactory.openSession();
Criteria criteria2 = session2.createCriteria(User.
class
);
criteria2.setCacheable(
true
);
criteria2.add(Restrictions.eq(
"name"
,
"shun123"
));
List list2 = criteria2.list();
for
(
int
i =
0
; i < list2.size(); i++){
System.out.println(((User)list.get(i)).getName());
}
session2.close();
}
|
我们看结果:
1
2
3
|
Hibernate: select this_.USER_ID as USER1_0_0_, this_.USER_NAME as USER2_0_0_, this_.age as age0_0_ from USER this_ where this_.USER_NAME=?
shun123
shun123
|
最后此篇关于详解Java的Hibernate框架中的缓存与二级缓存的文章就讲到这里了,如果你想了解更多关于详解Java的Hibernate框架中的缓存与二级缓存的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我阅读了有关 JSR 107 缓存 (JCache) 的内容。 我很困惑:据我所知,每个 CPU 都管理其缓存内存(无需操作系统的任何帮助)。 那么,为什么我们需要 Java 缓存处理程序? (如果C
好吧,我是 jQuery 的新手。我一直在这里和那里搞乱一点点并习惯它。我终于明白了(它并不像某些人想象的那么难)。因此,鉴于此链接:http://jqueryui.com/sortable/#dis
我正在使用 Struts 2 和 Hibernate。我有一个简单的表,其中包含一个日期字段,用于存储有关何时发生特定操作的信息。这个日期值显示在我的 jsp 中。 我遇到的问题是hibernate更
我有点不确定这里发生了什么,但是我试图解释正在发生的事情,也许一旦我弄清楚我到底在问什么,就可能写一个更好的问题。 我刚刚安装了Varnish,对于我的请求时间来说似乎很棒。这是一个Magneto 2
解决 Project Euler 的问题后,我在论坛中发现了以下 Haskell 代码: fillRow115 minLength = cache where cache = ((map fill
我正试图找到一种方法来为我网络上的每台计算机缓存或存储某些 python 包。我看过以下解决方案: pypicache但它不再被积极开发,作者推荐 devpi,请参见此处:https://bitbuc
我想到的一个问题是可以从一开始就缓存网络套接字吗?在我的拓扑中,我在通过双 ISP 连接连接到互联网的 HAProxy 服务器后面有 2 个 Apache 服务器(带有 Google PageSpee
我很难说出不同缓存区域 (OS) 之间的区别。我想简要解释一下磁盘\缓冲区\交换\页面缓存。他们住在哪里?它们之间的主要区别是什么? 据我了解,页面缓存是主内存的一部分,用于存储从 I/O 设备获取的
1.题目 请你为最不经常使用(LFU)缓存算法设计并实现数据结构。 实现 LFUCache 类: LFUCache(int capacity) - 用数据结构的容量 capacity 初始化对象 in
1.题目 请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。 实现 LRUCache 类: ① LRUCache(int capacity) 以正整数作为容量 capacity
我想在访问该 View 时关闭某些页面的缓存。它适用于简单查询模型对象的页面。 好像什么时候 'django.middleware.cache.FetchFromCacheMiddleware', 启
documents为 ExePackage element state Cache属性的目的是 Whether to cache the package. The default is "yes".
我知道 docker 用图层存储每个图像。如果我在一台开发服务器上有多个用户,并且每个人都在运行相同的 Dockerfile,但将镜像存储为 user1_myapp . user2 将其存储为 use
在 Codeigniter 中没有出现缓存问题几年后,我发现了一个问题。我在其他地方看到过该问题,但没有适合我的解决方案。 例如,如果我在 View 中更改一些纯 html 文本并上传新文件并按 F5
我在 Janusgraph 文档中阅读了有关 Janusgraph Cache 的内容。关于事务缓存,我几乎没有怀疑。我在我的应用程序中使用嵌入式 janusgrah 服务器。 如果我只对例如进行读取
我想知道是否有来自终端的任何命令可以用来匹配 Android Studio 中执行文件>使缓存无效/重新启动的使用。 谢谢! 最佳答案 According to a JetBrains employe
我想制作一个 python 装饰器来内存函数。例如,如果 @memoization_decorator def add(a, b, negative=False): print "Com
我经常在 jQuery 事件处理程序中使用 $(this) 并且从不缓存它。如果我愿意的话 var $this = $(this); 并且将使用变量而不是构造函数,我的代码会获得任何显着的额外性能吗?
是的,我要说实话,我不知道varnish vcl,我可以解决一些基本问题,但是我不太清楚,这就是为什么我遇到问题了。 我正在尝试通过http请求设置缓存禁止,但是该请求不能通过DNS而是通过 Varn
在 WP 站点上加载约 4000 个并发用户时遇到此问题。 这是我的配置: F5 负载均衡器 ---> Varnish 4,8 核,32 Gb RAM ---> 9 个后端,4 个核,每个 16 RA
我是一名优秀的程序员,十分优秀!