简体   繁体   English

在AdditionalCriteria中使用一对多关系

[英]Using one to many relation in AdditionalCriteria

Entities: Post, Space and Profile. 实体:帖子,空间和个人资料。 In summary: 综上所述:

class Post { Space space; String text; }

class Space { List<Profile> members; }

class Profile { String username; List<Space> spaces; }

How to set an @AdditionalCriteria on Post to only return the posts that belongs to the spaces which the current user is a member of. 如何在Post上设置@AdditionalCriteria以仅返回属于当前用户所属空间的帖子。

What I have tried so far are below. 到目前为止,我已经尝试过以下内容。

#1 - :currentUserProfile in space.members #1-:space.members中的currentUserProfile

@AdditionalCriteria(":currentUserProfile in (this.space.members)")

Profile profile = new Profile();
em.setProperty("currentUserProfile", profile);

Results in: 结果是:

Exception [EclipseLink-6015] (Eclipse Persistence Services - 2.6.2.v20151217-774c696): org.eclipse.persistence.exceptions.QueryException
Exception Description: Invalid query key [space] in expression.
Query: ReadObjectQuery(name="readPost" referenceClass=Post )

#2 - :currentUserProfile member of space.members #2-:space.members的:currentUserProfile成员

@AdditionalCriteria(":currentUserProfile member of this.space.members")

Profile profile = new Profile();
em.setProperty("currentUserProfile", profile);

Results in: 结果是:

Caused by: org.postgresql.util.PSQLException: Não pode inferir um tipo SQL a ser usado para uma instância de br.com.senior.social.model.profile.Profile. Use setObject() com um valor de Types explícito para especificar o tipo a ser usado.
    at org.postgresql.jdbc.PgPreparedStatement.setObject(PgPreparedStatement.java:1039)

In english: "Could not infer a SQL type to use for an instance of _. Use setObject() with a explicit value of Types to set the type to be used." 用英语:“无法推断用于_实例的SQL类型。使用显式值为Types的setObject()来设置要使用的类型。”

#3 - this.space in profile.spaces #3-profile.spaces中的this.space

@AdditionalCriteria("this.space in (select p.spaces from Profile p where p.username = :currentUsername)")

String username = "foo";
em.setProperty("currentUsername", username);

Results in: 结果是:

Exception [EclipseLink-0] (Eclipse Persistence Services - 2.6.2.v20151217-774c696): org.eclipse.persistence.exceptions.JPQLException
Exception Description: Problem compiling [this.space in (select p.spaces from Profile p where p.username = :currentUsername)]. 
[131, 139] The state field path 'p.spaces' cannot be resolved to a collection type.

#4 - :currentUsername = (subselect) #4-:currentUsername =(子选择)

@AdditionalCriteria(":currentUsername = (select p.username from Profile p where p.username = :currentUsername and this.space in (p.spaces))")

String currentUsername = "foo";
em.setProperty("currentUsername", currentUsername);

Results in: 结果是:

org.postgresql.util.PSQLException: ERROR: relation "post" does not exist
  Posição: 423

EclipseLink emits a SQL for the table without using the descriptor (prefix). EclipseLink在不使用描述符(前缀)的情况下为该表发出一个SQL。

Solved it by using a not-so-elegant solution: 通过使用不太优雅的解决方案解决了它:

First, I added a raw ID attribute to the Post-Space relation: 首先,我向Post-Space关系添加了一个原始ID属性:

class Post {
    @Column(name = "SPACE_ID", updatable = false, insertable = false)
    private String spaceId;
}

Then referenced it in the additional criteria: 然后在其他条件中引用它:

@AdditionalCriteria("this.spaceId in :currentUserSpaceIds")

And initialized :currentUserSpaceIds to the actual spaces that the current user is member of. 并将:currentUserSpaceIds初始化为当前用户所属的实际空间。

EntityManager em = ...;
Profile profile = ...; // current user profile
List<Space> spaces = profile.getSpaces();
List<String> spaceIds = new ArrayList<>();
for (Space space : spaces) { spaceIds.add(space.getId()); }
em.setProperty("currentUserSpaceIds", spaceIds);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM