【问题标题】:Spring JPA add pagination to @ManyToMany [duplicate]Spring JPA向@ManyToMany添加分页[重复]
【发布时间】: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 )。

那么,如何为parentInstanceschildInstances 添加分页支持?

【问题讨论】:

    标签: java jpa spring-data many-to-many


    【解决方案1】:

    我在一些unexpected post 中找到了解决方案。这与分页无关,但它仍然解决了我的问题。

    所以我的解决方案是将以下函数添加到我的PagingAndSortingRepository 界面:

    Page<InstanceEntity> findDistinctByParentInstancesIn(@Param("parent_instances") Set<InstanceEntity> parentInstances, Pageable pageable);
    

    然后调用它是:

    InstanceEntity ie = new InstanceEntity();
    ie.setDomain(parentDomain);
    ie.setId(Long.parseLong(parentId));
    instancesDao.findDistinctByParentInstancesIn(Collections.singleton(ie), PageRequest.of(page, size));
    

    说实话,我不确定它是如何/为什么起作用的。 IntelliJ IDEA 在存储库接口Expected parameter types: Collection&lt;Set&lt;InstanceEntity&gt;&gt; 中给我一个错误。

    所以如果有人有解释,我很乐意听到。

    【讨论】:

      猜你喜欢
      • 2014-02-21
      • 2016-12-01
      • 1970-01-01
      • 2018-11-09
      • 1970-01-01
      • 2020-02-04
      • 2018-10-27
      • 2012-06-07
      • 2014-03-08
      相关资源
      最近更新 更多