簡體   English   中英

休眠中的條件連接獲取

[英]conditional join fetch in hibernate

我在Restful Spring MVC項目中使用Spring 5.1.8。 我對某些實體使用了軟刪除和啟用標志。 例如,考慮以下兩個實體:

@Entity
@Table(name = "SECURITY_USER_REALM_ROLE", schema = "BARBANETUSER")
public class SecurityUserRealmRoleEntity {
    private int id;
    private int userId;
    private int realmId;
    private int roleId;

    private UserPersonEntity user;
    private SecurityRealmEntity realm;
    private SecurityRoleEntity role;

    @Id
    @Column(name = "ID_PK")
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SecurityUserRealmRole_Sequence")
    @SequenceGenerator(name = "SecurityUserRealmRole_Sequence", sequenceName = "SECURITY_USER_REALM_ROLE_SEQ", allocationSize = 1)
    public int getId() {
        return id;
    }

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

    @Basic
    @Column(name = "USER_ID_FK")
    public int getUserId() {
        return userId;
    }

    public void setUserId(int userId) {
        this.userId = userId;
    }

    @Basic
    @Column(name = "REALM_ID_FK")
    public int getRealmId() {
        return realmId;
    }

    public void setRealmId(int realmId) {
        this.realmId = realmId;
    }

    @Basic
    @Column(name = "ROLE_ID_FK")
    public int getRoleId() {
        return roleId;
    }

    public void setRoleId(int roleId) {
        this.roleId = roleId;
    }

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "USER_ID_FK", referencedColumnName = "ID_PK", insertable = false, updatable = false)
    public UserPersonEntity getUser() {
        return user;
    }

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

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "REALM_ID_FK", referencedColumnName = "ID_PK", insertable = false, updatable = false)
    public SecurityRealmEntity getRealm() {
        return realm;
    }

    public void setRealm(SecurityRealmEntity realm) {
        this.realm = realm;
    }

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "ROLE_ID_FK", referencedColumnName = "ID_PK", insertable = false, updatable = false)
    public SecurityRoleEntity getRole() {
        return role;
    }

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

@Entity
@Table(name = "SECURITY_ROLE", schema = "BARBANETUSER")
public class SecurityRoleEntity {
    private int id;
    private RoleTypeEnum type;
    private boolean manageView;
    private String title;
    private String slug;
    private Integer sortOrder;
    private boolean enabled;
    private boolean deleted;

    private Set<SecurityPermissionEntity> permissions;

    @Id
    @Column(name = "ID_PK")
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SecurityRole_Sequence")
    @SequenceGenerator(name = "SecurityRole_Sequence", sequenceName = "SECURITY_ROLE_SEQ", allocationSize = 1)
    public int getId() {
        return id;
    }

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

    @Basic
    @Column(name = "TYPE_ID_FK")
    @Convert(converter = RoleTypeConverter.class)
    public RoleTypeEnum getType() {
        return type;
    }

    public void setType(RoleTypeEnum type) {
        this.type = type;
    }

    @Basic
    @Column(name = "MANAGE_VIEW")
    public boolean isManageView() {
        return manageView;
    }

    public void setManageView(boolean manageView) {
        this.manageView = manageView;
    }

    @Basic
    @Column(name = "TITLE")
    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    @Basic
    @Column(name = "SLUG")
    public String getSlug() {
        return slug;
    }

    public void setSlug(String slug) {
        this.slug = slug;
    }

    @Basic
    @Column(name = "SORT_ORDER")
    public Integer getSortOrder() {
        return sortOrder;
    }

    public void setSortOrder(Integer sortOrder) {
        this.sortOrder = sortOrder;
    }

    @Basic
    @Column(name = "ENABLED")
    public boolean isEnabled() {
        return enabled;
    }

    public void setEnabled(boolean enabled) {
        this.enabled = enabled;
    }

    @Basic
    @Column(name = "DELETED")
    public boolean isDeleted() {
        return deleted;
    }

    public void setDeleted(boolean deleted) {
        this.deleted = deleted;
    }

    @ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
    @JoinTable(name = "SECURITY_ROLE_PERMISSION", schema = "BARBANETUSER", joinColumns = @JoinColumn(name = "ROLE_ID_FK", referencedColumnName = "ID_PK", nullable = false),
            inverseJoinColumns = @JoinColumn(name = "PERMISSION_ID_FK", referencedColumnName = "ID_PK", nullable = false))
    public Set<SecurityPermissionEntity> getPermissions() {
        return permissions;
    }

    public void setPermissions(Set<SecurityPermissionEntity> permissions) {
        this.permissions = permissions;
    }
}

如您所見,我的關系是LAZY,因此我需要使用“ Join Fetch”查詢從數據庫中讀取兩個實體。 另一方面,我不能在“ Join Fetch”查詢中使用“ ON子句”。 例如,考慮以下HQL查詢:

SELECT roleRealm FROM SecurityUserRealmRoleEntity roleRealm LEFT JOIN FETCH roleRealm.role role LEFT JOIN FETCH role.permissions

現在,假設我要考慮軟刪除和啟用標志。

問:如何更新此查詢以使其僅讀取已啟用但未刪除的角色?

我已經嘗試了不獲取角色實體而不fetch Left Join

我已經在@Where(clause = "deleted = false") SecurityRoleEntity類上面嘗試過@Where(clause = "deleted = false")

我已經在SecurityUserRealmRoleEntity類的@JoinColumn子句之后嘗試了@Where(clause = "deleted = false")@JoinColumn該方法不起作用。

我已經在過去兩種不起作用的情況下嘗試過@Filter(name = "deleteCondition", condition = "DELETED = false")

我不知道純粹的Hibernate解決方案。 我在博客文章中談到了這一點。

但是您可以考慮使用FluentJPA解決方案:

FluentQuery query = FluentJPA.SQL((SecurityUserRealmRoleEntity roleRealm,
                                   SecurityRoleEntity role,
                                   JoinTable<SecurityRoleEntity, SecurityPermissionEntity>
                                                                 rolesToPermissions,
                                   SecurityPermissionEntity permission) -> {
    SELECT(roleRealm, permission.getId());
    FROM(roleRealm).JOIN(role)
            .ON(roleRealm.getRole() == role)
            .JOIN(rolesToPermissions)
            .ON(rolesToPermissions.join(role, SecurityRoleEntity::getPermissions))
            .JOIN(permission)
            .ON(rolesToPermissions.inverseJoin(permission,
                                            SecurityRoleEntity::getPermissions));

    WHERE(role.isEnabled() && !role.isDeleted());
});

這將產生以下SQL :(為清楚起見,我故意將enableddeleted條件放在WHERE中)

SELECT t0.*, t3.ID_PK 
FROM BARBANETUSER.SECURITY_USER_REALM_ROLE t0  INNER JOIN BARBANETUSER.SECURITY_ROLE t1
  ON (t0.ROLE_ID_FK = t1.ID_PK)  INNER JOIN BARBANETUSER.SECURITY_ROLE_PERMISSION t2
  ON (t2.ROLE_ID_FK = t1.ID_PK)  INNER JOIN BARBANETUSER.SECURITY_PERMISSION t3
  ON (t2.PERMISSION_ID_FK = t3.ID_PK) 
WHERE (t1.ENABLED AND NOT(t1.DELETED))

您可以在此處閱讀有關FluentJPA中的ManyToMany概念的信息

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM