spring data jpa
学习 spring data jpa 之前其实应该先了解一下 JPA(Java Persistence API)规范
JPA 规范出现的目的
JPA 是在 JDK 5.0 后提出的 Java 持久化规范(JSR 338)。JPA 规范本身是为了整合市面上已有的 ORM 框架,结束 Hibernate、EclipseLink、JDO 等 ORM 框架各自为战的割裂局面,简化 Java 持久层开发。
JPA规范 解决了什么问题
JPA 是一个持久化规范,没有提供具体持久化实现,那谁来提供实现呢? 就是类似 spring data jpa 等等这些orm 框架实现的。
spring data jps 是什么
Spring Data JPA 是符合 JPA 规范的一个 Repository 层的实现
Spring Data JPA 帮助我们抹平了各个 ORM 框架的差异,从而可以让我们的上层业务无缝地切换 ORM 实现框架。
核心组成
JPA 有三个核心部分:
- ORM 映射元数据。
- 操作实体对象 API。
- 面向对象的查询语言(JPQL)。
jpa 常用注解说明
@EntityGraph
jpa2.1 之后出现了一个新的用法
Entity Graph
主要解决的问题
在JPA 2.0之前,要加载实体关联,我们通常使用FetchType.LAZY和FetchType.EAGER作为获取策略。 这指示JPA提供程序额外获取或不获取相关的关联。 不幸的是,此元配置是静态的,不允许在运行时在这两种策略之间切换。
主要目标是在加载实体的相关关联和基本字段时提高运行时性能。
如何使用
定义一个实体
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String email;
//...
}
@Entity
public class Post {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String subject;
@OneToMany(mappedBy = "post")
private List<Comment> comments = new ArrayList<>();
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn
private User user;
//...
}
@Entity
public class Comment {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String reply;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn
private Post post;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn
private User user;
//...
}
拓扑图类似这样
Post -> user:User
-> comments:List<Comment>
comments[0]:Comment -> user:User
comments[1]:Comment -> user:User
使用
@NamedEntityGraph 注解允许指定要加载实体和相关关联时要包括的属性。
现在让我们定义一个更复杂的EntityGraph ,在此我们还希望加载与comments 相关的用户。
@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<>();
//...
}
为此,我们将使用@NamedAttributeNode子图属性。 这允许引用通过@NamedSubgraph注解定义的命名子图:
@NamedEntityGraph(
name = "post-entity-graph-with-comment-users",
attributeNodes = {
@NamedAttributeNode("subject"),
@NamedAttributeNode("user"),
@NamedAttributeNode(value = "comments", subgraph = "comments-subgraph"),
},
subgraphs = {
@NamedSubgraph(
name = "comments-subgraph",
attributeNodes = {
@NamedAttributeNode("user")
}
)
}
)
@Entity
public class Post {
@OneToMany(mappedBy = "post")
private List<Comment> comments = new ArrayList<>();
//...
}
attributePaths 属性说明
attributePaths属性来设置,效果是一样的。只不过如果有多个属性都要一起查出来,而且有多个方法都用到了,使用@EntityGraph的attributePaths属性修改起来就不是那么方便了,结合自己的情况进行选择。
对于数据量比较小,我们可以重写JpaRepository的findAll方法,并添加@EntityGraph注解,抓取子节点,如下所示:
@Override
@EntityGraph(attributePaths = "children")
List<Category> findAll();
总结:
在使用了 实体关系图 之后可以在运行时决定加载或者是不加载,相关的关联。
参考文档
问题处理 解决N+1 问题
链接: https://www.codeprj.com/blog/958c721.html.
https://www.cnblogs.com/caofanqi/p/11902159.html