JPA 持久保存来自多对多关系的已持久对象
我在类 A 和类 B 之间有一个 @ManyToMany 关系:类 A 引用类 B 实例的集合,并且此关系配置为 CascadeType.ALL。因此,当 A 通过实体管理器持久化时,A 引用的 B 实例也会被持久化。
A 和 B 都有一个使用 GenerationType.IDENTITY 策略声明的 ID,以使用 MySQL 数据库中的 auto_inc。
问题是:
- 我创建一个新的 A
- 我使用 JPQL 从实体管理器加载一些现有的 B 对象
- 我将 B 对象添加到 A 的 B 集合
=> JPA 尝试保留 B 对象,尽管它们已经被持久化(它们刚刚被加载)。
我不明白为什么它会尝试再次保留它们,它们已正确加载,并且它们自动生成的 id 也已正确加载。
ManyToMany 声明:
@ManyToMany(cascade={CascadeType.ALL})
@JoinTable(name = "ENTRY_ENTITIES", joinColumns =
@JoinColumn(name = "ENTRY", referencedColumnName = "ID"),
inverseJoinColumns = @JoinColumn(name = "ENTITY", referencedColumnName = "ID"))
private List<Entity> entities;
从数据库加载现有对象的查询:
T result = (T) entityManager.createQuery("SELECT x FROM " + entityName + " x WHERE x.externalId='" + externalId + "'").getSingleResult();
持久化:
UserTransaction transaction = getTransaction();
try {
transaction.begin();
entityManager.persist(entity);
transaction.commit();
} catch (Throwable t) {
Logger.getLogger(JpaDao.class.getName()).log(Level.SEVERE, null, t);
}
非常感谢您的帮助!
I have a @ManyToMany relationship between class A and class B : class A references a collection of class B instances, and this relationship is configured as CascadeType.ALL. So when a A is persisted with the entity manager, the B instances referenced by A are also persisted.
Both A and B have an ID declared with the GenerationType.IDENTITY strategy to use the auto_inc from the MySQL database.
The problem is :
- I create a new A
- I load some existing B objects from entityManager using JPQL
- I add the B objects to A's collection of Bs
=> JPA tries to persist the B objects though they are already persisted (they just have been loaded).
I don't understand why it tries to persist them again, they have been properly loaded, and their auto generated id has been well loaded as well.
The ManyToMany declaration :
@ManyToMany(cascade={CascadeType.ALL})
@JoinTable(name = "ENTRY_ENTITIES", joinColumns =
@JoinColumn(name = "ENTRY", referencedColumnName = "ID"),
inverseJoinColumns = @JoinColumn(name = "ENTITY", referencedColumnName = "ID"))
private List<Entity> entities;
The Query to load existing objects from database :
T result = (T) entityManager.createQuery("SELECT x FROM " + entityName + " x WHERE x.externalId='" + externalId + "'").getSingleResult();
The persisting :
UserTransaction transaction = getTransaction();
try {
transaction.begin();
entityManager.persist(entity);
transaction.commit();
} catch (Throwable t) {
Logger.getLogger(JpaDao.class.getName()).log(Level.SEVERE, null, t);
}
Thanks a lot for your help!
我不确定这是否是您问题的原因,但您应该将整个事情包含在交易中。不仅仅是持久性部分:
正如我在评论中所说,您还有其他设计和编码问题:
SELECT x FROM A x WHERE x.externalId = :externalId
I'm not absolutely sure that this is the cause of your problem, but you should include the whole thing inside of a transaction. Not just the persistence part:
As I said in my comments, you have other design and coding problems:
SELECT x FROM A x WHERE x.externalId = :externalId