我有一个问题Hibernate不会为级联删除主题的项目集合更新二级缓存.
假设我们有一个对象Parent,它包含Parent对象的Parent.myChildren集合.现在我们还将人类与Humans.myAllHumans集合以及所有Parent和Child对象放在该集合中.
现在我们session.delete(父)和所有的孩子都从数据库中删除了级联,但是Humans.myAllHumans集合的缓存没有更新!它仍然假设级联删除的对象在数据库中,并且我们在稍后尝试对集合进行迭代时遇到以下异常:
org.hibernate.ObjectNotFoundException:不存在具有给定标识符的行:[foo.Child#751]
1)我已经尝试过SessionFactory.evictCollection()方法,但据我所知,它不是事务安全且很难从二级缓存中删除数据,我不希望这样.
2)我也可以手动(以编程方式)从myAllHumans集合中删除每个对象.在这种情况下,hibernate会更新第二级缓存.这种方法我想避免,因为它只是使级联删除功能无用.
我希望hibernate足够聪明,可以自动更新集合的缓存.可能吗?
我现在正在使用EhCache,您认为使用其他缓存实现还是配置EhCache可能会有所帮助?
我正在开发一个Web应用程序,我希望缓存在Web请求中持续存在.我知道第一级缓存只是每个会话.我启用了二级缓存,这适用于查询.
但是,二级缓存似乎不适用于"获取"实体...因此,应用程序所做的大部分数据库工作都不会跨Web请求进行缓存.
这是正常/理想的行为吗?我正在审查一个特定的页面,它会对数据库进行大量的往返,尽管每个查询都很快,如果可以缓存实体,这些似乎是不必要的.
编辑
好的,所以我启用了二级缓存,并且正在进行查询.我似乎无法让它为实体工作.我Cache.Is(c => c.ReadWrite())在我正在测试的主要实体上(流利的nhibernate).但不,它每次都会击中数据库.有任何想法吗?
编辑
我尝试过这样的交易:
public override Accommodation Get(int id)
{
using (var tx = Session.BeginTransaction())
{
var accomm = Session.Get<Accommodation>(id);
tx.Commit();
return accomm;
}
}
Run Code Online (Sandbox Code Playgroud)
我的映射是这样的(你可以看到我们有一个讨厌的架构):
public void Override(AutoMapping<Core.Entities.Itinerary.Accommodation.Accommodation> mapping)
{
mapping.HasManyToMany(x => x.Features).Table("AccommodationLinkFeatureType").ChildKeyColumn("FeatureTypeId").NotFound.Ignore();
mapping.HasManyToMany(x => x.SimilarAccommodation).Table("AccommodationLinkSimilarAccommodation").ChildKeyColumn("SimilarAccommodationId").NotFound.Ignore();
mapping.HasMany(x => x.TourItinerary).Table("AccommodationTourItinerary");
mapping.HasOne(x => x.Images).ForeignKey("AccommodationId").Cascade.All().Not.LazyLoad();
mapping.References(x => x.CollectionType).NotFound.Ignore().Not.LazyLoad();
mapping.References(x => x.AccommodationUnitType).NotFound.Ignore().Not.LazyLoad();
Cache.Is(c => c.ReadWrite());
}
Run Code Online (Sandbox Code Playgroud)
但是,这似乎仍然没有从二级缓存中获取.
顺便说一句,我看到很多在线使用的例子,Cache.ReadWrite()但我只能Is在Cache帮助器上看到一个方法,所以我正在尝试Cache.Is(c => c.ReadWrite())- 更改流畅的界面?
我们有一个Java应用程序,它使用MySQL,Hibernate(3.5.1-Final)和EHcache(1.2.3)作为我们的二级缓存.
我们的hibernate.properties隔离级别是Read-committed isolation = 2
# 2-Read committed isolation
hibernate.connection.isolation=2
Run Code Online (Sandbox Code Playgroud)
在大量并发事务中,我们看到一个问题,即加载时某些集合(数据库关联)将抛出ObjectNotFoundException,并且看起来第二级缓存正在返回该集合的旧副本.
我们有许多不同类型的交易来访问这个集合(只读取),只有一些会添加/删除它的项目.
我们在单个事务负载或甚至中等事务负载(10 - 20个并发连接)下都没有看到此问题.
例如,我们有一个Character实体:
@Entity
@Table(name = "CHARACTERS")
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class Character extends AbstractCharacter implements Serializable {
...
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@OneToMany(mappedBy = "character", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private Set<CharacterItem> items;
Run Code Online (Sandbox Code Playgroud)
我们正在通过从包含它们的集合中删除实体并调用session.delete()来删除实体时正确维护对象图.
character.getItems().remove(characterItem);
session.delete(characterItem);
Run Code Online (Sandbox Code Playgroud)
我们尝试过更改Set项目; CacheConcurrencyStrategy来自:
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
private Set<CharacterItem> items;
Run Code Online (Sandbox Code Playgroud)
至
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
private Set<CharacterItem> items;
Run Code Online (Sandbox Code Playgroud)
没有运气.
我们不使用数据库锁,而是使用乐观并发控制来捕获和重试冲突的事务.
目前我们只能看到两个解决方案:
尝试捕获ObjectNotFoundException并尝试智能地逐出集合(尽管在异常中似乎没有足够的上下文)
在items集合上使用@NotFound(action = NotFoundAction.IGNORE)注释,它将忽略而不抛出ObjectNotFoundException(但是我们关注它如何与二级缓存一起工作并确保它正在查看正确的数据) .
我希望能有一个@NotFound(动作= …
我正在尝试使用基于EHCache的二级缓存配置Spring Boot应用程序.我得到了这个例外:
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.cache.NoCacheRegionFactoryAvailableException: Second-level cache is used in the application, but property hibernate.cache.region.factory_class is not given; please either disable second level cache or set correct region factory using the hibernate.cache.region.factory_class setting and make sure the second level cache provider (hibernate-infinispan, e.g.) is available on the classpath.
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1554)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:539)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:302)
at …Run Code Online (Sandbox Code Playgroud) 我们的Java应用程序有大约100个映射到数据库(SQL Server或MySQL)的类.我们使用Hibernate作为我们的ORM(使用XML映射文件).
我们FOREIGN KEY在数据库模式中指定约束.我们的大多数FOREIGN KEY约束也都指明了ON DELETE CASCADE.
我们最近开始启用Hibernate二级缓存(针对流行的实体和集合)来缓解一些性能问题.
自从我们启用了二级缓存后,性能得到了提升.但是我们也开始遇到ObjectNotFoundExceptions.
似乎发生了ObjectNotFoundExceptions,因为数据库正在删除Hibernate 下面的表行.例如,当我们Parent使用Hibernate 删除a 时,数据库模式将ON DELETE CASCADE发送给任何Child实体.这显然没有Hibernates知识,所以它没有机会更新二级缓存(并删除任何已删除的Child实体).
我们相信这个问题的解决方案是ON DELETE CASCADE从我们的数据库模式中删除(但保留FOREIGN KEYs).相反,我们需要配置Hibernate来删除Child正常删除SQL的依赖关系,这也将使Hibernate更新二级缓存.一些有限的测试表明这种方法似乎有效.
我想得到一些社区反馈.我们的问题是否有其他(更好的?)解决方案?其他人如何处理这种情况?通常,在使用ON DELETE CASCADEHibernate的数据库模式中应该考虑哪些权衡?
谢谢.
我们现在使用Hazelcast作为Hibernate二级缓存一段时间,但是在使用多个节点时,我们认识到存储和读取数据的长时间延迟.
我们大量使用组合对象和@OneToMany关系,为了提高性能,我们决定通过Hibernate延迟加载来加载这些组合对象或集合.我们还实现了DataSerializable以加速Hazelcast序列化,正如Hazelcast文档中所述.但是记录writeData/readData方法的使用向我们表明它们实际上并没有被使用!
我们现在还不清楚,如果Hibernate Proxy(通过延迟加载使用)阻止使用DataSerializable方法(因为代理本身可能(?)没有实现接口)而且 - 更重要的是 - 如果Hazelcast支持延迟加载根本 - 以及如何!
我们在asp.net mvc 4(.net 4)应用程序中使用NHibernate 4.据我所知,NHibernate 4的行为在二级缓存方面有所改变.
以下行为似乎已经改变(如果我错了,请纠正我):
在我看来,第二级仅适用于以下情况:
using (var hibSession = SessionFactory.OpenSession())
{
// Second level cache working
var entity = hibSession.Get<ChachedEntity>(7); // second level cache working
var parent = entity.ParentElement; // second level cache working because n:1
// Probably working (not tested)
var elements = hibSession.Query<ChachedEntity>().Cacheable().Take(30).ToList(); // guessed behaviour: query-cache selects id's and then then uses second level cache
// second level cache NOT Working
var children = entity.ChildCollectionWithCachableEntities; …Run Code Online (Sandbox Code Playgroud) 在花了几天时间弄清楚为什么我的二级缓存配置为学说不起作用之后,我希望有人能够支持.目前没有二级缓存调用导致命中.
我的项目目前使用以下软件包进行设置(+其他一些可能与此设置无关的软件包):
"symfony/symfony": "2.6.*",
"doctrine/orm": "2.*",
"doctrine/dbal": "2.*",
"doctrine/doctrine-bundle": "~1.2"
...
"snc/redis-bundle": "1.*"
Run Code Online (Sandbox Code Playgroud)
Doctrine缓存的设置方式如下:
orm:
auto_generate_proxy_classes: "%kernel.debug%"
auto_mapping: true
metadata_cache_driver: redis
query_cache_driver: redis
result_cache_driver: redis
second_level_cache:
enabled: true
log_enabled: true
Run Code Online (Sandbox Code Playgroud)
元数据和查询缓存似乎正常工作,因为在Redis中创建了密钥,而SNC Redis Bundle也正确记录了我的缓存命中.但是"2l Cache"只记录未命中和放置,而不是命中:
在我的调试过程中,我发现在Doctrine/ORM/Query的缓存请求中尝试访问ArrayCache而不是配置的缓存驱动程序.
如果某人有二级缓存的工作示例配置,它可能已经有所帮助,因为它既不适用于我的Redis,也不适用于APCu或memcached.
我希望有人有想法或者可以分享他的工作配置.
在此先感谢您的问候
让我清楚地了解二级缓存。我的 Web 应用程序的基类中有一个查询。几乎每个操作都会调用此查询(我使用的是 Struts,这就是应用程序的设计方式,因此不能真正弄乱它),例如加载我的主页调用三个单独的 Struts 操作,并且为每个操作执行此查询。QueryDsl 形式的查询看起来像
Iterable<Event> eventsFromDb2 = eventRepository.findAll(EventExpressions.queryAllEvents());
,在简化形式中看起来像Select e from Event e where e.deleted = false
这个查询占用了大约 10 秒的甜蜜时间,因此它使应用程序变得非常慢,因为它调用了 Web 应用程序的每个操作(CRUD)。根据我的理解,在启用二级缓存时,hibernate+ Spring orm 应该从缓存中获取结果并避免数据库请求。但是,它不起作用。persistence.xml 如下所示
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/jdbc
http://www.springframework.org/schema/jdbc/spring-jdbc-3.1.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" depends-on="flyway">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="de.mm.moreevent.type" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="false" />
<property name="databasePlatform" value="org.hibernate.dialect.PostgreSQLDialect" />
<property name="generateDdl" value="true" />
</bean>
</property>
<property name="jpaPropertyMap">
<map>
<entry key="hibernate.cache.use_query_cache" value="true" />
<entry key="hibernate.cache.use_second_level_cache" …Run Code Online (Sandbox Code Playgroud) 我使用 Springboot 2.1 和 spring data-jpa 使用@RepositoryRestResource进行持久化。我已经为我的 API 调用启用了缓存,并且它与@Cacheable配合得很好,但是现在我想为我的所有 JPA 实体启用二级缓存并且具有以下配置,但仍然对这些实体的任何查询都在触发休眠查询而不使用缓存. 请让我知道我缺少此实体缓存的内容。
Gradle依赖:
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
implementation 'org.springframework.boot:spring-boot-starter-data-rest'
implementation 'org.springframework.boot:spring-boot-starter-hateoas'
implementation 'org.springframework.boot:spring-boot-starter-jersey'
implementation 'org.springframework.boot:spring-boot-starter-cache'
implementation 'org.ehcache:ehcache:3.7.1'
implementation 'javax.cache:cache-api'
compile group: 'org.hibernate', name: 'hibernate-jcache', version: '5.3.10.Final'
runtimeOnly 'mysql:mysql-connector-java'
Run Code Online (Sandbox Code Playgroud)
}
应用程序属性
spring.datasource.url=jdbc:mysql://localhost:3306/mar_db
spring.datasource.username=root
spring.datasource.password=
spring.jpa.database-platform=org.hibernate.dialect.MySQL57Dialect
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.cache.use_query_cache=true
spring.jpa.properties.hibernate.cache.use_second_level_cache=true
spring.jpa.properties.hibernate.cache.region.factory_class=org.hibernate.cache.jcache.JCacheRegionFactory
spring.jpa.properties.javax.persistence.sharedCache.mode=ENABLE_SELECTIVE
spring.cache.jcache.config=classpath:ehcache.xml
Run Code Online (Sandbox Code Playgroud)
缓存文件
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.ehcache.org/v3"
xmlns:jsr107="http://www.ehcache.org/v3/jsr107">
<service>
<jsr107:defaults enable-statistics="true" />
</service>
<cache alias="readOnlyEntityData">
<key-type>java.lang.Object</key-type>
<expiry>
<ttl unit="minutes">360</ttl> …Run Code Online (Sandbox Code Playgroud) hibernate ×6
java ×4
caching ×3
ehcache ×3
jpa ×2
nhibernate ×2
spring-boot ×2
cascade ×1
concurrency ×1
doctrine-orm ×1
ehcache-3 ×1
foreign-keys ×1
hazelcast ×1
lazy-loading ×1
redis ×1
spring-mvc ×1
spring-orm ×1
symfony ×1