我有一个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来删除连接表中的条目吗?如果不是,我可以只加载所有Role对象并从每个对象的privs集合中删除条目,然后保留每个角色。但是,如果一个简单的JPQL查询可以同时完成所有操作,那么这似乎很愚蠢。
答案 0 :(得分: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来确定究竟支持什么。
答案 1 :(得分:2)
Java是一种面向对象的语言,ORM的重点是隐藏连接表的细节等等。因此,即使考虑从连接表中删除而不考虑后果,也会很奇怪。
不,你不能用JPQL,即实体。
检索两端的实体并清除其集合。这将删除连接表条目。面向对象的。
答案 2 :(得分:2)
我也在寻找一种JPQL方法来删除多对多关系(包含在连接表中)。显然,ORM中没有表的概念,所以我们不能使用DELETE操作......但我希望这些情况有一个特殊的运算符。像LINK和UNLINK之类的东西。也许是未来的特色?
无论如何,我为实现这一需求所做的工作是使用实体bean中实现的集合,即映射多对多关系的集合。
例如,如果我有一个与课程有多对多关系的学生类:
@ManyToMany
private Collection <Courses> collCourses;
我在实体中构建了该集合的getter和setter。然后,例如,从EJB,我使用getter检索集合,添加或删除所需的课程,最后,使用setter分配新集合。它已经完成了。它运作得很好。
然而,我主要担心的是表现。 ORM应该保留所有对象的大量缓存(如果我没有记错的话),但即使使用它来更快地工作,我想知道从集合中检索所有元素是否真的有效......
因为对我来说,从表中检索注册表并使用纯Java而不是直接或间接与内部数据库引擎(SQL,JPQL ...)一起使用的查询语言对它们进行后过滤是非常低效的。< / p>