powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Java [игнор отключен] [закрыт для гостей] / Hibernate. merge update saveOrUpdate
25 сообщений из 31, страница 1 из 2
Hibernate. merge update saveOrUpdate
    #38398135
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
В hibernate у класса Session есть такие методы
merge
update
saveOrUpdate

Описание javaDoc как-то не совсем мне понятно.

Можете простыми словами объяснить зачем нужны эти методы, чем они отличаются и как ими правильно пользоваться?
...
Рейтинг: 0 / 0
Hibernate. merge update saveOrUpdate
    #38398162
ivanra
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Неразбериха бывает из-за неправильного понятия сессии.
Многие думают, что она предназначена только для работы с базой, а на самом деле сессия - это прежде всего кеш. Все, что мы пишем и читаем с помощью сессии, параллельно сохраняется в локальном кеше, и при повторном обращении к объекту не нужен сетевой запрос - объект уже хранится локально. Благодаря правильному использованию кеша, программы, написанные с использованием hibernate, зачастую работают быстрее, чем написанные на чистом jdbc.
А теперь смотрим, что происходит.
1) update и saveOrUpdate - 2 разных варианта синхронизации объекта, уже находящегося в сессии, с базой данных. Попросту говоря, объект из кеша сохраняется в базу данных с использованием update-а или insert-a. Есть нюанс: если объекта не было в сессии (detached), то проверяется, а есть ли объект с таким же ключом в локальном кеше. Если есть, то выдается исключение, если нет - пишется в базу и параллельно в кеш.
После выполнения update и saveOrUpdate состояния объекта в сессии и в базе совпадают .
2) merge (присоединение) - "обратная" операция. Имеет смысл для отсоединенных (detached) объектов. Например, мы получили в сессии объект, потом сессию закрыли (кеш обнулился), а сам объект где-то сохранили, и даже изменили некоторые поля. Так вот, когда мы пишем
Код: java
1.
attachedObject = session.merge(detachedObject);

, то происходит следующее:
- объект по ключу запрашивается из базы (делается запрос select ... from ...) - получаем заготовку attachedObject;
- поля attachedObject-а обновляются значениями полей detachedObject-а
- attachedObject сохраняется в кеше, а detachedObject после этого годится только в мусор.
То есть в базу идет только select запрос (и insert, если по ключу ничего не найдено). В общем случае, после выполнения merge состояния объекта в сессии и в базе не совпадают

Наиболее безопасный сценарий сохранения объекта - присоединить объект к сессии, затем сохранить в базе:
Код: java
1.
2.
object = session.merge(object);
session.update(object);


но это лишний select, поэтому, если мы уверены, что объекта нет в сессии, бывает выгоднее сразу detached состояние сохранять в кеш и базу:
Код: java
1.
2.
3.
session.update(object); 
// или
session.saveOrUpdate(object);


как-то так
...
Рейтинг: 0 / 0
Hibernate. merge update saveOrUpdate
    #38398177
DEVcoach
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ivanra,
...
Рейтинг: 0 / 0
Hibernate. merge update saveOrUpdate
    #38398180
DEVcoach
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ivanra ,
Начали вы правильно - многие неправильно понимают сессию. Но дальнейшее объяснение настолько чудовищно неверно, что освежить в голове семантику операций нужно именно вам.

ivanraupdate и saveOrUpdate - 2 разных варианта синхронизации объекта, уже находящегося в сессии, с базой данныхНеверно. Эти операции предназначены для того, что бы синхронизировать объект, которого нет в сессии с этой самой сессией.

ivanraПопросту говоря, объект из кеша сохраняется в базу данных с использованием update-а или insert-aНеверно. Непосредственно при вызове update или saveOrUpdate запись в СУБД может происходить, а может и не происходить.

ivanraЕсть нюанс: если объекта не было в сессии (detached), то проверяется, а есть ли объект с таким же ключом в локальном кеше. Если есть, то выдается исключениеВерно

ivanraесли нет - пишется в базу и параллельно в кешНеверно. Пишется только в сессию (кэш). В базу запись пойдет при флаше.

ivanraПосле выполнения update и saveOrUpdate состояния объекта в сессии и в базе совпадаютНеверно. Почему - см. выше.

ivanramerge (присоединение) - "обратная" операцияНеверно. merge по семантике очень близок к update, они практически идентичны. Главное отличие: если вызвать update, и объект с таким идентификатором уже есть в сессии, то будет брошено исключение, а если вызвать merge - не будет, состояние из детачнутого объекта успешно перенесется в сессию.
...
Рейтинг: 0 / 0
Hibernate. merge update saveOrUpdate
    #38398190
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
DEVcoach,

у Вас столько замечаний....
не могли бы полностью написать ваше видение этих функций, а то так всё смешалось.

Ну и расщифруйте пожалуйста слово синхронизировать в контексте использования.
==========
Я заметил, что при merge() сразу что-то в базу идёт, но если потом ещё update сделать у возвращаемого значения, то и ещё что-то в базу идёт.
...
Рейтинг: 0 / 0
Hibernate. merge update saveOrUpdate
    #38398195
DEVcoach
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
questioner ,
Нет смысла переписывать то, что достаточно просто и лаконично объяснено в пресловутой 10-й главе: http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/objectstate.html
Если буду конкретные вопросы после прочтения этого - обращайтесь.
...
Рейтинг: 0 / 0
Hibernate. merge update saveOrUpdate
    #38398205
ivanra
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
DEVcoach,
насчет flash замечание принимаю, но это другая история, да и не спрашивали про него.
А насчет остального - смотрите исходники, я написал как именно это работает, а не подстрочный перевод документации.
Можно даже и исходники не смотреть, просто включите трассировку:
merge() - в базу идут select-ы
save(), update(), saveOrUpdate() - в базу идут insert и update
...
Рейтинг: 0 / 0
Hibernate. merge update saveOrUpdate
    #38398213
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ivanra,
у меня после этого кода
Код: java
1.
session.merge(object);


состояние в базе меняется
...
Рейтинг: 0 / 0
Hibernate. merge update saveOrUpdate
    #38398223
DEVcoach
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ivanra ,
Цель автора - понять семантику работу этих методов. Вы объяснили ее неверно, я указал на ошибки:
1) Нет гарантий, что непосредственно после вызова update, saveOrUpdate или merge что-то тут же измениться в базе. Это крайне важно.
2) merge и update это не "обратные", а практически идентичные операции.
...
Рейтинг: 0 / 0
Hibernate. merge update saveOrUpdate
    #38398226
DEVcoach
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Кстати, вот еще одна ошибка:
Код: java
1.
2.
object = session.merge(object);
session.update(object);


Второй апдейт здесь не то, что не нужен, а он скорее всего даже эксепшн вызовет. Как только мы привязали объект к сессии, его не нужно потом явно сохранять. Например:
Код: java
1.
2.
employee = session.merge(employee);
employee.setName("NewName");

сохранит изменение имени в базу без явного вызова каких-либо методов сессии.
...
Рейтинг: 0 / 0
Hibernate. merge update saveOrUpdate
    #38398242
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Господа, Вы меня запутали))

Код: java
1.
2.
object = session.merge(object);
session.update(object);



могу только добавить, что у меня такой код не вызывает никаких эксепшенов(в моем конкретно случае).

я вот вижу только, что у merge всегда берется в расчёт возвращаемое значение а у апдейт нет...

ну и кстати
Код: java
1.
object = session.merge(object);


если оставить только это строчку у меня в базу записывается не то, что в объекте object, точнее не всё.

Если бы Вы объяснили это по такому принципу как

-состояние до
-входные параметры
-производимые манипуляции в функции
-выходные параметры
-состоянии после

было бы куда яснее.
...
Рейтинг: 0 / 0
Hibernate. merge update saveOrUpdate
    #38398494
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
questioner,
- Merge используется для отлова и исключения NonUniqueObjectException при деаттачнутых объектах.
- Как только закрыли сессию, хибер перестаёт ими управлять
- Для обратного присоединения к хиберу и есть Merge
- Возврат - объект с которым нужно работать дальше.
Сделай пример деаттачнутого объекта и логи вызова SQL.
Что гадать на кофейной гуще.
...
Рейтинг: 0 / 0
Hibernate. merge update saveOrUpdate
    #38398574
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Petro123questioner,
- Merge используется для отлова и исключения NonUniqueObjectException при деаттачнутых объектах.
- Как только закрыли сессию, хибер перестаёт ими управлять
- Для обратного присоединения к хиберу и есть Merge
- Возврат - объект с которым нужно работать дальше.
Сделай пример деаттачнутого объекта и логи вызова SQL.
Что гадать на кофейной гуще.

Собственно так и сделал, чтобы не быть голословным. Просто я смотрю даже у "гуру" мнения расходятся.

вот такой маппинг:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
@Entity
@Table(name = "prepod")
public class Prepod {

	private Long id;
	private String name;
	@Column
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	List<Student> students = new ArrayList<Student>();

	@ManyToMany(fetch=FetchType.EAGER)
	public List<Student> getStudents() {
		return students;
	}

	public void setStudents(List<Student> students) {
		this.students = students;
	}

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Column(name = "id")
	public Long getId() {
		return id;
	}

	public void setId(Long i) {
		id = i;
	}
}



Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
@Entity
@Table(name = "Student")
public class Student {

	private Long id;
	private String name;
	private Long age;
	private List<Prepod> prepods = new ArrayList<Prepod>();

	@ManyToMany(mappedBy = "students",fetch=FetchType.EAGER)
	public List<Prepod> getPrepods() {
		return prepods;
	}

	public void setPrepods(List<Prepod> prepods) {
		this.prepods = prepods;
	}

	public Student() {
		name = null;
	}

	public Student(Student s) {
		name = s.getName();
	}

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Column(name = "id")
	public Long getId() {
		return id;
	}

	@Column(name = "name")
	public String getName() {
		return name;
	}

	@Column(name = "age")
	public Long getAge() {
		return age;
	}

	public void setId(Long i) {
		id = i;
	}

	public void setName(String s) {
		name = s;
	}

	public void setAge(Long age) {
		this.age = age;
	}
}



вот такой код:

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
Session session = HibernateUtil.getSessionFactory().openSession();
		session.beginTransaction();
		Prepod prepod = (Prepod) session.get(Prepod.class, 1l);
		Student student = (Student) session.get(Student.class, 1l);
		

		
		session.getTransaction().commit();
		session.flush();
		session.close();
		
		List<Student> students = new ArrayList<Student>();
		students.add(student);

		List<Prepod> prepods = new ArrayList<Prepod>();
		prepods.add(prepod);

		prepod.setStudents(students);
		student.setPrepods(prepods);
	
	
	    session = HibernateUtil.getSessionFactory().openSession();
		session.beginTransaction();
	
		session.merge(student);
		session.merge(prepod);
	
		
		session.getTransaction().commit();
		session.close();



вот такой лог:

Код: java
1.
2.
3.
4.
5.
6.
 Hibernate: select prepod0_.id as id1_1_1_, prepod0_.name as name2_1_1_, students1_.prepods_id as prepods1_1_3_, student2_.id as students2_2_3_, student2_.id as id1_0_0_, student2_.age as age2_0_0_, student2_.name as name3_0_0_ from prepod prepod0_ left outer join prepod_Student students1_ on prepod0_.id=students1_.prepods_id left outer join Student student2_ on students1_.students_id=student2_.id where prepod0_.id=?
Hibernate: select student0_.id as id1_0_1_, student0_.age as age2_0_1_, student0_.name as name3_0_1_, prepods1_.students_id as students2_0_3_, prepod2_.id as prepods1_2_3_, prepod2_.id as id1_1_0_, prepod2_.name as name2_1_0_ from Student student0_ left outer join prepod_Student prepods1_ on student0_.id=prepods1_.students_id left outer join prepod prepod2_ on prepods1_.prepods_id=prepod2_.id where student0_.id=?
Hibernate: select student0_.id as id1_0_0_, student0_.age as age2_0_0_, student0_.name as name3_0_0_ from Student student0_ where student0_.id=?
Hibernate: select prepods0_.students_id as students2_0_1_, prepods0_.prepods_id as prepods1_2_1_, prepod1_.id as id1_1_0_, prepod1_.name as name2_1_0_ from prepod_Student prepods0_ inner join prepod prepod1_ on prepods0_.prepods_id=prepod1_.id where prepods0_.students_id=?
Hibernate: select prepod0_.id as id1_1_1_, prepod0_.name as name2_1_1_, students1_.prepods_id as prepods1_1_3_, student2_.id as students2_2_3_, student2_.id as id1_0_0_, student2_.age as age2_0_0_, student2_.name as name3_0_0_ from prepod prepod0_ left outer join prepod_Student students1_ on prepod0_.id=students1_.prepods_id left outer join Student student2_ on students1_.students_id=student2_.id where prepod0_.id=?
Hibernate: insert into prepod_Student (prepods_id, students_id) values (?, ?)




Ну это к слову, что в базу пишется в базу после merge()

Ну и про присоединение детачнутых объектов я согласен.
Код: java
1.
2.
object = session.merge(object);
session.update(object);



Так пишешь и всё работает.

Но как то я пока целостной картины понять не могу как это всё происходит.
...
Рейтинг: 0 / 0
Hibernate. merge update saveOrUpdate
    #38398586
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
если конкретнее сформулировать вопрос:
почему после merge() иногда что-то в базу идёт подобное апдейту, но результат
Код: java
1.
session.merge(object);


не равен(как минимум не всегда)
Код: java
1.
2.
object = session.merge(object);
session.update(object);
...
Рейтинг: 0 / 0
Hibernate. merge update saveOrUpdate
    #38398594
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
questioner
Код: java
1.
2.
object2 = session.merge(object1);
session.update(object2);
...
Рейтинг: 0 / 0
Hibernate. merge update saveOrUpdate
    #38398599
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
questionerПросто я смотрю даже у "гуру" мнения расходятся.
просто отсоединять объекты - лишний геморрой.
...
Рейтинг: 0 / 0
Hibernate. merge update saveOrUpdate
    #38398615
cdtyjv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
questioner ,
Стоп, а что вас не устраивает то в merge? Вы уже неоднократно упоминали, что у вас сохранилось "не все". Вопрос такой: что именно не сохранилось?

В приведенном вами коде все четко: у вас есть many-to-many отношение, вы добавили связь студен-препод, эта связь сохранилась в СУБД, все корректно и ожидаемо.
...
Рейтинг: 0 / 0
Hibernate. merge update saveOrUpdate
    #38398625
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
cdtyjv questioner ,
Стоп, а что вас не устраивает то в merge? Вы уже неоднократно упоминали, что у вас сохранилось "не все". Вопрос такой: что именно не сохранилось?

В приведенном вами коде все четко: у вас есть many-to-many отношение, вы добавили связь студен-препод, эта связь сохранилась в СУБД, все корректно и ожидаемо.

Иногда, чтобы добиться такого результат надо писать конструкцию вида:
Код: java
1.
2.
object = session.merge(object);
session.update(object);



непонятно когда надо, а когда нет.
...
Рейтинг: 0 / 0
Hibernate. merge update saveOrUpdate
    #38398629
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
questioner,

Код: java
1.
2.
object1 = session.merge(object);
session.update(object1);



для пущей понятности лучше даже так напишу
...
Рейтинг: 0 / 0
Hibernate. merge update saveOrUpdate
    #38398644
cdtyjv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
questioner ,
Так не пойдет. Вы сейчас привели пример, когда все работает без update, как то и должно быть. Если у вас что-то не работает, то приведите конкретный пример.
Корректную семантику этих операций я вам уже объяснил, ссылку на документацию дал. Я продолжаю настаивать на том, что merge + update это глупость.
...
Рейтинг: 0 / 0
Hibernate. merge update saveOrUpdate
    #38398689
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
cdtyjv questioner ,
Так не пойдет. Вы сейчас привели пример, когда все работает без update, как то и должно быть. Если у вас что-то не работает, то приведите конкретный пример.
Корректную семантику этих операций я вам уже объяснил, ссылку на документацию дал. Я продолжаю настаивать на том, что merge + update это глупость.
Вынужден с Вами согласиться. Просто мне казалось вчера, на проекте посложнее, что это влияло. В общем если выловлю различие - напишу.

То есть к merge стоит относиться так - "хибернейт сохрани в базу именно то, что аргумент у merge - он правильный, если есть другие в сессии инстансы - забей на них" ?
ну и что же всё таки он тогда возвращает....и зачем?
...
Рейтинг: 0 / 0
Hibernate. merge update saveOrUpdate
    #38398701
ivanra
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
questioner,
повторяю, вся работа идет с кешем, и состояние кеша записывается в базу во время session.flush().
Причем даже не обязательно вызывать session.flush(), поскольку по умолчанию flushMode сессии равен FlushMode.AUTO, и, например, при коммите транзакции (session.getTransaction().commit();) кеш предварительно будет записан.
А насчет merge() и update() DEVcoach прав в том смысле, что для кеша это очень похожие операции, но для базы они - разные.

update() - объект сохраняется в сессию и "планируется" операция sql update во время flush()
merge() - объект ищется в сессии, если нет - загружается из базы (немедленный sql select), обновляется полями detached инстанса, и далее все то же самое что и в update().

И в том и другом случае планируется sql update, но не факт, что он будет выполнен (например, при FlushMode.MANUAL забыли сделать flush()). Но для merge() обязательно выполняется sql select, при любом FlushMode.

В принципе, получается что достаточно делать
Код: java
1.
object = session.merge(object);


Но но в некоторых случаях у меня это не работало (при работе с коллекциями и транзитивными связями), а при заключительном update() - заработало
Код: java
1.
2.
3.
object = session.merge(object);
// что-то делаем с коллекциями объекта object
session.update(object);
...
Рейтинг: 0 / 0
Hibernate. merge update saveOrUpdate
    #38398715
cdtyjv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
questionerТо есть к merge стоит относиться так - "хибернейт сохрани в базу именно то, что аргумент у merge - он правильный, если есть другие в сессии инстансы - забей на них" ?
ну и что же всё таки он тогда возвращает....и зачем?Нет, не так. Еще раз: до тех пор, пока не был вызван флаш (руками, или автоматически по какой-то причине), ни один метод Хибернейта не гарантирует вам, что что-то будет сохранено в базу . Поймите, сессия - это кэш, в котором хранится информация об изменениях определенных объектов. И этот кэш синхронизируется с базой только по флашу. А пока флаша нет, все изменения храняться исключительно в памяти.

Метод update говорит Хиберу:
1) Проверь, есть ли у тебя объект с таким ID в сессии.
2) Если нет, то загрузи этот объект из базы в память, а потом перенеси значения полей из объекта-аргумент в тот объект, который загрузил.
3) Если есть - брось эксепшн.
Точка. Никакого сохранения в базу нет.

Метод merge говорит Хиберу:
1) Проверь, есть ли у тебя объект с таким ID в сессии.
2) Если нет, то загрузи этот объект из базы в память, а потом перенеси значения полей из объекта-аргумента в тот объект, который загрузил (сесионный объект).
3) Если есть, то просто перенеси состояние из объекта-аргумента в сессионный объект.
4) Верни сессионный объект.
Точка. Никакого сохранения в базу нет.

Вот один пример использования merge, корректный:
Код: java
1.
2.
3.
4.
5.
6.
7.
session.beginTransaction();
	
Student student0 = session.merge(student);
		
student0.setName("Ivan");

session.getTransaction().commit();

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

А вот некорректный пример:
Код: java
1.
2.
3.
4.
5.
6.
7.
session.beginTransaction();
	
session.merge(student);
		
student.setName("Ivan");

session.getTransaction().commit();

Тут я изменил имя у несессионного объекта. А потому это изменение не сохранится базу.

Вы почему-то упорно не хотите читать документацию Хибера. Там это в десятки раз лучше разжевано, чем я вам сейчас объясняю. И уж точно в документации нет ошибок.
...
Рейтинг: 0 / 0
Hibernate. merge update saveOrUpdate
    #38398722
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cdtyjv3) Если есть - брось эксепшн.
+1
NonUniqueObjectException
...
Рейтинг: 0 / 0
Hibernate. merge update saveOrUpdate
    #38398727
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ivanra,

авторmerge() - объект ищется в сессии, если нет - загружается из базы (немедленный sql select), обновляется полями detached инстанса, и далее все то же самое что и в update().

непонятно где вы у if скобки ставите)

1. объект в сессии:
Если есть, то данные из аргумента merge() копируются в персистентный объект.
2.объект не в сессии:
объект добавляется в сессию из базы иавтор данные из аргумента merge() копируются в персистентный объект
3. делается update в терминах sql

Я так понял. это правильно?


ну и с возвращаемым значением хотелось бы таки разобраться - оно же вроде как персистентное. не?
...
Рейтинг: 0 / 0
25 сообщений из 31, страница 1 из 2
Форумы / Java [игнор отключен] [закрыт для гостей] / Hibernate. merge update saveOrUpdate
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]