2010-09-16 1 views
0

Я пытаюсь сохранить 3 сущности (exp, def, meng) в транзакции, а затем сохранить еще 2 (def ', meng'), где meng 'связан с exp.Почему eclipselink/jpa пытается сохранить объект, пока я его не прошу?

Однако, как я пытаюсь упорствовать EclipseLink Meng»/ jpa2 в настоящее время сказано:

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

который сгенерирует expession так как он был уже установлен, и это ключ. Таким образом, по-видимому, сохраняющаяся сущность meng ', которая включает в себя обновление самого 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 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

В основном, вероятно, вы столкнетесь:

[...] Если объект отсоединяется [...] сделка совершить не удастся.

(тот же источник, что вы со ссылкой)

Если вы будете упорствовать новый объект, который ссылается на уже постоянный объект, вы должны использовать «сливаться» вместо «сохраняются». «merge» будет сохранять новые объекты и обновлять существующие объекты.

Остерегайтесь того факта, что операция слияния вернет прикрепленный граф данных, который должен использоваться для дальнейших операций в рамках одного и того же контекста персистентности.

+0

поэтому, если удалить все атрибуты аннотации каскада из значения persist должно работать. Кажется, так оно и есть, но как-то объект скрывается. Действительно, когда я прихожу, чтобы удалить все значения, которых нет (когда я удаляю каскадную операцию холдингового объекта). Если я попытаюсь явно удалить его, я получаю исключение из привязки, чтобы удалить таблицу, в которой содержится отношение btw к объектам exp и meng. Зачем? – simpatico

1

Frank является правильным. Вы не читаете в выражении, поэтому, когда вы вызываете упор на значение, когда он ссылается на существующие выражения, они отключаются, что приводит к сбою транзакции. Вызов слияния будет работать, или вы можете удалить каскад persist в отношениях exps, так как вы, похоже, сохраняете новые выражения напрямую, так или иначе не нужны.

+0

, так что это может быть более утонченным: @ManyToMany (cascade = {CascadeType.MERGE, CascadeType.REFRESH, CascadeType.REMOVE}). Однако, как только я удалю выражение (после удаления всех mengs в db, я получаю DELETE в таблице «EXPRESSION», вызвал нарушение ограничения внешнего ключа «MNNGXPRSSXPSXPRSSN». – simpatico