У меня есть класс Пользователь
class User {
int id;
String name;
}
где id
собственный генератор в User.hbm.xml
и name
первичный ключ в DB.
В моей базе данных я сохранил некоторую информацию о Пользователях.
Чем я хочу соединиться с этой информацией о Пользователе.
Например, в моем DB я ссорюсь INSERT INTO User VALUES ('Bill');
Main.java
User bill = new User();
bill.setName("Bill");
session.saveOrUpdate(bill);
Этот код всегда пытается вставить новое Bill
строка в таблицу, а не обновление существующее Bill
строка.
Этот код всегда пытается вставить счет в базу данных, а не обновлять, если в БД есть строка о Билле ...
Из раздела 10.7.Автоматическое определение состояния в документации ядра Hibernate:
saveOrUpdate ()
выполняет следующие действия:
- если объект уже является постоянным в этом сеансе ничего не делать
- , если другой объект, связанный с сессия имеет такой же идентификатор, бросить исключение
- , если объект не имеет свойство идентификатора,
save ()
it- , если идентификатор объекта имеет значение назначен вновь созданному экземпляру объект,
save ()
it- , если объект версией
или
<отметка времени>
и версия значение свойства такое же значение назначен вновь созданному экземпляру объект,save ()
it- в противном случае
update ()
объект
Когда вы делаете:
User bill = new User();
bill.setName("Bill");
session.saveOrUpdate(bill);
Этому вновь созданному экземпляру не присвоено никакого значения идентификатора, и saveOrUpdate ()
будет save ()
это, как указано в документации. Если это не то, что вам нужно, сделайте имя
первичным ключом.
Итак, Id не сохраняется в базе данных?
Почему Id не является первичным ключом в de DB, если вы отображаете его в Hibernate как идентификатор?
Почему haven «Разве вы просто не наложили уникальное ограничение на« Имя »в базе данных и не создали ограничение первичного ключа для идентификатора?
То есть вы хотите, чтобы:
User u1 = new User("Bill");
session.save(u1);
User u2 = new User("Bill");
session.saveOrUpdate(u2);
заметил, что u1 и u2 - один и тот же счет, и сохранил его только один раз? У Hibernate нет способа узнать, что Биллы - это один и тот же человек. Он только смотрит на id пользователя u2, видит, что он не установлен, делает вывод, что u2 должен быть вставлен, пробует это и сообщает об исключении.
SaveOrUpdate сохраняет как совершенно новый объект, так и загруженный объект, который в настоящее время присоединен к сессии. Итак, это работает (при условии, что у вас где-то есть метод findByName и есть другой атрибут, скажем, favoriteColor):
User u1 = new User("Bill");
u1.setFavoriteColor("blue");
session.saveOrUpdate(u1);
User u2 = findByName("Joe");
u2.setFavoriteColor("red");
session.saveOrUpdate(u2);
Но это не то, что вы хотите, верно?
Ваша проблема усугубляется тем, что у вашей сущности есть суррогатный первичный ключ и, отдельно, бизнес-ключ (обеспечиваемый ограничением уникальности). Если бы у вас не было поля id и только имя в качестве первичного ключа, вы могли бы использовать merge() (для обсуждения saveOrUpdate vs merge, посмотрите здесь):
User u1 = new User("Bill");
u1.setFavoriteColor("blue");
session.save(u1);
User u2 = new User("Bill");
u2.setFavoriteColor("red");
u2 = session.merge(u2);
Но у вас этого нет, вам нужно обеспечить и PK-ограничение на id, и уникальность на имени. Поэтому вам нужен какой-то вариант merge, который это делает. Очень приблизительно, вам нужно что-то вроде этого:
public User mergeByName(User user) {
User merged;
User candidate = findByName(user.getName());
if (candidate != null) {
user.setId(candidate.getId());
merged = session.merge(user);
} else {
session.save(user);
merged = user;
}
return merged;
}
Первый вопрос: если вам нужно получить пользователя по имени «Билл». Как бы Вы это сделали? Это должно дать вам представление.
Для обновления вам необходимо иметь идентификатор, связанный с пользовательским объектом. Установка только атрибута name не поможет. Если вы хотите обновить независимо от того, не имея идентификатора, используйте HQL в качестве запроса.
Query query = session.createQuery("update User u set u.name = :newName where u.name=:name");
query.setString("name", "Bill");
query.setString("newName", "John");
query.executeUpdate();
Вы должны использовать session.update(object) во время обновления, и session.save(object) при сохранении