[英]Fetch join hibernate conditionally or change the entity design to conditional fetch on children?
[英]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 :(為清楚起見,我故意將enabled
和deleted
條件放在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))
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.