我正在用SpringDataJPA开发SpringBoot2.3.4Web应用程序。
我想将Hibernate 2级查询缓存用于带有@EntityGraph的存储库方法。但是,如果数据已经在2级缓存中,除非打开了Spring的Open Session in view,否则在生成Thymeleaf视图时会出现LazyInitializationException。当第一次从数据库中获取数据或不使用二级缓存时,即使使用spring.jpa.open in view=false,一切都正常。此外,如果启用spring.jpa.open-in-view,则从缓存中获取数据时不会出现异常,而不会对数据库进行任何选择。
使用Hibernate二级缓存时,如何使Hibernate立即获取@EntityGraph中指定的所有关联?
以下是我的存储库方法:
@org.springframework.data.jpa.repository.QueryHints({@javax.persistence.QueryHint(name = "org.hibernate.cacheable", value = "true")})
@EntityGraph(attributePaths = { "venue.city", "lineup.artist", "ticketLinks" }, type = EntityGraphType.FETCH)
Optional<Event> findEventPageViewGraphById(long id);
和实体的一部分:
@Entity
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class Event {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
protected Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "venue_id")
private Venue venue;
@OneToMany(mappedBy = "event", cascade = CascadeType.ALL, orphanRemoval = true)
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
@OrderBy("orderId")
private Set<TicketLink> ticketLinks = new LinkedHashSet<>();
@OneToMany(mappedBy = "event", cascade = CascadeType.ALL, orphanRemoval = true)
@OrderBy("orderId")
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
private Set<ArtistEvent> lineup = new LinkedHashSet<>();
}
谢谢你的回答。我通过使用静态方法Hibernate.initialize()初始化实体解决了这个问题,如下所述https://vladmihalcea.com/initialize-lazy-proxies-collections-jpa-hibernate/
@Transactional(readOnly = true)
public Optional<Event> loadEventPageViewGraph(long id) {
Optional<Event> eventO = eventRepository.findEventPageViewGraphById(id);
if(eventO.isPresent()) {
Hibernate.initialize(eventO.get());
Hibernate.initialize(eventO.get().getVenue().getCity());
for (ArtistEvent artistEvent: eventO.get().getLineup()) {
Hibernate.initialize(artistEvent.getArtist());
}
Hibernate.initialize(eventO.get().getTicketLinks());
return eventO;
} else {
return Optional.empty();
}
}
不过,我同意一般来说,最好使用DTO/预测。但是,对于DTO,获取包含关联集合(@OneToMany属性)的投影时存在问题,如下所述https://vladmihalcea.com/one-to-many-dto-projection-hibernate/. 特别是在我们不想选择所有实体属性的情况下。我发现Blaze持久性实体视图有一个很好的解决方案https://persistence.blazebit.com/documentation/1.6/entity-view/manual/en_US/#subset-基本集合映射。我去看看。
这是一个众所周知的问题。在构造“仅代理”时,Hibernate不会检查二级缓存中的关联。您需要访问对象来初始化它们,然后触发二级缓存命中。
我建议您改用DTO方法。我认为这是Blaze持久性实体视图的完美用例。
我创建了这个库,以便在JPA模型和自定义接口或抽象类定义的模型之间进行简单的映射,类似于类固醇上的Spring数据投影。其思想是以您喜欢的方式定义目标结构(域模型),并通过JPQL表达式将属性(getter)映射到实体模型。
在Blaze持久性实体视图中,您的用例的DTO模型可能如下所示:
@EntityView(Event.class)
public interface EventDto {
@IdMapping
Long getId();
VenueDto getVenue();
@MappingIndex("orderId")
List<TicketLinkDto> getTicketLinks();
@MappingIndex("orderId")
List<ArtistEventDto> getLineup();
@EntityView(Venue.class)
interface VenueDto {
@IdMapping
Long getId();
CityDto getCity();
}
@EntityView(City.class)
interface CityDto {
@IdMapping
Long getId();
String getName();
}
@EntityView(TicketLink.class)
interface TicketLinkDto {
@IdMapping
Long getId();
String getName();
}
@EntityView(ArtistEvent.class)
interface ArtistEventDto {
@IdMapping
Long getId();
ArtistDto getArtist();
}
@EntityView(Artist.class)
interface ArtistDto {
@IdMapping
Long getId();
String getName();
}
}
查询是将实体视图应用于查询的问题,最简单的就是按id进行查询。
EventDto a=entityViewManager.find(entityManager,EventDto.class,id)
Spring数据集成允许您像使用Spring数据投影一样使用它:https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-数据特征
Optional<EventDto> findEventPageViewGraphById(long id);
问题内容: 我想在hibernate项目中使用二级缓存,但是我只对hibernate二级缓存了解一点,任何人都可以解释我应该如何在代码中使用它以及需要什么配置和.jar文件吗?我将这些设置设置为我的hibernate.cfg.xml文件 并添加这些jar文件, 我想知道我是否需要更改其他配置? 我怎么知道我的项目使用二级缓存? 如果只是设置此设置,hibernate将自动使用此设置,否则我必须在我
问题内容: 我正在开发hibernate+ ehcache程序。 ehcache.xml 我在bean.xml中提到了ehcache 我在dao类中的调用方法是 输出为: 但是它在数据库中命中了两次。我在代码中没有发现任何错误。请向我建议为什么它在数据库中命中了两次。 问题答案: 我已经解决了我的问题。我需要添加 在域类中。
我有一个关于内存系统遵循的策略的基本问题。 考虑一个具有私有L1和L2缓存的核心。在L2缓存之后,我们有一个相干流量运行的总线。现在,如果从L2高速缓存中逐出地址(X)的高速缓存行,是否有必要从L1高速缓存中逐出该地址?? 逐出的原因可能是它有助于保持一致性协议的不变[如果l2中的一行显示无效,则此核心不包含此地址]。
尝试使用infinispan作为Hibernate的二级缓存,但总是给我以下错误 org.infinispan.jmx.JMX MBean实例类型=CacheManager, name="DefaultCacheManager"已经在'org.infinispan'JMX域下注册。如果您想允许多个配置了相同JMX域的实例,请在org.infinispan.jmx.JmxUtil.buildJmxD
当你使用本地(在内存中)缓存时,服务器可以缓存一些信息并快速地检索它,但是其他服务器不能访问这个缓存数据,他们需要到数据库中查询同样的信息。 如果你喜欢使用分布式缓存让其他服务器访问缓存的数据,由于它有一些序列化/反序列化和网络延迟开销,则需要注意:在某些情况下,它可能会降低性能。 缓存需要处理的另一个问题:缓存失效。 There are only two hard things in Compu
在我的查询(查找)get cached会话关闭后,在一个新会话中,在我通过随机写入Sql查询更改数据库后,hibernate正在逐出所有内容,我如何才能阻止这种情况发生?我正在研究为那些很少改变的事情制定政策。 ecache。xml SpringHibernate配置