Java 为什么eclipselink/jpa试图持久化一个实体,而我不';你不要求吗?
我试图在一个事务中持久化3个实体(exp,def,meng),然后持久化另外2个实体(def',meng'),其中meng'与exp相关 然而,当我试图坚持孟日食/jpa2时,有人告诉我:Java 为什么eclipselink/jpa试图持久化一个实体,而我不';你不要求吗?,java,orm,eclipselink,jpa-2.0,Java,Orm,Eclipselink,Jpa 2.0,我试图在一个事务中持久化3个实体(exp,def,meng),然后持久化另外2个实体(def',meng'),其中meng'与exp相关 然而,当我试图坚持孟日食/jpa2时,有人告诉我: Call: INSERT INTO EXPRESSION (EXPRESSION, GENDER) VALUES (?, ?) bind => [exp, null] 这将抛出一个expression,因为它已经被插入并且是一个键。 因此,显然,坚持包含更新exp本身的实体会让eclipsel
Call: INSERT INTO EXPRESSION (EXPRESSION, GENDER) VALUES (?, ?)
bind => [exp, null]
这将抛出一个expression,因为它已经被插入并且是一个键。
因此,显然,坚持包含更新exp本身的实体会让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 testInsertWords()引发乘法异常,异常{
最终列表mengsWithSharedExp=新建LinkedList();
mengsWithSharedExp.add(mengsList.get(3));
mengsWithSharedExp.add(mengsList.get(4));
插入字(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;
}
public void insertWords(EnumMap输入)引发乘法异常{
表达式def=(表达式)input.get(input.definition);
表达式exp=(表达式)input.get(input.Expression);
beginTransaction();
新的(def);
新的(实验);
persistenewmeng(null、exp、def);
提交交易();
}
私有void persistenewmeng(最终MUser usr、表达式exp、最终表达式def)抛出RuntimeException{
最终含义=新含义(usr、exp、def);
如果(!persistIfNew(meng)){
抛出新的RuntimeException(“Meng.+Meng.toString()+”应该是新的。”);
}
如果(usr!=null){
usr.addMeng(meng);
}
}
公共布尔persistIfNew(最终实体){
最终对象键=emf.getPersistenceUnitUtil().getIdentifier(实体);
if(em.find(entity.getClass(),emf.getPersistenceUnitUtil().getIdentifier(entity))!=null){
返回false;
}
em.persist(实体);
返回true;
}
您可以从中签出Maven源代码(要测试)
这是预期的行为吗?若然,原因为何?最重要的是,如何解决
看起来好像
@ManyToMany(cascade=CascadeType.ALL)
private Set<Expression> exps;
@ManyToMany(cascade=CascadeType.ALL)
私有集扩展;
意思是罪魁祸首,尽管我不明白为什么会这样。报告说:
如果实体已被管理,则将忽略持久化操作,尽管持久化操作将级联到相关实体,这些实体的级联元素在关系注释中设置为持久化或全部
您很可能会遇到: […]如果实体被分离[…]事务提交将失败 (与您引用的来源相同) 如果持久化引用已持久化实体的新实体,则必须使用“合并”而不是“持久化”。“合并”将保留新实体并更新现有实体
还要注意,合并操作将返回一个附加的数据图,该数据图必须用于同一持久性上下文中的进一步操作。Frank是正确的。您没有读取表达式,因此当您调用persist on means时,当它引用现有表达式时,它们被分离,这会导致事务失败。调用merge将起作用,或者您可以删除exps关系上的cascade persist,因为您似乎可以直接持久化新表达式,而这是不需要的 所以这可以更精确:@manytomy(cascade={CascadeType.MERGE,CascadeType.REFRESH,CascadeType.REMOVE})。但是一旦我删除了一个表达式(在删除数据库中的所有mengs后,我发现表'EXPRESSION'上的DELETE违反了外键约束'MNNGXPRSSXSPSXPRSSN'。因此,如果从Means persist中删除所有级联注释属性,应该可以工作。看起来是这样,但不知何故,实体仍然潜伏在周围。事实上,当我删除所有的Means时,其中一个是不存在的(当我通过持有实体的级联操作进行删除时)。如果我确实尝试显式删除它,我会得到一个异常,即删除持有exp和MEG实体关系的表。为什么?