hibernate缓存不解

2019-03-25 13:51|来源: 网路

大家看一下这段代码
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Session s = sessionFactory.openSession();
s.beginTransaction();
for(int i=0;i<10;i++)
{
   Cat cat = new Cat();
   cat.setWeight(20.1f);
   cat.setName("cat_"+i);//此处改变了name属性的值,即使不改变,我也要求它插入新的十条数据
  s.save(cat);
}
s.getTransaction().commit();

映射文件:Cat.hbm.xml
<hibernate-mapping>

    <class name="org.hibernate.entity.Cat" table="CAT">

        <!-- A 32 hex character is our surrogate key. It's automatically
            generated by Hibernate with the UUID pattern. -->
        <id name="id" type="string" unsaved-value="null" >
            <column name="CAT_ID" sql-type="char(32)" not-null="true"/>
            <generator class="uuid.hex"/>
        </id>

        <!-- A cat has to have a name, but it shouldn' be too long. -->
        <property name="name">
            <column name="NAME" length="16" not-null="true"/>
        </property>

        <property name="sex"/>

        <property name="weight"/><!--  -->
              
    </class>

</hibernate-mapping>
第一次执行插入操作时, i 的范围是从0到10,执行没有问题,向数据库中插入了十条正确的数据。
当第二次执行插入操作时,将  i  的范围改为从10到20,执行没有问题,
此次操作的结果“看起来”仅仅是对前面的数据进行修改,因为仅仅改变了其 name属性的值,其他的没有改变,而不是重新插入,这是为什么呢?也许是由于映射文件中对CAT_ID的设置有问题吗?
问题补充
肉嘎嘎 写道
为什么是修改,LZ说的修改是update吗?,你的代码上怎么没看出来有什么修改的啊?顶多就是又新增了10条数据!不解?

另外,对于save方法来说,当第一次持久化对象的时候,对象状态是从零时状态到了持久状态,这样数据库中存在了相应的记录(前10条记录),并且在缓存中保存了这10个对象和数据的快照,当你修改了循环次数,再次执行此方法的时候,由于你的属性没有任何改变,因此缓存快照的对象数据和你新创建的对象数据是一致的,所以在提交的时候,仅会对原有的数据重新做insert操作!

个人的分析,如有错误,请牛人指出,谢谢!~~~~~~

我的name属性已经发生了变化,即使没有发生变化,我执行的插入操作,它也应该给我执行插入操作!也许是某个设置上有问题,但一直没有找到解法
问题补充
amwiacel 写道
看看你的save是怎么实现的

兄弟,没用过hibernate吧!
问题补充
肉嘎嘎 写道
xiexifeng113 写道
肉嘎嘎 写道
为什么是修改,LZ说的修改是update吗?,你的代码上怎么没看出来有什么修改的啊?顶多就是又新增了10条数据!不解?

另外,对于save方法来说,当第一次持久化对象的时候,对象状态是从零时状态到了持久状态,这样数据库中存在了相应的记录(前10条记录),并且在缓存中保存了这10个对象和数据的快照,当你修改了循环次数,再次执行此方法的时候,由于你的属性没有任何改变,因此缓存快照的对象数据和你新创建的对象数据是一致的,所以在提交的时候,仅会对原有的数据重新做insert操作!

个人的分析,如有错误,请牛人指出,谢谢!~~~~~~

我的name属性已经发生了变化,即使没有发生变化,我执行的插入操作,它也应该给我执行插入操作!也许是某个设置上有问题,但一直没有找到解法


为什么没有变化也应该做插入操作呢?能说一下你的理由吗?

你好好看一下主帖嘛!难道我没说明白。我是说执行之后的结果,仅仅是修改了name的值,其他的没有变化,包括id。而我确实是需要进行插入操作。两次执行完之后,数据库的表中应该有20条数据,即对应的name值从cat_0到cat_19,而现在表中只有十条数据cat_10到cat_19。希望后来的人能看明白。

相关问答

更多
  • 这是面试中经常问到的一个问题,楼主可以按照我的思路回答,准你回答得很完美,首先说下Hibernate缓存的作用(即为什么要用缓存机制),然后再具体说说Hibernate中缓存的分类情况, 最后可以举个具体的例子。 Hibernate缓存的作用: Hibernate是一个持久层框架,经常访问物理数据库,为了降低应用程序对物理数据源访问的频次,从而提高应用程序的运行性能。缓存内的数据是对物理数据源中的数据的复制,应用程序在运行时从缓存读写数据,在特定的时刻或事件会同步缓存和物理数据源的数据 Hibernate ...
  • 你的意思是第一级缓存还是第二级缓存? 使用Hibernate二级缓存(如Ehcache)缓存与您手动修改的同一表中的行对应的实体可能会导致您描述的行为。 第一级缓存不会导致这种行为,无论如何,我认为你不能禁用它。 要禁用Hibernate第二级缓存,请从Hibernate配置文件hibernate-cfg.xml除去所有引用第二级缓存的行。 例如:
    实际上JPA2是规范,Hibernate是这个规范的实现。 它们都不提供缓存实现,除了会话缓存(您的实体在单个事务/会话交互中) 如果您打算添加替换hibernate的可能性,那么使用纯JPA2注释和配置。 Hibernate的注释@Cache对实体如何存储在缓存中提供了更细粒度的控制,JPA的@Cacheable只提供了包含在缓存中的可能性(缓存中的所有存储控制都是在一般的JPA配置和缓存实现中定义的) )。 actually JPA2 is specification and Hibernate is ...
  • Hibernate ORM提供两个级别的缓存 - 第一级缓存 :与每个会话对象关联的进程内缓存,仅限于会话级别,即每个会话都有自己的第一级缓存。 - 二级缓存 :需要配置的可插拔缓存。 它是会话工厂级缓存,即在多个会话之间共享。 像memcached / redis或Tayzgrid这样的缓存解决方案为hibernate提供了二级缓存提供程序,可以在hibernate应用程序中进行配置。 使用这样的缓存提供程序,您可以在hibernate应用程序中加入分布式缓存功能,就像缓存可以在多个会话之间共享以及使用同 ...
  • 当我通过多个线程反复执行相同的操作集时,我已经设置了一个简单的压力测试。 当我检查hibernate统计信息时,结果是查询缓存hitCount为零! 好吧,虽然可以从统计信息中获取有关缓存命中的统计信息( 如果通过在配置中设置属性hibernate.generate_statistics=true来启用统计信息),这是IMO不是诊断缓存“问题”的最佳方法。 我的建议是激活1.执行的DML语句和2.缓存活动的日志记录。 相关的日志记录类别是: org.hibernate.SQL在执行时记录所有SQL DML语 ...
  • Hibernate已经通过持久化上下文提供了称为第一级缓存的缓存机制。 它位于Session范围内,默认情况下处于启用状态,无法关闭。 缓存提供程序(如EHCache)提供了另一种称为第二级缓存的缓存机制。 它位于SessionFactory范围内。 默认情况下不启用二级缓存,您必须对其进行配置。 有关如何在休眠中启用EHCache的信息,请参阅此内容 。 Hibernate already provides a caching mechanisms called 1st level cache by th ...
  • Doe Hibernate使用缓存(第二级别或其他)如果我所做的只是批量插入? 新插入的实体实例在刷新到数据库之前会缓存在L1缓存(会话级别缓存)中(请参阅第13章“批处理” ),因此需要定期flush和clear会话以防止OOM。 另外,StatelessSession vs Session会改变答案吗? 是。 如第13.3节所述。 StatelessSession接口 : StatelessSession没有与其关联的持久性上下文,并且不提供许多更高级别的生命周期语义。 特别是, 无状态会话不会实现一级 ...
  • 快速不是一般的质量,必须在上下文中考虑性能。 一个好的方法似乎是: 代码足够快,足够高效,您需要在整个应用程序中使用许多查询。 之前完成该阶段 ,因为您编写的代码很快,您不会使用棘手的技术来提高性能。 找到不够快的1%查询,经常调用等等,因此它们构成了最多的总时间(仅考虑真实用户正在等待的那些)。 花足够的时间来优化这个 (你有这个时间,因为你在阶段1中获得了时间)。 你可以使用这么快的东西,你不会全局考虑它们(内存缓存,本机SQL,数据库程序......)。 回到2,直到你没时间,或者你的用户满意为止。 ...
  • 据我所知 答案01: Hibernate缓存加载的对象,以避免不必要的数据库访问。 避免持久化上下文的最简单方法是使用StatelessSession 。 无状态Hibernate会话没有脏检查责任,因此可以满足您不具备第一级缓存(Persistant Context)的要求。 答案02: 您不必启用第一级缓存 回答03 如果使用其标识在同一会话中加载了两次对象,则无论是否启用了二级缓存,Hibernate都会确保返回相同的对象。 让我澄清二级缓存不会缓存对象的实例 。 它维护实例的序列化(不完全)版本。 ...
  • 到目前为止,我已经看到高速缓存级别1仅用于在事务刷新之前暂停sql调用。 简而言之,第一级缓存只是从id(主键)到保存与该主键关联的状态的对象的映射。 但是,你不应该将会话和事务概念混为一谈,它们不是同一件事(并且会话不一定是事务范围)。 如果我在一次事务中多次加载同一个对象,会发生什么? 将只有一个对象表示数据库中的给定行(即对于给定的id)。 这就是为什么管理状态成为可能,这就是一级缓存的重点。 hibernate是否使用某种身份映射并缓存已在1个事务中加载的对象 往上看。 So far I've se ...