spring-data-jpa Spring Data JPA:三个实体的ManyToMany关系,查询结果与findById重复

4nkexdtk  于 2022-11-10  发布在  Spring
关注(0)|答案(1)|浏览(144)

User.java

@Entity
@Table(name = "test_user")
public class User implements Serializable {
    private static final long serialVersionUID = 1L;

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

    @JsonProperty(access = Access.WRITE_ONLY)
    private String password;

    private String username;

    private String name;

    @ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    @JoinTable(name = "test_user_and_role", inverseJoinColumns = @JoinColumn(name = "role_id"), joinColumns = @JoinColumn(name = "user_id"))
    private List<UserRole> userRoles = new ArrayList<>();

    public User() {
    }

    public Long getId() {
        return id;
    }

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

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getName() {
        return name;
    }

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

    public List<UserRole> getUserRoles() {
        return userRoles;
    }

    public void setUserRoles(List<UserRole> userRoles) {
        this.userRoles = userRoles;
    }

}

UserRole.java

@Entity
@Table(name = "test_user_role")
public class UserRole implements Serializable {
    private static final long serialVersionUID = 1L;

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

    private String role;

    @ManyToMany(mappedBy = "userRoles")
    @JsonProperty(access = Access.WRITE_ONLY)
    private List<User> users = new ArrayList<>();

    @ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.REFRESH)
    @JoinTable(name = "test_role_and_permission", inverseJoinColumns = @JoinColumn(name = "permission_id"), joinColumns = @JoinColumn(name = "role_id"))
    private List<RolePermission> permissions = new ArrayList<>();

    public UserRole() {
    }

    public Long getId() {
        return id;
    }

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

    public String getRole() {
        return role;
    }

    public void setRole(String role) {
        this.role = role;
    }

    public List<User> getUsers() {
        return users;
    }

    public void setUsers(List<User> users) {
        this.users = users;
    }

    public List<RolePermission> getPermissions() {
        return permissions;
    }

    public void setPermissions(List<RolePermission> permissions) {
        this.permissions = permissions;
    }

}

RolePermission.java

@Entity
@Table(name="test_role_permission")
public class RolePermission implements Serializable{

    private static final long serialVersionUID = 1L;

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

    private String code;

    private String des;

    @ManyToMany(mappedBy = "permissions")
    @JsonProperty(access = Access.WRITE_ONLY)
    private List<UserRole> roles = new ArrayList<>();

    public String getAuthority() {
        return this.code;
    }

    public Long getId() {
        return id;
    }

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

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getDes() {
        return des;
    }

    public void setDes(String des) {
        this.des = des;
    }

    public List<UserRole> getRoles() {
        return roles;
    }

    public void setRoles(List<UserRole> roles) {
        this.roles = roles;
    }

}

JDK:17Spring引导:2.7.4
findById和findBy也生成不同结构SQL。findById使用左外部连接。findByName使用子查询。
用户只有一个角色,角色有三种权限。
如果使用findByUsername,它将正确返回用户信息。

{
    "username": "admin",
    "userRoles": [
        {
            "created": null,
            "id": 1,
            "role": "admin",
            "roleName": "admin",
            "permissions": [
                {
                    "authority": "user_query",
                    "code": "user_query",
                    "id": 1
                },
                {
                    "authority": "role_query",
                    "code": "role_query",
                    "id": 2
                },
                {
                    "authority": "equ_query",
                    "code": "equ_query",
                    "id": 3
                }
            }
        ]
    }

如果我使用findById,同样的角色重复三次。

{
"username": "admin",
"userRoles": [
    {
        "id": 1,
        "permissions": [
            {
                "authority": "user_query",
                "code": "user_query",
                "id": 1
            },
            {
                "authority": "role_query",
                "code": "role_query",
                "id": 2
            },
            {
                "authority": "equ_query",
                "code": "equ_query",
                "id": 3
            }
        ],
        "role": "admin",
        "roleName": "admin",
    },
    {
        "id": 1,
        "permissions": [
            {
                "authority": "user_query",
                "code": "user_query",
                "id": 1
            },
            {
                "authority": "role_query",
                "code": "role_query",
                "id": 2
            },
            {
                "authority": "equ_query",
                "code": "equ_query",
                "id": 3
            }
        ],
        "role": "admin",
        "roleName": "admin",
        "updated": null
    },
    {

        "id": 1,
        "permissions": [
            {
                "authority": "user_query",
                "code": "user_query",
                "id": 1
            },
            {
                "authority": "role_query",
                "code": "role_query",
                "id": 2
            },
            {
                "authority": "equ_query",
                "code": "equ_query",
                "id": 3
            }
        ],
        "role": "admin",
        "roleName": "admin",
    }
]

}
代码:https://github.com/shuanshuan/demo-questions

bvpmtnay

bvpmtnay1#

当使用id Spring Data获取数据时,JPa会考虑您的fetch = FetchType.EAGER,但当使用其他属性获取数据时,它会忽略并延迟加载这些属性,这样您就不会看到重复的记录。
要在两个查询中获得相同的输出,您需要添加SpringDataJPA构造查询的方式。

@ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.REFRESH)
@Fetch(FetchMode.SUBSELECT)
@JoinTable(name = "test_role_and_permission", inverseJoinColumns = 
    @JoinColumn(name = "permission_id"), joinColumns = @JoinColumn(name = "role_id"))

@Fetch注解来自org.hibernate.annotations包。

相关问题