Hibernate: сохранение родительских объектов с уже существующими дочерними элементами (однонаправленное)

1

Я хочу сохранить/сохранить объект (родительский) с уникальными дочерними объектами, включенными только родительским объектом. Все работает хорошо, пока не появится дубликат ребенка, здесь я получаю следующее исключение:

Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry


Сначала вы должны знать, что я использую выражение session.bySimpleNaturalId(Child.class).load(child.getMd5Hash()) чтобы проверить, существует ли уже этот дочерний объект, поскольку все дочерние объекты имеют уникальные значения хэша (созданные после инициализации), которые явно не назначены в качестве первичного ключа (их первичный ключ является автоматическим приращением; strategy = GenerationType.TABLE).

Я использую session.merge(child) или любое другое выражение в моем DAO, я получаю то же исключение.

Мой родитель-объект:

@Entity
@Table(name = "parent")
public class Parent implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.TABLE)
    private Long id = null;


    @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    @JoinColumn(name = "kind_child_id", referencedColumnName = "md5hash")
    private Child firstChild;

    @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    @JoinColumn(name = "rude_child_id", referencedColumnName = "md5hash")
    private Child secondChild;

    //private String attributes;
    //Getters & Setters

Мой ребенок-объект:

@Entity
@Table(name = "child")
public class Child implements Serializable {

        @Id
        @GeneratedValue(strategy = GenerationType.TABLE)
        private Long id = null;

        @NaturalId
        @Column(name="md5hash", unique=true)
        private char[] md5hash = new char[32];

        //private String attributes;
        //Getters & Setters


И вот мой метод сохранения/сохранения родителя (включая проверки):

public void writeParent(Parent parent) {
                try {
                    if (parent != null) {
                        if (globalSession == null) {
                            globalSession = getSessionFactory().openSession();
                        }
                        globalSession.beginTransaction();

                            if (parent.getFirstChild() != null) {
                                Child tempFirstChild = (Child)  globalSession.bySimpleNaturalId(Child.class).load(parent.getFirstChild().getMd5Hash());
                                if (tempFirstChild != null) {
                                    parent.setFirstChild(tempFirstChild);
                                    //globalSession.merge(tempFirstChild);
                                    //throws MySQLICV-Exception

                                    //globalSession.update(tempFirstChild);
                                    //throws MySQLICV-Exception
                                }
                            }
                            if (parent.getSecondChild() != null) {
                                Child tempSecondChild = (Child) globalSession.bySimpleNaturalId(Child.class).load(parent.getSecondChild().getMd5Hash());
                                if (tempSecondChild != null) {
                                    parent.setSecondChild(tempSecondChild);

                                    //globalSession.merge(tempSecondChild);
                                    //throws MySQLICV-Exception

                                    //globalSession.update(tempSecondChild);
                                    //throws MySQLICV-Exception

                                }
                            }

                        globalSession.saveOrUpdate(parent);
                        //globalSession.persist(parent);
                        globalSession.getTransaction().commit();
                    }
                } catch (Exception ex) {
                    log.error("FAILURE: ", ex);
                }
finally{
globalSession.close();
}
            }


Возможно, я не понял весь документальный фильм, почему я придумал это: мне даже нужно сказать Hibernate объединить найденные объекты? Как я могу сказать Hibernate, что этих детей нельзя рассматривать как новые объекты, которые необходимо сохранить? Или мне даже нужно переключиться на двунаправленные отношения (в данном случае мне не разрешено использовать двунаправленные отношения)

Любые подсказки приветствуются и очень ценятся, заблаговременно. С уважением, Yeti

  • 0
    Хорошо, позвольте мне понять, почему вы в первую очередь пытаетесь обновить или сохранить дочерний объект, так как вы связываете эти объекты с родительским, и вы сохраняете / обновляете родительский объект, они в любом случае будут сохраняться?
  • 0
    @zerocool Конечно, они будут сохраняться в любом случае, те методы, на которые вы ссылаетесь, предназначены только для операций тестирования, потому что, возможно, я захочу изменить некоторые атрибуты дочернего элемента.
Теги:
hibernate
parent-child
persistence
foreign-key-relationship

1 ответ

0
Лучший ответ

Я сам нашел ответ, иначе. Сначала, чтобы исправить это, я использовал отдельную функцию, чтобы проверить, существует ли дочерний элемент, кроме того, я использовал отдельные сеансы для их проверки (возможно, он не работает, если L2C отключен).

synchronized public Child checkChild(Child child) {
    try {
        if (child != null) {
            tempSession = getSessionFactory().openSession();
            Child tempChild = (Child) tempSession.bySimpleNaturalId(Child.class).load(Child.getMd5Hash());
            if (tempChild != null) {
                return tempChild;
            } else {
                return child;
            }
        } else {
            return null;
        }
    } catch (Exception ex) {
        return null;
    }
    finally{
        tempSession.close();
    }
}

Во-вторых, и есть подсказка, я попытался сохранить родительский объект как параметрическое значение, что неверно, поэтому просто инициируйте новый родительский объект внутри метода и сделайте это.

public void writeParent(Parent parent) {
    tempParent = new Parent();
    tempParent.setFirstChild(checkChild(tempParent.getFirstChild()));
    tempParent.setSecondChild(checkChild(tempParent.getSecondChild()));
    globalSession = getSessionFactory().openSession();
    globalSession.beginTransaction();
    globalSession.saveOrUpdate(tempParent);
    globalSession.getTransaction().commit();
    globalSession.close();
}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню