Почему eclipselink / jpa пытается сохранить сущность, а я об этом не спрашиваю? - PullRequest
0 голосов
/ 16 сентября 2010

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

Однако, так как я пытаюсь сохранить это, meng 'eclipselink / 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 (для тестирования) с здесь .

Это ожидаемое поведение?Если так, то почему?И самое главное, как решить?

Похоже, что

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

в значении является виновником, хотя я не понимаю, почему это должно. документация гласит:

Если объект уже управляется, операция persist игнорируется, хотя операция persist будет каскадно связана со связанными объектами, для которых элемент каскада установлен в PERSIST илиВСЕ в аннотации отношений.

Ответы [ 2 ]

1 голос
/ 16 сентября 2010

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

0 голосов
/ 16 сентября 2010

Скорее всего, вы столкнетесь:

[...] Если объект отсоединен [...], транзакция завершится неудачей.

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

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

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

...