I have seen various post describing that JPA EntityGraph allows to choose the graph at run time. And I am not entirely clear what this refers to.
我见过各种描述JPA EntityGraph允许在运行时选择图形的帖子。我也不完全清楚这指的是什么。
Out of good faith and respect I would like to take this helpful article for reference: https://www.baeldung.com/jpa-entity-graph. (Most of JPA users might have gone through it already.)
出于诚意和尊重,我想将这篇有用的文章作为参考:https://www.baeldung.com/jpa-entity-graph.(大多数JPA用户可能已经经历过了。)
The article quotes -
这篇文章引用了-
EntityGraph allows grouping the related persistence fields which we
want to retrieve and lets us choose the graph type at runtime.
and again solidifies above statement in conclusion section.
并在结语部分再次印证了上述论述。
In this article, we've explored using the JPA Entity Graph to
dynamically fetch an Entity and its associations.
The decision is made at runtime in which we choose to load or not the
related association.
As we see in the article (5.1) - EntityGraphs are defined as below using Annotations-
5.1. Defining an Entity Graph with Annotations
正如我们在文章(5.1)中所看到的--使用注释-5.1定义实体图如下所示。定义带注释的实体图
@NamedEntityGraph(
name = "post-entity-graph",
attributeNodes = {
@NamedAttributeNode("subject"),
@NamedAttributeNode("user"),
@NamedAttributeNode("comments"),
}
)
@Entity
public class Post {
@OneToMany(mappedBy = "post")
private List<Comment> comments = new ArrayList<>();
//...
}
The @NameEntityGraph annotation is defined at compile time and I don't see anything runtime or dynamic here.
@NameEntityGraph注释是在编译时定义的,我在这里看不到任何运行时或动态内容。
But in 5.2 - entity graphs are defined using api or programmatically -
5.2. Defining an Entity Graph with the JPA API
但在5.2中-实体图是使用API或以编程方式定义的-5.2。使用JPA API定义实体图
EntityGraph<Post> entityGraph = entityManager.createEntityGraph(Post.class);
entityGraph.addAttributeNodes("subject");
entityGraph.addAttributeNodes("user");
In 5.2 approach, I see nodes can be chosen dynamically using some logic. So is this approach is what is refered to "dynamically fetch" and "runtime based".
Or am i missing something and do i have more to understand.
在5.2方法中,我看到可以使用一些逻辑动态选择节点。这种方法被称为“动态获取”和“基于运行时”。还是我错过了什么,我还有更多要理解的东西吗?
Further the approaches given in 6. Using the Entity Graph
ex:
进一步介绍6.使用实体图EX中给出的方法:
EntityGraph entityGraph = entityManager.getEntityGraph("post-entity-graph");
Map<String, Object> properties = new HashMap<>();
properties.put("javax.persistence.fetchgraph", entityGraph);
Post post = entityManager.find(Post.class, id, properties);
are all programmatic and so can be changed during runtime i.e they can be said as dynamic.
But one approach missed in above article, but mentioned here - https://www.baeldung.com/spring-data-jpa-named-entity-graphs, as below, does not seem to fit in to dynamic criteria.
都是程序化的,因此可以在运行时更改,也就是说,它们可以说是动态的。但是有一种方法在上面的文章中遗漏了,但在这里提到了--https://www.baeldung.com/spring-data-jpa-named-entity-graphs,,如下所示,似乎不符合动态标准。
public interface ItemRepository extends JpaRepository<Item, Long> {
@EntityGraph(value = "Item.characteristics")
Item findByName(String name);
}
So does the dynamic approach just refer to 5.2 style or it implies even 5.1 style too.
那么,动态方法是仅指5.2样式,还是也隐含5.1样式。
更多回答
You can't use dynamic entity graphs with spring-data, because JpaRepository
doesn't have methods to pass entity graphs like
您不能将动态实体图与Spring数据一起使用,因为JpaRepository没有传递实体图的方法,比如
Optional<T> findById(ID id, EntityGraph entityGraph);
Using custom JPA repository
使用自定义JPA存储库
You can use raw JPA for that, by creating a custom repository and using entity graphs with EntityManager
.
为此,您可以使用原始JPA,方法是创建自定义存储库并将实体图与EntityManager一起使用。
Using spring-data-jpa-entity-graph
使用Spring-data-jpa-entity-graph
There is a more convenient approach by using library
spring-data-jpa-entity-graph.
还有一种更方便的方法,那就是使用库Spring-data-jpa-Entity-graph。
It allows to use JPA repository methods like findById()
or findByName()
with dynamic entity graphs.
它允许对动态实体图使用像findById()或findByName()这样的JPA存储库方法。
I prefer to use it with this helper class
我更喜欢在这个Helper类中使用它
public abstract class EntityGraphBuilder<T> {
private List<String> result = new ArrayList<>();
protected T self;
public T add(String path) {
result.add(path);
return self;
}
public DynamicEntityGraph build() {
return new DynamicEntityGraph(EntityGraphType.FETCH, result);
}
}
Each entity has its own GraphBuilder
每个实体都有自己的GraphBuilder
@Entity
public class OrderEntity {
@Id
private Long id;
@Column
private name;
@ManyToOne(fetch = FetchType.LAZY)
private OrderRequestEntity orderRequest;
@ManyToOne(fetch = FetchType.LAZY)
private ProviderEntity provider;
public static GraphBuilder graph() {
return new GraphBuilder();
}
public static class GraphBuilder extends EntityGraphBuilder<GraphBuilder> {
private GraphBuilder() {
self = this;
}
public GraphBuilder orderRequest() {
return add("orderRequest");
}
public GraphBuilder provider() {
return add("provider");
}
}
}
Repository uses EntityGraphJpaRepository
from spring-data-jpa-entity-graph
library
存储库使用Spring-Data-JPA-Entity-graph库中的EntityGraphJpaRepository
@Repository
public interface OrdersRepository extends EntityGraphJpaRepository<OrderEntity, Long> {
OrderEntity findByName(String name, EntityGraph entityGraph);
}
You can use derived query methods like findByName()
with dynamic entity graphs too.
您也可以对动态实体图使用像findByName()这样的派生查询方法。
Example of using findById()
method, the same approach can be applied to findByName()
使用findById()方法的示例,可以将相同的方法应用于findByName()
OrdersRepository ordersRepository;
Long orderId = 1L;
OrderEntity order = ordersRepository.findById(
orderId,
OrderEntity.graph().orderRequest().provider().build()
).orElseThrow(
() -> new ServiceException("Can't find orderId=" + orderId)
);
In the Baeldung article, Section 5 is only about various ways to define a graph with not much emphasis on the dynamic/non-dynamic nature of the definition itself.
在Baeldung的文章中,第5节只是关于定义图的各种方法,而不是太多地强调定义本身的动态/非动态性质。
In Section 5.1 the definition of the graph is static but this section is only about demonstrating how to define a graph which then will be used in typical cases when building the graph dynamically is not really necessary. This section shows an alternative to the older way of building HQL / JPA-QL queries with JOIN FETCH sections.
在5.1节中,图的定义是静态的,但这一节只是演示如何定义图,然后在没有真正需要动态构建图的典型情况下使用它。本节展示了使用联接FETCH部分构建HQL/JPA-QL查询的旧方法的替代方法。
@NamedEntityGraph(
name = "post-entity-graph",
attributeNodes = {
@NamedAttributeNode("subject"),
@NamedAttributeNode("user"),
@NamedAttributeNode("comments"),
}
)
@Entity
public class Post {
@OneToMany(mappedBy = "post")
private List<Comment> comments = new ArrayList<>();
//...
}
Then, Section 6 tells you how to use the entity graphs defined earlier in various ways.
然后,第6节告诉您如何以各种方式使用前面定义的实体图。
// Getting the "statically" defined graph (from annotation)
EntityGraph entityGraph = entityManager.getEntityGraph("post-entity-graph");
// Then using the graph
Map<String, Object> properties = new HashMap<>();
properties.put("javax.persistence.fetchgraph", entityGraph);
Post post = entityManager.find(Post.class, id, properties);
Naturally, you can swap this first line to the fully dynamically built graph demonstrated in Section 5.2:
自然,您可以将这第一行替换为5.2节中演示的完全动态构建的图形:
// Building the graph dynamically
EntityGraph<Post> entityGraph = entityManager.createEntityGraph(Post.class);
entityGraph.addAttributeNodes("subject");
entityGraph.addAttributeNodes("user");
// Then using the graph
Map<String, Object> properties = new HashMap<>();
properties.put("javax.persistence.fetchgraph", entityGraph);
Post post = entityManager.find(Post.class, id, properties);
In both cases you supply an EntityGraph object to the query.
在这两种情况下,都需要为查询提供一个EntityGraph对象。
With spring-data from jpa-buddy blog:
使用来自JPA伙伴博客的春季数据:
"Fortunately, this framework allows adding any arbitrary string between the repository method's find and By parts. So, in the repository, there will be two methods"
@EntityGraph(attributePaths = { "pets.type", "pets.visits" })
Optional<Owner> findById(Integer id);
@EntityGraph(attributePaths = { "pets "})
Optional<Owner> findOwnerWithPetsById(Integer id);
更多回答
very much appreciate for bringing in new libarary ++1
非常感谢引进了新的图书馆++1
@samshers Always ready to help. You can try my approach, it is production ready.
@Samshers总是乐于助人。你可以试试我的方法,它已经准备好生产了。
@RédaHousniAlaoui Thank you for a good library. We are havy using it in production. It is cool that you have updated the library to the last Spring version. I appreciate it very much and going to use the last version. I don't like code generation. Also I don't like this ____
in the fluent API. I am okay to have a lot of the code on the low level (model, utils etc.) to have good code quality on the user (developer) level.
@RédaHousniAlaoui感谢你提供了一个好的图书馆。我们正在生产中使用它。您已经将库更新到了最新的Spring版本,这很酷。我非常感谢,我将使用最后一个版本。我不喜欢代码生成。我也不喜欢这个流畅的API中的_。我可以有很多低级别的代码(模型,实用程序等)。在用户(开发人员)层面上有良好的代码质量。
Well, I could allow customization of ____
. > I don't like code generation I distinguish 2 types of code generation. The one that is provided by Maven/Gradle plugin that I also dislike. But this one is provided by an Annotation Processor (SPI provided by the JDK). It is triggered by a simple call to javac
. Anyway, happy you have been using the lib in production :)
嗯,我可以允许定制_。>我不喜欢代码生成我区分了两种类型的代码生成。Maven/Gradle插件提供的那个我也不喜欢。但是这个是由注释处理器(由JDK提供的SPI)提供的。它是由对javac的简单调用触发的。无论如何,很高兴您一直在生产中使用lib:)
In both cases you supply an EntityGraph object to the query.
. Gr8 answer. ++1. You said, "This section shows an alternative to the older way of building HQL / JPA-QL queries with JOIN FETCH sections."
so this vs/or NamedEntityGraph. Right?
在这两种情况下,您都向查询提供了EntityGraph对象。G8回答。++1.您说过,“这一节展示了一种使用JOIN FETCH段构建HQL/JPA-QL查询的旧方法的替代方法。”这是VS/或NamedEntiyGraph。对吗?
"so this vs/or NamedEntityGraph. Right? " - Yes
“所以这是VS/或NamedEntiyGraph,对吗?”-是的。
我是一名优秀的程序员,十分优秀!