Я знаю, что объект находится в состоянии отсоединения, когда мы уже нажали save, и мы должны его снова присоединить.
Предположим, что у меня есть одна форма с текстовыми полями html, и есть кнопка сохранения, которая сохраняет текст в базе данных.
У меня есть этот код
public void edit(Person person) {
logger.debug("Editing existing person");
// Retrieve session from Hibernate
Session session = sessionFactory.getCurrentSession();
// Retrieve existing person via id
Person existingPerson = (Person) session.get(Person.class, person.getId());
// Assign updated values to this person
existingPerson.setFirstName(person.getFirstName());
existingPerson.setLastName(existingPerson.getLastName());
existingPerson.setMoney(existingPerson.getMoney());
// Save updates
session.save(existingPerson);
}
Теперь я могу нажать сохранить любое количество времени, чтобы сохранить данные.
Теперь это означает, что как только я ударил сэкономить в первый раз, он будет отсоединен.
Так что мне нужно сделать что-то особенное для этого или это не имеет значения.
Я хочу знать, при каких условиях мне нужно запрограммировать что-нибудь об отдельном состоянии
Ответ 1
Как только сеанс, используемый для сохранения, загрузки, получения или нахождения объекта, был закрыт, объект становится отсоединенным. Это означает, что он больше не подключается к сеансу и работает как любой другой POJO.
Когда объект привязан и вы меняете одно из его свойств, Hibernate автоматически сохраняет изменения, внесенные вами в соответствующую строку в базе данных (время флеша/фиксации).
При отключении изменения, внесенные вами в объект, автоматически не сохраняются в базе данных. Чтобы сохранить изменения, вам нужно сделать это самостоятельно, вызывая session.update() или session.merge(). Оба метода делают более или менее одно и то же, но делают это по-другому. Я предпочитаю использовать слияние, что менее опасно и приводит к меньшим ошибкам.
Подробнее читайте http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html_single/#objectstate-detached
В вашем коде человек, переданный как аргумент в метод редактирования, вероятно, отключен. То, что вы делаете, это получить человека с тем же идентификатором, что и тот, который был передан из сеанса. existingPerson
прилагается. Затем вы копируете все свойства от отдельного человека в прикрепленный существующий файл. И, наконец, вы сохраняете существующийPerson.
С этим кодом возникают 3 проблемы:
- save не делает то, что вы думаете. save - для вставки нового объекта person. Ваш существующий человек уже существует и уже имеет идентификатор, поэтому операция для использования - это обновление или слияние.
- Вам даже не нужно использовать обновление или слияние, потому что, поскольку existingPerson подключен к сеансу, сделанные вами изменения (setFirstName, setLastName и т.д.) автоматически будут выполняться с помощью Hibernate во время очистки. Это прозрачно.
- Алгоритм, который вы реализовали, является тем же (за исключением каскадов и т.д.), как тот, который используется слиянием, что делает все это автоматически для вас.
Поэтому он должен быть изменен на:
public void edit(Person person) {
logger.debug("Editing existing person, which is a detached object");
// Retrieve session from Hibernate
Session session = sessionFactory.getCurrentSession();
// Retrieve existing person via id, then copy everything from detached person
// to attached one, and return attached one
Person existingPerson = (Person) session.merge(person);
}