7

我有一个 JPA 对象,它具有这样的多对多关系:

@Entity
public class Role {
    //...

    @ManyToMany(fetch=FetchType.EAGER)
    @JoinTable(
    name="RolePrivilege",
    joinColumns=
        @JoinColumn(name="role", referencedColumnName="ID"),
    inverseJoinColumns=
        @JoinColumn(name="privilege", referencedColumnName="ID")
    )
    private Set<Privilege> privs;
}

RolePrivilege 没有 JPA 对象,因此我不确定如何编写 JPQL 查询来删除角色对象的 privs 字段中的条目。例如,我试过这个,但它不起作用。它抱怨 Role.privs 没有被映射。

DELETE FROM Role.privs p WHERE p.id=:privId

我不确定还能尝试什么。我当然可以只编写一个从连接表 RolePrivilege 中删除的本机查询。但是,我担心这样做会与本机查询不会更新的本地缓存对象进行不良交互。

甚至可以编写 JPQL 来从这样的连接表中删除条目吗?如果不是,我可以加载所有角色对象并从每个角色的 privs 集合中删除条目,然后保留每个角色。但是,如果一个简单的 JPQL 查询可以一次完成所有操作,那么这样做似乎很愚蠢。

4

3 回答 3

3

JPQL 更新和删除语句需要引用实体名称,而不是表名称,因此我认为您建议的方法不走运。

根据您的 JPA 提供者,您可以使用简单的原始 SQL 语句(应该 100% 可移植)从 JoinTable 中删除条目,然后以编程方式与您的缓存提供者 API 交互以逐出数据。例如,在 Hibernate 中,您可以调用 evict() 来使二级缓存中的所有“Role.privs”集合过期:

sessionFactory.evictCollection("Role.privs", roleId); //evict a particular collection of privs
sessionFactory.evictCollection("Role.privs"); //evict all privs collections

不幸的是,我没有使用足够的 JPA API 来确定确切支持什么。

于 2009-07-02T06:04:56.667 回答
3

我还在寻找一种 JPQL 方法来删​​除多对多关系(包含在连接表中)。显然,ORM 中没有表的概念,所以我们不能使用 DELETE 操作……但我希望有一个特殊的操作符来处理这些情况。像 LINK 和 UNLINK 之类的东西。也许是未来的功能?

无论如何,为了实现这一需求,我一直在使用实体 bean 中实现的集合,即映射多对多关系的集合。

例如,如果我有一个与 Courses 具有多对多关系的类 Student:

@ManyToMany
private Collection <Courses> collCourses;

我在实体中为该集合构建了一个 getter 和 setter。然后,例如从 EJB 中,我使用 getter 检索集合,添加或删除所需的 Course,最后,使用 setter 分配新集合。它已经完成了。它完美地工作。

但是我主要担心的是性能。ORM 应该保留所有对象的巨大缓存(如果我没记错的话),但即使使用它来更快地工作,我想知道从集合中检索所有元素是否真的有效......

因为对我来说,它与从表中检索注册表并使用纯 Java 而不是直接或间接与内部数据库引擎(SQL、JPQL ...)一起工作的查询语言对它们进行后过滤一样低效。

于 2009-07-19T14:50:03.457 回答
2

Java 是一种面向对象的语言,ORM 的全部意义在于向您隐藏连接表等的细节。因此,即使考虑从连接表中删除而不考虑后果也会很奇怪。

不,你不能用 JPQL 来做到这一点,那就是实体。

检索任一端的实体并清除它们的集合。这将删除连接表条目。面向对象。

于 2009-07-03T07:52:41.300 回答