Почему некоторые модификации объекта теряются, когда я объединяю этот объект в Hibernate? - PullRequest
0 голосов
/ 16 ноября 2018

Вот соответствующие части кода, который я унаследовал.Объект «процесс» - это старый процесс, который передается методу.Объект «newProcess» - это то, чем я заменяю его, используя различные поля по выбору пользователя.

try
{
   final EntityManager em = getEntityManager();
   em.getTransaction().begin();
   JpaProcessDAO pDao = new JpaProcessDAO(em);
   Process newProcess = pDao.findById(processId);

    newProcess.setName(process.getName());
    newProcess.setDataBaseVersion(process.getDataBaseVersion());
    newProcess.setNotes(process.getNotes());
    newProcess.setReadyForUse(process.getReadyForUse();
    newProcess.setSteps(process.getSteps());
    em.merge(newProcess);   <---- WHERE PROBLEM OCCURS
    em.persist(newProcess);
    em.getTrasaction().commit();
}

RESULT : каждое поле, которое я изменяю, изменяется в newProcess EXCEPT "Шаги».Во время шага слияния в коде этот список возвращается к шагам, которые были в исходном объекте «process».

Теперь это может быть потому, что «Step» сам объект, а не примитив, как всеиз других полей, которые я установил в "newProcess":

Отображение в Process.java

@OneToMany(mappedBy="process")
private List<Step>
// getter, setter

В Step.java есть коллекция объектов, некоторые изкоторые представляют собой списки самих непримитивных объектов.

Step.java

public class Step implements Serializable {
    @Id
    @Column(name = "step_id")
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private int stepId;

    private String duration;
    private String name;
    private String notes;
    private Integer sort;

    @OneToMany(mappedBy="step", cascade=CascadeType.REMOVE)
    private List<Constituent> constituents;

    @OneToMany(mappedBy="step")
    private List<Reference> references;

    @ManyToOne
    @JoinColumn(name ="process_id")
    private Process process;

    @OneToMany(mappedBy="step",cascade=CascadeType.REMOVE)
    private List<StepEquipment> stepEquipments;

    public Step() {
    }

    // getters/setters
}

Кто-нибудь знает, что этот унаследованный код, который я мог, мог сделать неправильно?


ДОПОЛНЕНИЯ К КОДУ 11/29:

public T findById(final Integer id) throws CPDPersistenceExceptin {
   return findByPrimaryKey(id,templateClass);
}

public T findBYPrimaryKey(Object key, Class<T> clazz)  {
   T t = getEntityManager().find(clazz,key);
   getEntityManager.merge(t);
   getEntityManager.refresh(t);
   return t; <--------------  newProcess is returned by this statement.
}

newProcess не содержит шагов, которые были в исходном процессе, и не имеет ProcessCategories, которые были в процессе.Журналы Hibernate сообщают, что select выполняется для process_id, database_version, process_name, process_notes и process_ready_to_use только в операторах слияния и обновления.

Ответы [ 2 ]

0 голосов
/ 17 ноября 2018

Как и в ответе от dyslexit сказал, что вам нужно установить Process для каждого Step.

Но кроме того, вам нужно иметь новыйStep s сохранены и старые удалены.Вы можете сделать это вручную для Step, но более простым способом было бы немного изменить ваш код.

Mofify аннотации сопоставления в шаге, например:

@OneToMany(mappedBy = "process", cascade=CascadeType.PERSIST, orphanRemoval=true)
private List<Step> steps;

, так что скажите сохранить для каскадированияStep s также и удалить все Steps, отсоединенные от Process.

Изменить логику обновления:

// newProcess.setSteps(process.getSteps());
// em.merge(newProcess);   <---- WHERE PROBLEM OCCURS
// em.persist(newProcess);

newProcess.getSteps().clear(); // remove old steps
newProcess.getSteps().addAll(process.getSteps()); // add new steps
// You need to set the other side of association also as below
newProcess.getSteps().forEach(s -> s.setProcess(newProcess));
// em.persist(newProcess); // not sure if needed

SO: не ЗАМЕНИТЬ список, а вместо этого ИЗМЕНИТЬисходный список.

ТАКЖЕ: не может быть необходимости в какой-либо операции слияния / сохранения (и, конечно, выполнение обоих последовательных действий не является чем-то, что должно когда-либо выполняться).Но поскольку вы используете мистическое JpaProcessDAO, я не могу быть уверен, поэтому проверьте это.

А также посмотрите, для чего они на самом деле используются, отличное объяснение здесь .

IЯ предполагаю, что менеджер сущностей мог бы справиться со всем просто отлично - без сохранения / слияния - потому что я думаю, что вы уже получили управляемую сущность при вызове pDao.findById(processId);, поэтому я прокомментировал ее.

Тогда другая историясопоставления, которые у вас есть в вашем Step классе.Этим также могут потребоваться изменения в настройках персистентности и каскада.

В качестве примечания: посмотрите также на этот вопрос , как вы могли бы сделать обновление проще с ModelMapper.

0 голосов
/ 17 ноября 2018

Вам необходимо синхронизировать обе стороны ассоциации.В вашем коде вы устанавливаете только newProcess.setSteps(...), но каждый Step не устанавливает Process.Начиная с здесь :

Однако нам по-прежнему необходимо синхронизировать обе стороны, так как в противном случае мы нарушаем согласованность отношений Доменной модели, и переходы между состояниями объектов не гарантируются.если обе стороны не синхронизированы должным образом.

Другими словами, вам нужно будет сделать что-то вроде:

newProcess.setSteps(process.getSteps());
process.getSteps().forEach(s -> s.setProcess(newProcess));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...