2010-09-16 37 views
0

我试图在交易中坚持3个实体(exp,def,meng),然后坚持另外2个(def',meng'),其中meng'与exp有关。为什么eclipselink/jpa试图坚持一个实体,而我没有问它呢?

然而,当我试图坚持萌”的EclipseLink/JPA2被告知:

Call: INSERT INTO EXPRESSION (EXPRESSION, GENDER) VALUES (?, ?) 
    bind => [exp, null] 

,因为它已经被插入,这是一个关键,这将抛出一个expession。 因此,显然坚持包括更​​新exp本身的实体meng会以某种方式使eclipselink认为我要求坚持一个新的exp。

下面是测试:

@Test 
public void testInsertWords() throws MultipleMengsException, Exception{ 
    final List<String[]> mengsWithSharedExp = new LinkedList<String[]>(); 
    mengsWithSharedExp.add(mengsList.get(3)); 
    mengsWithSharedExp.add(mengsList.get(4)); 

    insertWords(mengsWithSharedExp, null, mengsDB); 
} 

下面是有问题的代码:

public void insertWords(EnumMap<Input, MemoEntity> input) throws MultipleMengsException { 
    Expression def = (Expression) input.get(Input.definition); 
    Expression exp = (Expression) input.get(Input.expression); 
    beginTransaction(); 
    persistIfNew(def); 
    persistIfNew(exp); 
    persistNewMeng(null, exp, def); 
    commitTransaction(); 
} 

private void persistNewMeng(final MUser usr, Expression exp, final Expression def) throws RuntimeException { 
    final Meaning meng = new Meaning(usr, exp, def); 
    if (!persistIfNew(meng)) { 
     throw new RuntimeException("Meng ." + meng.toString() + " was expected to be new."); 
    } 
    if (usr != null) { 
     usr.addMeng(meng); 
    } 
} 

public <Entity> boolean persistIfNew(final Entity entity) { 
     final Object key = emf.getPersistenceUnitUtil().getIdentifier(entity); 
     if (em.find(entity.getClass(), emf.getPersistenceUnitUtil().getIdentifier(entity)) != null) { 
      return false; 
     } 
     em.persist(entity); 
     return true; 
    } 

可以检出的Maven源代码(测试)从here

这是预期的行为?如果是这样,为什么?最重要的是,如何解决?

看起来好像

@ManyToMany(cascade=CascadeType.ALL) 
private Set<Expression> exps; 
词义

是罪魁祸首,但我不明白为什么它应该。该documentation说:

如果实体已被管理,persist操作将被忽略,虽然坚持操作将级联到具有设置为持续或ALL的关系注释级联元素相关实体。

回答

0

最有可能碰上:

[...]如果实体被分离[...]事务提交将失败。

如果你坚持下去,它引用一个已经持久性实体的新实体(即你所引用相同的源),您必须使用“合并”,而不是“坚持”。 “合并”将持续新实体并更新现有实体。

还要注意合并操作将返回附加数据图的事实,该数据图必须用于相同持久性上下文中的进一步操作。

+0

所以如果从意思坚持应该工作所有级联注释属性去除。看起来确实如此,但不知怎的,实体仍然潜伏着。事实上,当我删除所有不具有意义的东西时(当我通过控股实体的级联操作删除时)。如果我试图明确删除它,我会得到一个异常,从绑定到删除包含exp和meng实体的关系的表。为什么? – simpatico 2010-09-17 05:40:37

1

弗兰克是正确的。您没有在Expression中读取,因此当您调用persist时,如果它引用现有表达式,它们将被分离,导致事务失败。调用合并会起作用,或者您可以删除exps关系中的级联,因为您似乎直接持续使用新的表达式,直到它不需要。

+0

所以这可能会更精致:@ManyToMany(cascade = {CascadeType.MERGE,CascadeType.REFRESH,CascadeType.REMOVE})。然而,一旦我删除了一个表达式(在删除了db中的所有数据之后,我在表'EXPRESSION'上获得了DELETE导致了对外键约束'MNNGXPRSSXPSXPRSSN'的违反。 – simpatico 2010-09-16 13:03:12

相关问题