JPA @ManyToMany 编写创建但不更新
我的团队有两个类,User
和 Store
,它们通过 JPA @ManyToMany
注释相关。 相关代码如下。
当创建一个新的User
对象并设置它的存储时,生活是美好的。 但是,当尝试通过 Struts 2 / Spring Web UI 更新 User 对象时,我们看到了一些意外的行为。 (通过 JUnit 运行简单的自动化集成测试时不会出现这些问题)。
简而言之,当保存 User
时,其存储集合不会更新 - 数据库显示没有更改,并且重新加载相关的 User
对象显示它有一个未更改的商店集。
我们找到的解决此问题的唯一解决方案(我们不喜欢这个解决方案,它让我们团队中的所有开发人员都有点不安)是创建一个新的 Set
< code>Stores,然后执行 user.setStores(null)
,然后执行 user.setStores(stores)
。
我们正在使用OpenEntityManagerInViewFilter
; 我们使用 Hibernate 作为我们的 JPA 提供者; 我们正在使用 Spring 的 JpaTransactionManager。 我们的代码中没有任何 @Transactional
注释 - 由于其他地方描述的代理行为,添加它们会破坏现有代码。
欢迎任何人就我们如何以一种不令人不安的方式解决这个问题提供任何见解。
User.java 的相关部分:
@ManyToMany
@JoinTable(name = "company.user_store_access",
joinColumns = @JoinColumn(name = "userid"),
inverseJoinColumns = @JoinColumn(name = "storeid"))
public Set<Store> getStores() {
return stores;
}
Store.java 的相关部分:
@ManyToMany(mappedBy = "stores")
public List<User> getUsers() {
return users;
}
UserDetailAction.java 的相关部分: (向下传递一两层,然后:)
entity = getEntityManager().merge(entity);
My team has two classes, User
and Store
, related by JPA @ManyToMany
annotations. The relevant code is below.
When creating a new User
object and setting its stores, life is good. But we're seeing some unexpected behavior when trying to update User objects through our Struts 2 / Spring web UI. (These problems do not occur when running simple automated integration tests through JUnit).
Simply put, when saving a User
, its stores collection is not updated -- the database shows no changes, and reloads of the User
object in question shows it to have an unchanged set of stores.
The only solution that we have found to this problem -- and we don't like this solution, it makes all of the developers on our team a little queasy -- is to create a new Set
of Store
s, then do user.setStores(null)
, then do user.setStores(stores)
.
We are using the OpenEntityManagerInViewFilter
; we are using Hibernate as our JPA provider; we are using Spring's JpaTransactionManager. We don't have any @Transactional
annotations in our code -- and adding them breaks the existing code due to proxy behavior described elsewhere.
Any insight anyone might provide as to how we might solve this problem in a non-queasy manner is welcome.
Relevant part of User.java:
@ManyToMany
@JoinTable(name = "company.user_store_access",
joinColumns = @JoinColumn(name = "userid"),
inverseJoinColumns = @JoinColumn(name = "storeid"))
public Set<Store> getStores() {
return stores;
}
Relevant part of Store.java:
@ManyToMany(mappedBy = "stores")
public List<User> getUsers() {
return users;
}
Relevant parts of UserDetailAction.java:
(pass-throughs down a layer or two, and then:)
entity = getEntityManager().merge(entity);
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
问题是您有一种双向关系,在这种情况下,有一个实体控制另一个实体,从您的映射来看,控制实体是 Store 实体,而不是 User ,因此将用户添加到商店是可行的(因为商店是控制者),但将商店添加到用户则不行。
尝试扭转这种情况,通过使 User 对象成为控制关系的对象,通过在 getStores() 方法上放置 @ManyToMany(mappedBy = "users") 注释并更改 getUsers() 方法。
希望有帮助。
PS 控制关系的实体始终是没有mappedBy 属性的实体。
The problem is that you have a bi-directional relation, and in this case there is one entity that controls the other, and from your mapping the controlling one is the Store entity and not the User, so adding a user to a store would work (since the Store is the one who controls) but adding a store to a user will not.
try inverting the situation, by making the User object the one who controls the relation, by putting the @ManyToMany(mappedBy = "users") annotation on the getStores() method and changing the getUsers() one.
Hope it helped.
P.S. the entity that controls the relation is always the one that doesn't have the mappedBy attribute.
我刚刚遇到同样的问题并在另一页上找到了解决方案。
这是在调用 merge 对我有用
之前调用 getJpaTemplate().flush() 对我有用的方法。
我不明白它起作用的原因。
I just got stuck to same problem and found solution on another page.
Here is what has worked for me
calling getJpaTemplate().flush() before calling merge has worked for me.
I did not get the reason why it worked.
请在您的 User 对象中尝试以下注释:
Please try the following annotation in your User object: