JPA嵌套对象的LAZY FETCH仅返回第一个对象。

huangapple go评论74阅读模式
英文:

JPA nested object LAZY FETCH returns only first object

问题

我有以下内容。

@Data
@Getter
@Setter
@Accessors(fluent = false, chain = true)
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
@MappedSuperclass
@Slf4j
class Base {
  private Timestamp createdTime;
  private Timestamp modifiedTime;
  private String createdBy;
  private String modifiedBy;
  private Boolean deleted = false;
}

@Getter
@Setter
@Builder
@EqualsAndHashCode
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "account")
@SQLDelete(sql = "UPDATE account SET deleted = true WHERE account_id = ?")
@Where(clause = "deleted=false")
class Account {
  @Id
  @EqualsAndHashCode.Include()
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long accountId;

  @Builder.Default
  @OneToMany(fetch = FetchType.LAZY, mappedBy = "account", cascade = {CascadeType.ALL})
  private Set<Collab> collaborators = new HashSet<>(0);
  private String objId;
}

class Collab {
  @Id
  @EqualsAndHashCode.Include()
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long collabId;
  private String email;
  private String role;
  @JsonBackReference
  @JoinColumn(name = "accountId")
  @ManyToOne(fetch = FetchType.EAGER)
  private Account account;
}

public interface AccountRepo {
  Optional<Account> findByObjId(String objId);
}

尽管在数据库中单个帐户有多个合作伙伴,但当我检查AccountRepo.findByObjId(或findAll)方法的响应时,任何帐户对象中的collaborators只有1个元素。我漏掉了什么? PS: @EqualsAndHashCode.Include() 是来自 Lombok。

英文:

I have the following.

@Data
@Getter
@Setter
@Accessors(fluent = false, chain = true)
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
@MappedSuperclass
@Slf4j
class Base {
private Timestamp createdTime;
private Timestamp modifiedTime;
private String createdBy;
private String modifiedBy;
private Boolean deleted = false;
}
@Getter
@Setter
@Builder
@EqualsAndHashCode
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = &quot;account&quot;)
@SQLDelete(sql = &quot;UPDATE account SET deleted = true WHERE account_id = ?&quot;)
@Where(clause = &quot;deleted=false&quot;)
class Account {
@Id
@EqualsAndHashCode.Include()
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long accountId;
@Builder.Default
@OneToMany(fetch = FetchType.LAZY, mappedBy = &quot;account&quot;, cascade = {CascadeType.ALL})
private Set&lt;Collab&gt; collaborators = new HashSet&lt;&gt;(0);
private String objId;
}
class Collab {
@Id
@EqualsAndHashCode.Include()
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long collabId;
private String email;
private String role;
@JsonBackReference
@JoinColumn(name = &quot;accountId&quot;)
@ManyToOne(fetch = FetchType.EAGER)
private Account account;
}
public interface AccountRepo {
Optional&lt;Account&gt; findByObjId(String objId);
}

Even though there are multiple collab for a single account in the DB.
When I inspect the response of AccountRepo.findByObjId (or findAll) method, only 1 element is inside collaborators for any account object. What am I missing?

PS: @EqualsAndHashCode.Include() is from lombok

答案1

得分: 2

当您检查AccountRepo.findByObjId或findAll的响应时,您可能只会看到协作者集合中的一个元素,因为惰性加载机制会按需加载相关的Collab实体。如果在检索Account对象后访问协作者集合,它应该会触发从数据库加载关联的Collab实体。

尝试通过实现一个类似这样的协作者的getter方法:

public Set<Collab> getCollaborators() {
  return collaborators;
}

之后,您可以像这样访问协作者:

Optional<Account> accountOptional = accountRepo.findByObjId(objId);
if (accountOptional.isPresent()) {
  Account account = accountOptional.get();
  Set<Collab> collaborators = account.getCollaborators(); // 加载协作者
}
英文:

When you inspect the response of AccountRepo.findByObjId or findAll, you may only see one element inside the collaborators set because the lazy-loading mechanism loads the related Collab entities on-demand. If you access the collaborators set after retrieving an Account object, it should trigger the loading of the associated Collab entities from the database.

Try by implementing a getter method for collaborators like this

public Set&lt;Collab&gt; getCollaborators() {
return collaborators;
}

after that you can access the collaborators like this

Optional&lt;Account&gt; accountOptional = accountRepo.findByObjId(objId);
if (accountOptional.isPresent()) {
Account account = accountOptional.get();
Set&lt;Collab&gt; collaborators = account.getCollaborators(); // Load collaborators
}

答案2

得分: 0

在BaseClass中,我有以下的注解,这导致了HashCode/Equals的问题,最终影响了Set中的项目。

@EqualsAndHashCode(onlyExplicitlyIncluded = true)

英文:

Turns our I had the following annotation in the BaseClass which was causing the issue with Hashcode/Equals and eventually the items in the Set.

@EqualsAndHashCode(onlyExplicitlyIncluded = true)

huangapple
  • 本文由 发表于 2023年7月3日 14:34:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/76602339.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定