JPA/Spring Дубликат записи для ключа «PRIMARY»

у меня проблема с JPA.

мой метод сохранения отмечен @Transactional следующим образом:

        @Transactional(propagation = Propagation.REQUIRED)
        public void push(long id) {
            Parent parent = dao.findParentById(id);
            setParentMeta(parent);
            Country country = dao.findCountry(id);
            setParentChild(parent);
            User user = dao.findUser(id);
            dao.update(parent);
        }

        public void setParentMeta(Parent parent){
            parent.setTitle("toto");
            parent.setdescription("some description");
        }

        public void setParentChild(Parent parent){
            List<Child> childList = new ArrayList<>();
            for (String date : dao.getList()) {
                Child child = new Child();
                ChildPK childPK = new ChildPK();
                childPK.setProductId(parent.getId());
                childPK.setDate(date);
                child.setChildPK(childPK);
                child.setParent(parent);
                childList.add(child);
            }
            parent.setChildList(childList);
        }

Моя родительская сущность:

        public class Parent {
            ...
            private long parentId;
            @OneToMany(cascade = CascadeType.ALL, mappedBy = "parent", fetch = FetchType.LAZY, orphanRemoval = true)
            private List<Child> childList;
            ...
        }

Моя дочерняя сущность:

        public class Child {
            ...
            @EmbeddedId
            protected ChildPK childPK;
            @MapsId("parentId")
            @ManyToOne(optional = false, fetch = FetchType.LAZY)
            @JoinColumn(name = "parent_id", referencedColumnName = "parent_id", insertable = true, updatable = true)
            private Parent parent;
            ...
        }
        @Embeddable
        public class ChildPK {
            ....
            @Basic(optional = false)
            @Column(name = "parent_id")
            private long parentId;
            @Basic(optional = false)
            @Column(name = "date")
            @Temporal(TemporalType.TIMESTAMP)
            private Date date;
            ....
        }

моя проблема заключается в том, что когда я удаляю @Transactional(propagation = Propagation.REQUIRED) из метода "push" и помещаю его в dao, все операции вставки/обновления или отката работают отлично:

        @Transactional(propagation = Propagation.REQUIRED)
        public E update(E entity) {
            return entityManager.merge(entity);
        } 

но если я помещу эту аннотацию в метод push и удалю ее из dao, я получу это исключение:

        Duplicate entry '3623238-2016-02-21 00:00:00' for key 'PRIMARY'
        Error Code: 1062
        Call: INSERT INTO child (date, parent_id) VALUES (?, ?)
            bind => [2016-02-21 00:00:00.0, 3623238]

Проблема здесь в том, что eclipselink автоматически очищается при изменении дочернего элемента. есть ли смысл сбрасывать в конце метода push?


person Morad Angel    schedule 23.06.2016    source источник


Ответы (2)


эта ошибка возникает, когда вы пытаетесь сохранить уже существующий объект, с другой стороны, @Transactional(propagation = Propagation.REQUIRED) использует уже открытую транзакцию и открывает новую, когда никто не открыт, я думаю, что проблема с findByParentId, поэтому попробуйте "найти" его, а затем отправить методом push.

person Ibrahim    schedule 23.06.2016
comment
я не могу поместить findByParentId вне метода push - person Morad Angel; 23.06.2016
comment
поясните, пожалуйста, почему вы не можете этого сделать? - person Ibrahim; 23.06.2016
comment
потому что это меняет какие-либо вещи, есть также несколько случаев поиска чуть ниже, проблема здесь в том, что если я удалю все поиск и вызову непосредственное обновление этой работы. и для моего лечения мне нужно найти перед сохранением - person Morad Angel; 23.06.2016
comment
здесь вам нужно сохранить новые дочерние элементы для существующего родителя? - person Ibrahim; 23.06.2016
comment
Пожалуйста, проверьте, является ли столбец (ID) в дочерней таблице auto_increment - person Ibrahim; 23.06.2016
comment
вы можете использовать Propagation.REQUEST_NEW, что означает, что новая транзакция будет открыта независимо от существующей - person Ibrahim; 24.06.2016

Я нашел проблему. диспетчер транзакций плохо настроен, вот решение с примером кода

person Morad Angel    schedule 30.06.2016