【问题标题】:Spring boot, How to perform conditional query on many to many relationship with bridge table?Spring Boot,如何对桥表的多对多关系进行条件查询?
【发布时间】:2021-10-06 01:12:21
【问题描述】:

我有三个实体包括桥实体:

团队实体:

       public class Team {
        
            @Id
            @GeneratedValue(strategy = GenerationType.IDENTITY)
            @Column(name = "TEAM_ID")
            private Integer id;
        
            @Column(name = "teamname", length = 128, nullable = false, unique = true)
            private String teamname;
            @Column(name = "delete_date", length = 128, nullable = true)
            private Date delete_date;
        
            @Column(name = "description", nullable = true, length = 240)
            private String description;
        
            @Column(name = "active", length = 64, nullable = false)
            private int active;
            @OneToMany(mappedBy = "team", fetch = FetchType.LAZY)
            private Set<TeamUsers> team_users = new HashSet<TeamUsers>();

---getter setter constructur
    }

用户实体:

   @Entity
    @Table(name = "tblUsers")
    public class User {
    
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Integer id;
        @Column(name = "Username", length = 128, nullable = false, unique = true)
        private String username;
        @Column(name = "FirstName", nullable = false, length = 45)
        private String firstName;
        @Column(name = "LastName", nullable = false, length = 45)
        private String lastName;
        @Column(name = "Password", length = 64, nullable = false)
        private String password;
        @Column(name = "Email", length = 128, nullable = false, unique = true)
        private String email;
        @Column(name = "Phone", length = 64, nullable = false, unique = true)
        private String phoneNumber;
    
    
        @OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
    
        private Set<TeamUsers> team_users = new HashSet<TeamUsers>();

---getter setter constructur

    }

TeamUsers - 具有额外列的桥接实体(活动):

@Entity
@Table(name = "team_users")

public class TeamUsers implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    @ManyToOne(fetch = FetchType.LAZY, optional = false, cascade = CascadeType.ALL)
    @JoinColumn(name = "TEAM_ID")
    private Team team;

    @ManyToOne(fetch = FetchType.LAZY, optional = false, cascade = CascadeType.ALL)
    @JoinColumn(name = "USER_ID")
    private User user;

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

---getter setter constructur
}

在团队存储库中我有代码:

package com.crmbackend.allService.teamService.repo;

import java.util.List;

import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.PagingAndSortingRepository;

import com.crmbackend.entity.Team;

public interface TeamRepository extends PagingAndSortingRepository<Team, Integer> {

    @Query("select t from Team t")
    public List<Team> getAllTeamAndDetails();

}

如果我在 Junit Test 中调用 getAllTeamAndDetails() 方法,结果是所有团队信息: 它基本上告诉我我有多少个团队,以及团队用户反对谁属于哪个团队。

现在,我的问题是我想获取所有团队信息和团队用户信息, 但在桥接表中只有它们的 active = 1。

这意味着如果团队用户记录的活动 = 0,则该用户不应显示在结果中。

这个查询应该是什么样子或者最好的方法是什么?

谢谢

【问题讨论】:

  • 你总是想要那个(可能)还是只在这个查询中(不可能,因为我无法在查询中过滤集合)
  • @SimonMartinelli 如果不可能,那么还有其他方法吗?最后,我将有一个 API 来返回团队信息和用户信息,并提供给前端权限。那么这里最好的方法是什么?是否需要多次获取数据库才能返回API层?
  • 你必须使用JPA吗?因为 JPA 不支持您的用例。它可能会以不止一个查询结束。如果您使用 jOOQ 进行读取,您可以在一个查询中做到这一点:blog.jooq.org/2021/07/06/…
  • @SimonMartinelli 是的,这很好,我会检查一下。但我认为我的案例是一个非常典型的例子,只有三个表。在现实世界的开发中,一旦用户进入团队管理页面,用户首先会看到所有的团队信息和用户,对吧?那些专业开发人员如何使用服务层上的 API 调用将所有数据显示回 UI?
  • 这些将是多个请求。不止一个。您只加载用户当前看到的数据。所以通常没有加载树

标签: mysql spring-boot hibernate jpa


【解决方案1】:

这对于可用的普通 JPA/Hibernate 或 Spring Data JPA 工具是不可能的。为此,您必须使用 DTO。我认为这是Blaze-Persistence Entity Views 的完美用例。

我创建了该库以允许在 JPA 模型和自定义接口或抽象类定义模型之间轻松映射,例如 Spring Data Projections on steroids。这个想法是您按照自己喜欢的方式定义目标结构(域模型),并通过 JPQL 表达式将属性(getter)映射到实体模型。

使用 Blaze-Persistence Entity-Views 的用例的 DTO 模型可能如下所示:

@EntityView(Team.class)
public interface TeamDto {
    @IdMapping
    Integer getId();
    String getDescription();
    @Mapping("team_users[active = 1].user")
    Set<UserDto> getUsers();

    @EntityView(User.class)
    interface UserDto {
        @IdMapping
        Integer getId();
        String getUsername();
    }
}

查询是将实体视图应用于查询的问题,最简单的就是通过 id 进行查询。

TeamDto a = entityViewManager.find(entityManager, TeamDto.class, id);

Spring Data 集成让您可以像使用 Spring Data Projections 一样使用它:https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-data-features

Page<TeamDto> findAll(Pageable pageable);

最好的部分是,它只会获取实际需要的状态!

【讨论】:

    猜你喜欢
    • 2021-10-25
    • 1970-01-01
    • 2020-08-02
    • 1970-01-01
    • 1970-01-01
    • 2018-10-29
    • 2015-07-20
    • 2021-11-20
    • 2013-11-18
    相关资源
    最近更新 更多