Слияние Hibernate теряет данные
Я получаю странную проблему с Hibernate и merge.
структура рассматриваемых классов выглядит следующим образом:
Project --> CaseWorkerA --|> CaseWorker --|> User
Итак, в основном у меня есть класс проекта, который содержит ссылку на CaseWorkerA, который является подклассом CaseWorker, который снова является подклассом User.
в коде:
public class Project {
[...]
private CaseWorkerA caseWorkerA;
@ManyToOne(fetch = FetchType.EAGER)
@Cascade({ org.hibernate.annotations.CascadeType.SAVE_UPDATE, org.hibernate.annotations.CascadeType.PERSIST,
org.hibernate.annotations.CascadeType.REFRESH, org.hibernate.annotations.CascadeType.MERGE })
@JoinColumn(name = "CaseWorker_A")
public CaseWorkerA getCaseWorkerA() {
return caseWorkerA;
}
}
тогда у нас есть пользовательская иерархия:
public class User {
[...]
}
public class CaseWorker extends User {
private CaseWorkerStatus status;
@Enumerated(EnumType.STRING)
public CaseWorkerStatus getStatus() {
return status;
}
[...]
}
public class CaseWorkerA extends CaseWorker {
[...]
}
тогда в Dao-классе есть метод для хранения проект:
public class ProjectDao {
[...]
public Project saveUpdateProject(final Project project) {
if (project.getId() == null) {
getSession(false).save(project);
} else {
project = (Project) getSession(false).merge(project);
}
getHibernateTemplate().flush();
return project;
}
}
теперь проблема заключается в следующем:
Dao-метод получает проект, который существует в базе данных. Этот проект связан с CaseWorkerA, который имеет статус CaseWorkerStatus.ACTIVE (как в базе данных, так и в объекте incomming). Но после слияния статус соцработника становится нулевым.
Я действительно не понимаю, как это возможно, так как значение одинаково в базе данных, как и в объекте для хранения, я бы рассчитываем, что после слияния.
(в базе данных нет триггеров для этого поля..)
(Я попытаюсь изменить dao-метод, чтобы использовать saveOrUpdate вместо этого, но даже если это исправит проблему, я все равно очень хотел бы знать, что вызвало ее в первую очередь).
обновление:
так что я возился с отладчиком и обнаружил следующее: Когда я спросил сессии для соцработника в вопрос, оказалось с его набором полей состояния (на самом деле возвращаемый объект был именно тем, который был подключен к проекту).
делаем saveOrUpdate, а потом сделать, в результате соцработник со статусом-поля. Таким образом, это, похоже, проблема с методом merge..
1 ответов
удалось это выяснить, оказалось, что был второй путь от проекта к пользователю (lastChangedBy), где кто-то решил поставить Каскад по какой-то странной причине. Поэтому, когда человек, который в последний раз изменял проект, был соц.работником, lastChangedBy ссылался на него как на пользователя, который ничего не знает о статусе, поэтому он был сохранен как null.
код:
public class Project {
private User changedBy;
@Cascade({ org.hibernate.annotations.CascadeType.SAVE_UPDATE, org.hibernate.annotations.CascadeType.PERSIST,
org.hibernate.annotations.CascadeType.REFRESH, org.hibernate.annotations.CascadeType.MERGE })
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "changed_by")
public User getChangedBy() {
return this.changedBy;
}
[...]
}
пользователь, который был установлен как changedBy, был извлечен из базы данных вот так:
public class UserDao {
public User getUser(final String userName) {
return (User) getSession(false).createQuery("from User u where u.loginName = :username").setParameter("username", userName).uniqueResult();
}
}
Appearantly, даже если пользователь одного конца до получения это-соцработник, поля, имеющие отношение к соцработник не получен..
в любом случае, удалил каскад uneccesary, и все хорошо :)