【发布时间】:2022-01-23 21:55:22
【问题描述】:
在我当前的项目中,我使用 JPA 和 Hibernate 来处理我的数据库层。
我的一个实体与其自身具有多对多关系,使用 @ManyToMany 和 @JoinTable 注释非常有效。
我的问题是我被要求为实体添加分页支持。我在网上搜索了一个解决方案,但我发现的最接近解决方案的解决方案适用于不同的用例,其中关系在 2 个实体之间(而不是一个实体自身)。
这是实体类的重要部分:
package iob.data;
import iob.data.primarykeys.InstancePrimaryKey;
import iob.logic.exceptions.instance.InvalidBindingOperationException;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.IdClass;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import java.util.Date;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
@RequiredArgsConstructor
@Entity
@Table(name = "INSTANCES")
@IdClass(InstancePrimaryKey.class)
public class InstanceEntity {
//<editor-fold desc="Primary key">
@Id
// The index would be generated from a sequence named "INSTANCES_SEQUENCE"
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "INSTANCES_SEQUENCE")
// Here we create that sequence, and define it to be updated every insertion (allocationSize = 1).
@SequenceGenerator(name = "INSTANCES_SEQUENCE", sequenceName = "INSTANCES_SEQUENCE", allocationSize = 1)
private long id;
@Id
@NonNull
private String domain;
//</editor-fold>
//<editor-fold desc="Many to Many relation">
// Define a new table that would store the references
@JoinTable(name = "INSTANCES_TO_INSTANCES",
// The main columns for this attribute are the parent's primary key which is constructed from domain and id
inverseJoinColumns = {@JoinColumn(name = "PARENT_ID", referencedColumnName = "id"),
@JoinColumn(name = "PARENT_DOMAIN", referencedColumnName = "domain")},
// The referenced columns for this attribute are the child's primary key which is also constructed from domain and id
joinColumns = {@JoinColumn(name = "CHILD_ID", referencedColumnName = "id"),
@JoinColumn(name = "CHILD_DOMAIN", referencedColumnName = "domain")})
// Declare the parent's side of the relation
@ManyToMany(fetch = FetchType.LAZY)
private Set<InstanceEntity> parentInstances = new HashSet<>();
// Declare the children's size of the relation, and define that it is related to the parentInstances
@ManyToMany(mappedBy = "parentInstances", fetch = FetchType.LAZY)
private Set<InstanceEntity> childInstances = new HashSet<>();
//</editor-fold>
public void addParent(InstanceEntity parent) {
if (this.equals(parent))
throw new InvalidBindingOperationException("Cannot assign parent to himself");
parentInstances.add(parent);
}
public void addChild(InstanceEntity child) {
if (this.equals(child))
throw new InvalidBindingOperationException("Cannot assign child to himself");
childInstances.add(child);
}
@Override
public int hashCode() {
return Objects.hash(id, domain);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
InstanceEntity entity = (InstanceEntity) o;
return id == entity.id && domain.equals(entity.domain);
}
}
到目前为止,我尝试(可能很天真)为parentInstance 编写getter 并将其传递给Pagable 对象(因为它适用于derived-queries,所以值得一试????)但显然它什么也没做。
我能想到的唯一解决方案是删除关系并手动创建它(使用另一个实体创建表并添加一个新的PagingAndSortingRepository,它将检索相关实例,然后将它们转换为服务中的InstanceEntity )。
那么,如何为parentInstances 和childInstances 添加分页支持?
【问题讨论】:
标签: java jpa spring-data many-to-many