import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Set;
@Entity
@Table(name = "users")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
@Id
@GeneratedValue
private Long id;
@Column(unique = true, nullable = false)
private String username;
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = "user_subscriptions",
joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"),
inverseJoinColumns = @JoinColumn(name = "subscription_id", referencedColumnName = "id"))
private Set<Subscription> subscriptions;
}
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Set;
@Entity
@Table(name = "subscriptions")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Subscription {
@Id
@GeneratedValue
private Long id;
@Column(unique = true, nullable = false)
private String name;
@OneToMany(mappedBy = "subscription")
private Set<Notification> notifications;
@ManyToMany(mappedBy = "subscriptions")
private Set<User> users;
}
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Entity
@Table(name = "notifications")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Notification {
@Id
@GeneratedValue
private Long id;
@Column(nullable = false)
private String title;
@Column(nullable = false)
private String message;
@Column(name = "is_read", nullable = false)
private boolean isRead;
@ManyToOne
@JoinColumn(name = "subscription_id")
private Subscription subscription;
}
字符串
我已经创建了这3个实体。用户和订阅有ManyToMany关系。当我保存用户时,它工作正常,在数据库中我可以看到用户的订阅。
的数据
当我调用方法findById来获取用户时,我得到订阅设置为空。我如何修复它?我使用Sping Boot v3.1.3,Java v17和PostgreSQL v14.3
1条答案
按热度按时间2eafrhcq1#
有几个问题本可以在这里解决,但没有。所有的问题我都注意到了。
Eager
. Hibernate many to many - fetch method eager vs lazy的建议阅读Entities
中使用了Set
。考虑到这一点,但当JPA将List
转换为Set
时,它可能会导致问题。如果可以避免,最好不要让JPA做任何额外的事情。Notification
应该跟踪到特定User
的通知,那么您的数据库模式就不能实现这一点。那么,让我们开始吧。如果我创建一个示例并执行
findById
,我会得到以下SQL。字符串
这就是你想要的吗,希望不是,我们来解决
型
请注意,
@Data
已经被删除,并被@Getter
和@Setter
替换。您也可以通过使用List
而不是Set
来修复它,但我将把它作为读者找出原因的练习。现在我的SQL只是原始的第一行。型
请注意,您已经联接了订阅表
型
但是你没有将它包含在
User
中使用。型
我们来解决这个问题。
型
这给了我
型
最后,让我们摆脱
Eager
,因为它可以说是一个JPA-ANTIPATTERN. JPA and Hibernate FetchType EAGER is a code smell。型
现在我们有了一个合理的
Repository
,其中findById
只给我们 * 请求的实体型
方法
findByIdWithSubscriptions
给出了联合订阅并将它们包含在结果中。