gpt4 book ai didi

java - JPA 检索所有引用的关系(ManyToMany - ManyToOne - OneToMany)

转载 作者:行者123 更新时间:2023-11-30 06:16:46 25 4
gpt4 key购买 nike

正在开发这个“twitter”应用程序,用户可以在其中发布帖子@OneToMany并且可以拥有关注者@ManyToMany

在检索用户时,也会检索其所有帖子和关注者。

这都是正确的,但它还检索每个帖子(即用户本身)的每个“海报”以及每个关注者的所有帖子和关注者。

我不知道如何将此限制为用户本身。

用户

@Entity
@Table(name = "User")
@NamedQueries({
@NamedQuery(name = "User.findAll", query = "SELECT u FROM User u"),
@NamedQuery(
name = "User.auth",
query = "SELECT u FROM User u WHERE u.username = :username AND u.password = :password"
)
})
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(unique = true, nullable = false)
private String username;

@Column(nullable = false)
private String password;

@ManyToMany
@OneToMany(mappedBy = "poster", cascade = CascadeType.ALL)
private List<Post> posts = new ArrayList<>();

@JoinTable(name = "Followers",
joinColumns = {
@JoinColumn(name = "USER_ID", referencedColumnName = "ID")
},
inverseJoinColumns = {
@JoinColumn(name = "FOLLOWER_ID", referencedColumnName = "ID")
}
)
private List<User> followers = new ArrayList<>();
.... constructor, getters and setters

发布

@Entity
@Table(name = "Post")
public class Post {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String content;

@ManyToOne
private User poster;
.... constructor, getters and setters

我得到的结果与我想要的结果

{
"id": 1,
"username": "jim",
"posts": [
{
"id": 1,
"content": "Post 1 by jim",
"poster": {
// ^ this is the user itself (I don't need this one)
"id": 1,
"username": "jim",
"posts": [
// keeps recurse
]
}
}
],
"followers": [
{
"id": 2,
"username": "follower1",
"posts": [
{
"id": 4,
"content": "Post 2 by follower 1",
"poster": {
// ^ this is the follower itself (I don't need this one)
"id": 2,
"username": "follower1",
"posts": [
// Same issue
]
}
}
],
"followers": [], // <-- I don't need this one either
}
]
}

很明显,获取一个用户填充会不断获取其所有递归关系。

这是设计师的错误还是可以忽略/限制?

注意:我使用 Gson 将对象序列化为 JSON 格式

更新

尝试使用:

@ManyToOne(fetch = FetchType.LAZY)
private User poster;

它有效,但仍然在 JSON 中获得以下额外的 Prop ,因此不确定这是否是一个简洁的解决方案:

"_persistence_poster_vh": {
"sourceAttributeName": "poster",
"isInstantiated": false,
"row": {
"Post.ID": 3,
"Post.CONTENT": "Post 3 by jim",
"Post.DATETIME": "2018-01-22",
"Post.POSTER_ID": 1
},
"isCoordinatedWithProperty": false
}

还有

  @ManyToMany(fetch = FetchType.LAZY)
@JoinTable(
...
)
private List<User> followers = new ArrayList<>();

它仍然返回所有关注者(我想要的!)我只是不想要followers.followers和followers.posts..

最佳答案

最佳猜测:在您尝试取消引用这些对象之前,它实际上并没有获取这些对象。

默认情况下,JPA 将急切获取 @OneToOne 和 @OneToMany 关系,但不会获取 @ManyToOne 或 @ManyToMany。发生的情况是,当您引用这些字段时,它将去获取列表的实际内容。

你怎么知道这种情况正在发生?使用 getFollowers().getClass() 检查列表的类您看到的不会是 LinkedList 或 ArrayList,而是 JPA 提供者提供的一个类,名称中可能带有“Lazy”。当您在列表上调用 Size 或 Get 时,它将执行获取。

您也可以将 OneToOne 和 OneToMany 关系设置为惰性关系,并使用 EntityGraphs 来确定您想要急切获取哪些实体。 JPA 有很多这样的陷阱。

我已经看到提到过 GSON,只是一个警告:它不会意识到延迟加载列表,所以你必须告诉它避免使用你不希望它遵循的属性。

通常使用 JSON 编码(marshal)处理时,您会希望它忽略父对象,因此在 Post 中,应忽略 User。另外,到相同类型的链接通常应该被忽略(关注者)或者专门映射,这样它就不会编码整个对象,而只生成用户名数组。您可以告诉它忽略实际的关注者字段,并让它编码一个返回用户名数组的 getter 来实现此目的。

关于java - JPA 检索所有引用的关系(ManyToMany - ManyToOne - OneToMany),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49027819/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com