【问题标题】:Retrieving a Table Join Result Set from my REST API从我的 REST API 检索表连接结果集
【发布时间】:2017-09-19 11:00:32
【问题描述】:

我创建了一个 JHipster Monolithic 应用程序,其中包含以下实体:profile、following & voyage,这会产生以下架构:

  • 我通过添加 PROFILE 实体扩展了 JHI_USER。
  • 每个用户可以关注零个或多个其他用户 (FOLLOWING)。
  • 一个用户有零个或多个航程 (VOYAGES)

在我的网络 Angular 应用程序中,我想为特定用户关注的用户显示航程列表。以下 SQL 查询将为我提供所需的结果集:

SELECT PROFILE.HANDLE, VOYAGE.NAME
FROM PROFILE, VOYAGE, FOLLOWING
WHERE FOLLOWING.USER_ID = 4
AND VOYAGE.USER_ID = PROFILE.USER_ID
AND PROFILE.USER_ID = FOLLOWING.FOLLOWING_ID

在我的 JHipster 应用程序中创建返回此结果集的 REST 端点需要哪些步骤?

我需要执行以下操作吗?

  • 为结果集创建一个新的实体类
  • 创建一个新的 Repository 类来执行查询
  • 在我的 Controller 中创建一个端点,调用 Repository 以检索结果作为我的实体列表

我是 Spring JPA 的新手,并且一直在努力实现它。

=== 更新 ===

这是我项目中的实体类:

“个人资料”实体:

/**
 * A Profile.
 */
@Entity
@Table(name = "profile")
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class Profile implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
    @SequenceGenerator(name = "sequenceGenerator")
    private Long id;

    @NotNull
    @Column(name = "handle", nullable = false)
    private String handle;

    @Column(name = "bio")
    private String bio;

    @OneToOne
    @JoinColumn(unique = true)
    private User user;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getHandle() {
        return handle;
    }

    public Profile handle(String handle) {
        this.handle = handle;
        return this;
    }

    public void setHandle(String handle) {
        this.handle = handle;
    }

    public String getBio() {
        return bio;
    }

    public Profile bio(String bio) {
        this.bio = bio;
        return this;
    }

    public void setBio(String bio) {
        this.bio = bio;
    }

    public User getUser() {
        return user;
    }

    public Profile user(User user) {
        this.user = user;
        return this;
    }

    public void setUser(User user) {
        this.user = user;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        Profile profile = (Profile) o;
        if (profile.id == null || id == null) {
            return false;
        }
        return Objects.equals(id, profile.id);
    }

    @Override
    public int hashCode() {
        return Objects.hashCode(id);
    }

    @Override
    public String toString() {
        return "Profile{" +
            "id=" + id +
            ", handle='" + handle + "'" +
            ", bio='" + bio + "'" +
            '}';
    }
}

“关注”实体:

/** * 追随者。 */ @实体 @Table(name = "以下") @Cache(使用 = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) 公共类Following实现Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
    @SequenceGenerator(name = "sequenceGenerator")
    private Long id;

    @OneToOne
    @JoinColumn(unique = true)
    private User following;

    @ManyToOne
    private User user;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public User getFollowing() {
        return following;
    }

    public Following following(User user) {
        this.following = user;
        return this;
    }

    public void setFollowing(User user) {
        this.following = user;
    }

    public User getUser() {
        return user;
    }

    public Following user(User user) {
        this.user = user;
        return this;
    }

    public void setUser(User user) {
        this.user = user;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        Following following = (Following) o;
        if (following.id == null || id == null) {
            return false;
        }
        return Objects.equals(id, following.id);
    }

    @Override
    public int hashCode() {
        return Objects.hashCode(id);
    }

    @Override
    public String toString() {
        return "Following{" +
            "id=" + id +
            '}';
    }
}

“航行”实体:

/**
 * A Voyage.
 */
@Entity
@Table(name = "voyage")
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class Voyage implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
    @SequenceGenerator(name = "sequenceGenerator")
    private Long id;

    @NotNull
    @Column(name = "name", nullable = false)
    private String name;

    @NotNull
    @Column(name = "start_date", nullable = false)
    private ZonedDateTime startDate;

    @Column(name = "distance")
    private Integer distance;

    @ManyToOne
    private User user;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public Voyage name(String name) {
        this.name = name;
        return this;
    }

    public void setName(String name) {
        this.name = name;
    }

    public ZonedDateTime getStartDate() {
        return startDate;
    }

    public Voyage startDate(ZonedDateTime startDate) {
        this.startDate = startDate;
        return this;
    }

    public void setStartDate(ZonedDateTime startDate) {
        this.startDate = startDate;
    }

    public Integer getDistance() {
        return distance;
    }

    public Voyage distance(Integer distance) {
        this.distance = distance;
        return this;
    }

    public void setDistance(Integer distance) {
        this.distance = distance;
    }

    public User getUser() {
        return user;
    }

    public Voyage user(User user) {
        this.user = user;
        return this;
    }

    public void setUser(User user) {
        this.user = user;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        Voyage voyage = (Voyage) o;
        if (voyage.id == null || id == null) {
            return false;
        }
        return Objects.equals(id, voyage.id);
    }

    @Override
    public int hashCode() {
        return Objects.hashCode(id);
    }

    @Override
    public String toString() {
        return "Voyage{" +
            "id=" + id +
            ", name='" + name + "'" +
            ", startDate='" + startDate + "'" +
            ", distance='" + distance + "'" +
            '}';
    }
}

【问题讨论】:

  • 你是如何添加实体的?手动还是使用生成器?如果你使用了生成器,那么你提到的所有这些东西都会自动为你生成实体类、存储库、服务、rest 端点和角度 crud 接口
  • 我使用了生成器。我要运行的查询不会直接映射到任何现有实体,因为它是多个表的连接,并且返回的结果集包含来自 Profile 和 Voyage 实体的列。
  • 所以我从您的评论中了解到,这与 Jhipster 无关,而是与 spring-data 相关。如果您需要帮助创建查询,您应该阅读docs.spring.io/spring-data/jpa/docs/current/reference/html/… 并发布具体的实体类,因为仅从 UML 很难回答您的问题
  • 我已将实体类添加到我的原始帖子中。也许问题在于我构建实体之间关系的方式。也许我应该重组,以便实体“跟随”和“航行”与“个人资料”(这只是 JHI_USER 的扩展)具有一对多关系,这样我就可以同时引用“跟随”和“航行”通过“个人资料”实体。

标签: spring spring-data-jpa jhipster


【解决方案1】:

按照评论中的建议修改架构后,您需要添加 2 个查询:

1.VoyageRepository:

List<Voyage> findByProfileIn(Collection<Profile> profiles);

2.ProfileRepository

List<Profile> findByFollowingID(long Id);

然后在您的 Voyage Service 中合并这两个查询:

return voyageRepository.findByProfileIn(profileRepository.findbyFollowingId(id));

然后在您的 VoyageRessource 中公开它。

【讨论】:

  • 我修改了 Schema,但在将 List&lt;Profile&gt; findByFollowingID(long Id); 添加到 ProfileRepository 后,我得到了 PropertyReferenceException: No property followingID found for type Profile! Did you mean 'followings'?。这是因为个人资料和关注(一对多)之间的关系是单向的吗?
【解决方案2】:

我得到了这个工作:

1.修改架构,使“配置文件”具有一对多 与“Following”和“Voyage”的关系,即删除 JHI_USER & 'Following' 和 'Voyage' 的关系

2.在 VoyageRepository 中定义以下查询

public interface VoyageRepository extends JpaRepository<Voyage,Long> {
    @Query("select v.name, v.profile.handle from Voyage v, Following f where f.profile.user.id = 4 and f.following.id = v.profile.id")

    List<Voyage> getFeed();
}

我已经在上面的代码中硬编码了 id 值 (4),因为我还没有弄清楚如何将参数传递给查询。 JPA 正在折腾!

【讨论】:

  • @Query("select v.name, v.profile.handle from Voyage v, Following f where f.profile.user.id = :id and f.following.id = v.profile.id") List&lt;Voyage&gt; getFeed(@Param(id) long id);
  • 很高兴它有帮助。
猜你喜欢
  • 2019-10-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多