当前位置: 首页 > 知识库问答 >
问题:

Spring数据 JPA - 使用@EntityGraph导致“指定的实体图不适用于实体”警告

聂和宜
2023-03-14

我将我的应用程序从spring boot 2.2.5升级到2.3.3,并且我正在使用spring data JPA starter和5.4.20.Final板载。我的实体在编译时得到了增强。

现在,当我使用@EntityGraph注释与属性路径属性覆盖findAll来自JpaRepository的方法时,我收到了这个警告:

2020-08-19 12:13:41.121  WARN 9348 --- [nio-8060-exec-3] [] [] o.h.engine.internal.TwoPhaseLoad         : Entity graph specified is not applicable to the entity [DictionaryLang(id=1601, name=null, lang=null)]. Ignored.
2020-08-19 12:13:41.483  WARN 9348 --- [nio-8060-exec-3] [] [] o.h.engine.internal.TwoPhaseLoad         : Entity graph specified is not applicable to the entity [DictionaryValueLang(id=3051, lang=null, name=null)]. Ignored.

即使这个警告-图是正确获取-我只能看到一个SQL查询日志和应用程序的行为之前的更新。

这是我的存储库代码:

public interface DictionaryRepository extends JpaRepository<Dictionary, Long>, QuerydslPredicateExecutor<Dictionary> {

    @EntityGraph(attributePaths = {"langs", "values", "values.langs"})
    @Override
    Page<Dictionary> findAll(Predicate predicate, Pageable pageable);
}

这是我的实体:

@Entity
@Table(name = "DICTIONARIES")
public class Dictionary {

    @Id
    @SequenceGenerator(name = "SEQ_DICTIONARIES", sequenceName = "SEQ_DICTIONARIES")
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_DICTIONARIES")
    private Long id;

    @OrderBy("ordinal ASC")
    @OneToMany(mappedBy = "dictionary", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
    private List<DictionaryValue> values;

    @OneToMany(mappedBy = "dictionary", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
    private Set<DictionaryLang> langs;

}


@Entity
@Table(name = "DICTIONARY_LANGS")
public class DictionaryLang extends BaseEntity {

    @Id
    @SequenceGenerator(name = "SEQ_DICTIONARY_LANGS", sequenceName = "SEQ_DICTIONARY_LANGS")
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_DICTIONARY_LANGS")
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY)
    @LazyToOne(LazyToOneOption.PROXY)
    @JoinColumn(name = "DICTIONARY_ID")
    private Dictionary dictionary;

}

如何解决此警告?我可以看到这个警告发生在hibernate的<code>TwoPhaseLoad</code>类的那些行中:

GraphImplementor fetchGraphContext = session.getFetchGraphLoadContext();
if ( fetchGraphContext != null && !fetchGraphContext.appliesTo( entity.getClass() ) ) {
    LOG.warnf( "Entity graph specified is not applicable to the entity [%s]. Ignored.", entity);
    fetchGraphContext = null;
    session.setFetchGraphLoadContext( null );
}

共有1个答案

彭博厚
2023-03-14

这是因为在Spring 2.3.3中将hibernate更新到5.4.20。

如果你降级Hibernatetp 5.4.18这个问题将消失,升级到5.4.21没有帮助。

在我的例子中,hibernate不只是添加了一个警告消息,它实际上忽略了@EntityGraph(attributePaths = {...})注释,并根据映射执行查询生成,在我的例子中,这会导致N-1个问题和数千个查询。还有,EntityGraph。LOAD并不能解决问题,因为在这种情况下,hibernate将根据mappings fetch类型加载@EntityGraph中没有提到的所有映射,如果您查找大的集合,这可能会增加很多查询。

查看有关EntityGraphType的详细信息

o降级Hibernate,您可以使用

 implementation ("org.springframework.boot:spring-boot-starter-data-jpa") {
     // to remove fibernate that came with new spring
     exclude group: "org.hibernate", module: "hibernate-core" 
 }
 // to add old hibernate 
 implementation "org.hibernate:hibernate-core:5.4.18.Final"

这是hibernate中的一个相关问题https://hibernate.atlassian.net/browse/HHH-14124它说受影响的版本4.5.19和修复版本是4.5.20。但是,我仍然在spring 2.3.3(hibernate 4.5.20)中遇到错误

更新:以下是针对此错误发布的问题。它已经固定:https://hibernate.atlassian.net/browse/HHH-14212

 类似资料:
  • 当应用程序基于Spring Boot时,不考虑定义的实体图。相反,在JUnit测试期间,一切正常。 领域非常简单:书籍及其类别(多对多关系) 图书类: 类别类: 带有使用创建的实体图的方法的JPA存储库: REST控制器中的用法: 启动Spring Boot(mvn Spring Boot:run)并导航到http://localhost:8080/books书籍会被显示,但它们有各自的类别(由于

  • 我用Spring和Hibernate开发了我的Java应用程序,我有两个实体。 我创建我的服务类别,以获得Hibernate的结果 当我调试时,我在这一行中得到这个错误: 104165[http-bio-8080-exec-3]警告组织。冬眠util。JDBCExceptionReporter-SQL错误:904,SQLState:42000 104166[http-bio-8080-exec-3

  • 我在各自的字段中使用了@CreatedBy、@CreatedDate、@LastModifiedBy和@LastModifiedDate注释。通过使用@MappdSuperclass、@EntityListeners,我能够持久化上面的列。 但这不适用于以下情况: 审计员我mpl.java JpaAuditConfiguration。Java语言 在这种情况下,实体B填充了审计列。但实体A并非如此

  • 这个问题几乎说明了一切。使用JPARepository,我如何更新一个实体? JPARepository只有一个save方法,它并不告诉我它实际上是create还是update。例如,我向数据库用户插入一个简单的对象,它有三个字段:、和: 然后我只需调用,此时它实际上是对数据库的插入: 到目前为止还不错。现在我想更新这个用户,比如说改变他的年龄。为此,我可以使用查询,无论是QueryDSL还是Na

  • 另外,当切换到一个新的视图(spring controller中的新调用)时,来自上一个视图的事务将已经关闭,我必须进行新的调用,以与用户有不同的数据。我不明白如果您不在相同的事务服务方法中,fetch lazy有什么帮助,除非我没有遗漏什么。 例如,如果我需要“orderwiew.html”中的订单数据,惰性加载订单是没有帮助的,我必须对相同的用户数据和额外的订单数据进行另一次完整调用

  • 我有几个实体,并使用Spring Data JPA存储库与规范查询我的数据库。因此,我创建了一个泛型类< code>SpecBuilder来基于查询描述(< code>MyQueryDescriptor)构建我的查询。 我的存储库: 和 现在有三件事我不太确定:< br> 1) 使用泛型SpecBuilder是一个干净的设计吗? 2) 有没有办法避免为每个实体编写这些存储库接口?假设一个通用存储库