Hibernate Session merge, update, save, saveOrUpdate, persist Beispiel

Hibernate-Sitzung ist die Schnittstelle zwischen Java-Anwendung und Hibernate-Framework. Heute werden wir uns die wichtigen Methoden der Sitzung zum Speichern und Aktualisieren von Daten in Tabellen ansehen – save, saveOrUpdate, persist, update und merge.

Hibernate-Sitzung

Hibernate-Sitzung speichern

Wie der Methodenname vermuten lässt, kann hibernate save() verwendet werden, um eine Entität in der Datenbank zu speichern. Wir können diese Methode außerhalb einer Transaktion aufrufen, deshalb mag ich diese Methode nicht zum Speichern von Daten. Wenn wir dies ohne Transaktion verwenden und zwischen Entitäten Kaskadierung besteht, wird nur die Primärentität gespeichert es sei denn, wir leeren die Sitzung. Für unsere Testzwecke haben wir zwei Entitäts-Beans – Employee und Address.

package com.journaldev.hibernate.model;

import javax.persistence.Access;
import javax.persistence.AccessType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.Table;

import org.hibernate.annotations.Cascade;

@Entity
@Table(name = "EMPLOYEE")
@Access(value=AccessType.FIELD)
public class Employee {

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Column(name = "emp_id")
	private long id;

	@Column(name = "emp_name")
	private String name;

	@Column(name = "emp_salary")
	private double salary;

	@OneToOne(mappedBy = "employee")
	@Cascade(value = org.hibernate.annotations.CascadeType.ALL)
	private Address address;

        // Getter-Setter-Methoden

	@Override
	public String toString() {
		return "Id= " + id + ", Name= " + name + ", Salary= " + salary
				+ ", {Address= " + address + "}";
	}

}
package com.journaldev.hibernate.model;

import javax.persistence.Access;
import javax.persistence.AccessType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table;

import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Parameter;

@Entity
@Table(name = "ADDRESS")
@Access(value=AccessType.FIELD)
public class Address {

	@Id
	@Column(name = "emp_id", unique = true, nullable = false)
	@GeneratedValue(generator = "gen")
	@GenericGenerator(name = "gen", strategy = "foreign", parameters = { @Parameter(name = "property", value = "employee") })
	private long id;

	@Column(name = "address_line1")
	private String addressLine1;

	@Column(name = "zipcode")
	private String zipcode;

	@Column(name = "city")
	private String city;

	@OneToOne
	@PrimaryKeyJoinColumn
	private Employee employee;

        // Getter-Setter-Methoden

	@Override
	public String toString() {
		return "AddressLine1= " + addressLine1 + ", City=" + city
				+ ", Zipcode=" + zipcode;
	}
}

Hier ist ein einfaches Hibernate-Programm, in dem wir die Methode save() in verschiedenen Fällen aufrufen.

package com.journaldev.hibernate.main;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;

import com.journaldev.hibernate.model.Address;
import com.journaldev.hibernate.model.Employee;
import com.journaldev.hibernate.util.HibernateUtil;

public class HibernateSaveExample {

	public static void main(String[] args) {
		
		// Vorbereitungsarbeiten
		SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
		
		// Beispielspeicherung - ohne Transaktion
		Session session = sessionFactory.openSession();
		Employee emp = getTestEmployee();
		long id = (Long) session.save(emp);
		System.out.println("1. Employee save called without transaction, id="+id);
		session.flush(); //address will not get saved without this
		System.out.println("*****");
		
		// Beispielspeicherung - mit Transaktion
		Transaction tx1 = session.beginTransaction();
		Session session1 = sessionFactory.openSession();
		Employee emp1 = getTestEmployee();
		long id1 = (Long) session1.save(emp1);
		System.out.println("2. Employee save called with transaction, id="+id1);
		System.out.println("3. Before committing save transaction");
		tx1.commit();
		System.out.println("4. After committing save transaction");
		System.out.println("*****");
		
		// Beispielspeicherung - vorhandener Eintrag in der Tabelle
		Session session6 = sessionFactory.openSession();
		Transaction tx6 = session6.beginTransaction();
		Employee emp6 =  (Employee) session6.load(Employee.class, new Long(20));
		
		// Aktualisierung einiger Daten
		System.out.println("Employee Details="+emp6);
		emp6.setName("New Name");
		emp6.getAddress().setCity("New City");
		
		long id6 = (Long) session6.save(emp6);
		emp6.setName("New Name1"); // will get updated in database
		System.out.println("5. Employee save called with transaction, id="+id6);
		System.out.println("6. Before committing save transaction");
		tx6.commit();
		System.out.println("7. After committing save transaction");
		System.out.println("*****");
		
		// Ressourcen schließen
		sessionFactory.close();

	}

	public static Employee getTestEmployee() {
		Employee emp = new Employee();
		Address add = new Address();
		emp.setName("Test Emp");
		emp.setSalary(1000);
		add.setAddressLine1("Test address1");
		add.setCity("Test City");
		add.setZipcode("12121");
		emp.setAddress(add);
		add.setEmployee(emp);
		return emp;
	}
}

Wenn wir das obige Programm ausführen, erzeugt es folgende Ausgabe.

Hibernate: insert into EMPLOYEE (emp_name, emp_salary) values (?, ?)
1. Employee save called without transaction, id=149
Hibernate: insert into ADDRESS (address_line1, city, zipcode, emp_id) values (?, ?, ?, ?)
*****
Hibernate: insert into EMPLOYEE (emp_name, emp_salary) values (?, ?)
2. Employee save called with transaction, id=150
3. Before committing save transaction
Hibernate: insert into ADDRESS (address_line1, city, zipcode, emp_id) values (?, ?, ?, ?)
4. After committing save transaction
*****
Hibernate: select employee0_.emp_id as emp_id1_1_0_, employee0_.emp_name as emp_name2_1_0_, employee0_.emp_salary as emp_sala3_1_0_, address1_.emp_id as emp_id1_0_1_, address1_.address_line1 as address_2_0_1_, address1_.city as city3_0_1_, address1_.zipcode as zipcode4_0_1_ from EMPLOYEE employee0_ left outer join ADDRESS address1_ on employee0_.emp_id=address1_.emp_id where employee0_.emp_id=?
Employee Details=Id= 20, Name= Kumar1, Salary= 1000.0, {Address= AddressLine1= Test address1, City=Blr, Zipcode=12121}
5. Employee save called with transaction, id=20
6. Before committing save transaction
Hibernate: update EMPLOYEE set emp_name=?, emp_salary=? where emp_id=?
Hibernate: update ADDRESS set address_line1=?, city=?, zipcode=? where emp_id=?
7. After committing save transaction
*****

Einige wichtige Punkte, die wir aus der obigen Ausgabe bestätigen können, sind:

  • Wir sollten das Speichern außerhalb der Transaktionsgrenze vermeiden, da sonst zugeordnete Entitäten nicht gespeichert werden und Dateninkonsistenzen verursachen können. Es ist sehr normal, das Flushing der Sitzung zu vergessen, weil es keine Ausnahme oder Warnungen wirft.
  • Die Hibernate-Speichermethode gibt sofort die generierte ID zurück, dies ist möglich, weil das primäre Objekt sofort gespeichert wird, sobald die Speichermethode aufgerufen wird.
  • Wenn es andere Objekte gibt, die vom primären Objekt zugeordnet sind, werden sie beim Commit der Transaktion oder beim Flushing der Sitzung gespeichert.
  • Für Objekte im persistenten Zustand aktualisiert „save“ die Daten durch eine Aktualisierungsabfrage. Beachten Sie, dass dies beim Commit der Transaktion passiert. Wenn es keine Änderungen am Objekt gibt, wird keine Abfrage ausgeführt. Wenn Sie das obige Programm mehrmals ausführen, werden Sie feststellen, dass Aktualisierungsabfragen beim nächsten Mal nicht ausgeführt werden, weil sich die Spaltenwerte nicht geändert haben.
  • Die Hibernate-Speichermethode lädt das Entitätsobjekt in den persistenten Kontext. Wenn Sie die Objekteigenschaften nach dem Aufruf von „save“, aber vor dem Commit der Transaktion aktualisieren, werden sie in die Datenbank gespeichert.

Hibernate Persist

Hibernate persist ist ähnlich wie save (mit Transaktion) und fügt das Entitätsobjekt dem persistenten Kontext hinzu, sodass alle weiteren Änderungen verfolgt werden. Wenn die Objekteigenschaften vor dem Commit der Transaktion oder vor dem Flush der Session geändert werden, werden sie auch in die Datenbank gespeichert. Ein weiterer Unterschied besteht darin, dass wir die Methode persist() nur innerhalb des Rahmens einer Transaktion verwenden können. Daher ist sie sicher und kümmert sich um alle kaskadierten Objekte. Schließlich gibt persist nichts zurück, daher müssen wir das persistierte Objekt verwenden, um den generierten Identifikatorwert zu erhalten. Schauen wir uns Hibernate Persist anhand eines einfachen Programms an.

package com.journaldev.hibernate.main;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;

import com.journaldev.hibernate.model.Employee;
import com.journaldev.hibernate.util.HibernateUtil;

public class HibernatePersistExample {

	public static void main(String[] args) {
		
		// Vorbereitung
		SessionFactory sessionFactory = HibernateUtil.getSessionFactory();	
		
		// Persistenzbeispiel - mit Transaktion
		Session session2 = sessionFactory.openSession();
		Transaction tx2 = session2.beginTransaction();
		Employee emp2 = HibernateSaveExample.getTestEmployee();
		session2.persist(emp2);
		System.out.println("Persist called");
		emp2.setName("Kumar"); // will be updated in database too
		System.out.println("Employee Name updated");
		System.out.println("8. Employee persist called with transaction, id="+emp2.getId()+", address id="+emp2.getAddress().getId());
		tx2.commit();
		System.out.println("*****");
		
		// Ressourcen schließen
		sessionFactory.close();

	}

}

Ausgabe des obigen Codes:

Hibernate: insert into EMPLOYEE (emp_name, emp_salary) values (?, ?)
8. Employee persist called with transaction, id=158, address id=158
Hibernate: insert into ADDRESS (address_line1, city, zipcode, emp_id) values (?, ?, ?, ?)
Hibernate: update EMPLOYEE set emp_name=?, emp_salary=? where emp_id=?
*****

Beachten Sie, dass zuerst das erste Mitarbeiterobjekt eingefügt wird. Dann wird beim Commit der Transaktion die Update-Abfrage ausgeführt, um den Namenswert zu aktualisieren. Auch die Adresse des gemappten Objekts wird in die Datenbank gespeichert.

Hibernate saveOrUpdate

Hibernate saveOrUpdate führt je nach den bereitgestellten Daten zu Einfüge- oder Update-Abfragen. Wenn die Daten in der Datenbank vorhanden sind, wird die Update-Abfrage ausgeführt. Wir können saveOrUpdate() auch ohne Transaktion verwenden, aber auch hier können Probleme auftreten, wenn die zugeordneten Objekte nicht gespeichert werden, wenn die Sitzung nicht gespült wird. Hibernate saveOrUpdate fügt das Entitätsobjekt dem persistenten Kontext hinzu und verfolgt weitere Änderungen. Alle weiteren Änderungen werden zum Zeitpunkt des Commit der Transaktion gespeichert, ähnlich wie bei persist.

package com.journaldev.hibernate.main;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;

import com.journaldev.hibernate.model.Employee;
import com.journaldev.hibernate.util.HibernateUtil;

public class HibernateSaveOrUpdateExample {

	public static void main(String[] args) {
		
		// Vorbereitung
		SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
		
		// Beispiel für saveOrUpdate - ohne Transaktion
		Session session5 = sessionFactory.openSession();
		Employee emp5 = HibernateSaveExample.getTestEmployee();
		session5.saveOrUpdate(emp5);
		System.out.println("*****");
		
		// Beispiel für saveOrUpdate - mit Transaktion
		Session session3 = sessionFactory.openSession();
		Transaction tx3 = session3.beginTransaction();
		Employee emp3 = HibernateSaveExample.getTestEmployee();
		session3.saveOrUpdate(emp3);
		emp3.setName("Kumar"); //will be saved into DB
		System.out.println("9. Before committing saveOrUpdate transaction. Id="+emp3.getId());
		tx3.commit();
		System.out.println("10. After committing saveOrUpdate transaction");
		System.out.println("*****");
		
		
		Transaction tx4 = session3.beginTransaction();
		emp3.setName("Updated Test Name"); //Name changed
		emp3.getAddress().setCity("Updated City");
		session3.saveOrUpdate(emp3);
		emp3.setName("Kumar"); //again changed to previous value, so no Employee update
		System.out.println("11. Before committing saveOrUpdate transaction. Id="+emp3.getId());
		tx4.commit();
		System.out.println("12. After committing saveOrUpdate transaction");
		System.out.println("*****");

		// Ressourcen schließen
		sessionFactory.close();

	}
}

Das obige Programm erzeugt folgende Ausgabe.

Hibernate: insert into EMPLOYEE (emp_name, emp_salary) values (?, ?)
*****
Hibernate: insert into EMPLOYEE (emp_name, emp_salary) values (?, ?)
9. Before committing saveOrUpdate transaction. Id=166
Hibernate: insert into ADDRESS (address_line1, city, zipcode, emp_id) values (?, ?, ?, ?)
Hibernate: update EMPLOYEE set emp_name=?, emp_salary=? where emp_id=?
10. After committing saveOrUpdate transaction
*****
11. Before committing saveOrUpdate transaction. Id=166
Hibernate: update ADDRESS set address_line1=?, city=?, zipcode=? where emp_id=?
12. After committing saveOrUpdate transaction
*****

Beachten Sie, dass ohne Transaktion nur der Mitarbeiter gespeichert wird und die Adressinformationen verloren gehen. Mit Transaktion wird das Mitarbeiterobjekt auf Änderungen überwacht, deshalb gibt es im letzten Aufruf kein Update in der Mitarbeiter-Tabelle, obwohl der Wert zwischendurch geändert wurde, bleibt der endgültige Wert gleich.

Hibernate update

Hibernate update sollte verwendet werden, wenn wir wissen, dass wir nur die Entitätsinformationen aktualisieren. Diese Operation fügt das Entitätsobjekt dem persistenten Kontext hinzu, und weitere Änderungen werden verfolgt und gespeichert, wenn die Transaktion abgeschlossen ist. Überprüfen wir dieses Verhalten mit einem einfachen Programm.

package com.journaldev.hibernate.main;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;

import com.journaldev.hibernate.model.Employee;
import com.journaldev.hibernate.util.HibernateUtil;

public class HibernateUpdateExample {

	public static void main(String[] args) {

		// Vorbereitungsarbeiten
		SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
		Session session = sessionFactory.openSession();
		Transaction tx = session.beginTransaction();
		Employee emp = (Employee) session.load(Employee.class, new Long(101));
		System.out.println("Employee object loaded. " + emp);
		tx.commit();

		// Beispiel aktualisieren
		emp.setName("Updated name");
		emp.getAddress().setCity("Bangalore");
		Transaction tx7 = session.beginTransaction();
		session.update(emp);
		emp.setName("Final updated name");
		System.out.println("13. Before committing update transaction");
		tx7.commit();
		System.out.println("14. After committing update transaction");

		// Ressourcen schließen
		sessionFactory.close();

	}

}

Wenn wir das obige Programm zum ersten Mal ausführen, erhalten wir folgende Ausgabe.

Hibernate: select employee0_.emp_id as emp_id1_1_0_, employee0_.emp_name as emp_name2_1_0_, employee0_.emp_salary as emp_sala3_1_0_, address1_.emp_id as emp_id1_0_1_, address1_.address_line1 as address_2_0_1_, address1_.city as city3_0_1_, address1_.zipcode as zipcode4_0_1_ from EMPLOYEE employee0_ left outer join ADDRESS address1_ on employee0_.emp_id=address1_.emp_id where employee0_.emp_id=?
Employee object loaded. Id= 101, Name= Test Emp, Salary= 1000.0, {Address= AddressLine1= Test address1, City=Test City, Zipcode=12121}
13. Before committing update transaction
Hibernate: update EMPLOYEE set emp_name=?, emp_salary=? where emp_id=?
Hibernate: update ADDRESS set address_line1=?, city=?, zipcode=? where emp_id=?
14. After committing update transaction

Bei weiteren Ausführungen erhalten wir folgende Ausgabe.

Hibernate: select employee0_.emp_id as emp_id1_1_0_, employee0_.emp_name as emp_name2_1_0_, employee0_.emp_salary as emp_sala3_1_0_, address1_.emp_id as emp_id1_0_1_, address1_.address_line1 as address_2_0_1_, address1_.city as city3_0_1_, address1_.zipcode as zipcode4_0_1_ from EMPLOYEE employee0_ left outer join ADDRESS address1_ on employee0_.emp_id=address1_.emp_id where employee0_.emp_id=?
Employee object loaded. Id= 101, Name= Final updated name, Salary= 1000.0, {Address= AddressLine1= Test address1, City=Bangalore, Zipcode=12121}
13. Before committing update transaction
14. After committing update transaction

Beachten Sie, dass nach der ersten Ausführung keine Updates ausgelöst werden, weil keine Änderungen vorliegen. Beachten Sie auch, dass der Mitarbeitername „Final updated name“ ist, den wir nach dem Aufruf der update() -Methode festgelegt haben. Dies bestätigt, dass Hibernate das Objekt verfolgt hat, um Änderungen festzustellen, und zum Zeitpunkt der Transaktionsbestätigung dieser Wert gespeichert wurde.

Hibernate Merge

Hibernate Merge kann verwendet werden, um vorhandene Werte zu aktualisieren. Diese Methode erstellt jedoch eine Kopie des übergebenen Entitätsobjekts und gibt es zurück. Das zurückgegebene Objekt ist Teil des persistenten Kontexts und wird auf Änderungen überwacht, das übergebene Objekt wird nicht überwacht. Dies ist der Hauptunterschied zu merge() von allen anderen Methoden. Schauen wir uns das mit einem einfachen Programm an.

package com.journaldev.hibernate.main;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;

import com.journaldev.hibernate.model.Employee;
import com.journaldev.hibernate.util.HibernateUtil;

public class HibernateMergeExample {

	public static void main(String[] args) {

		// Vorbereitungsarbeiten
		SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
		Session session = sessionFactory.openSession();
		Transaction tx = session.beginTransaction();
		Employee emp = (Employee) session.load(Employee.class, new Long(101));
		System.out.println("Employee object loaded. " + emp);
		tx.commit();

		 // Merge-Beispiel - Daten bereits in Tabellen vorhanden
		 emp.setSalary(25000);
		 Transaction tx8 = session.beginTransaction();
		 Employee emp4 = (Employee) session.merge(emp);
		 System.out.println(emp4 == emp); // returns false
		 emp.setName("Test");
		 emp4.setName("Kumar");
		 System.out.println("15. Before committing merge transaction");
		 tx8.commit();
		 System.out.println("16. After committing merge transaction");

		// Ressourcen schließen
		sessionFactory.close();

	}

}

Die Ausgabe bei der ersten Ausführung lautet:

Hibernate: select employee0_.emp_id as emp_id1_1_0_, employee0_.emp_name as emp_name2_1_0_, employee0_.emp_salary as emp_sala3_1_0_, address1_.emp_id as emp_id1_0_1_, address1_.address_line1 as address_2_0_1_, address1_.city as city3_0_1_, address1_.zipcode as zipcode4_0_1_ from EMPLOYEE employee0_ left outer join ADDRESS address1_ on employee0_.emp_id=address1_.emp_id where employee0_.emp_id=?
Employee object loaded. Id= 101, Name= Final updated name, Salary= 1000.0, {Address= AddressLine1= Test address1, City=Bangalore, Zipcode=12121}
false
15. Before committing merge transaction
Hibernate: update EMPLOYEE set emp_name=?, emp_salary=? where emp_id=?
16. After committing merge transaction

Bei weiteren Ausführungen wird folgende Ausgabe erzeugt:

Hibernate: select employee0_.emp_id as emp_id1_1_0_, employee0_.emp_name as emp_name2_1_0_, employee0_.emp_salary as emp_sala3_1_0_, address1_.emp_id as emp_id1_0_1_, address1_.address_line1 as address_2_0_1_, address1_.city as city3_0_1_, address1_.zipcode as zipcode4_0_1_ from EMPLOYEE employee0_ left outer join ADDRESS address1_ on employee0_.emp_id=address1_.emp_id where employee0_.emp_id=?
Employee object loaded. Id= 101, Name= Kumar, Salary= 25000.0, {Address= AddressLine1= Test address1, City=Bangalore, Zipcode=12121}
false
15. Before committing merge transaction
16. After committing merge transaction

Beachten Sie, dass das von merge() zurückgegebene Entitätsobjekt sich vom übergebenen Objekt unterscheidet. Beachten Sie auch, dass im weiteren Verlauf die Bezeichnung „Kumar“ ist, dies liegt daran, dass das zurückgegebene Objekt auf Änderungen überwacht wird. Das ist alles für die Hibernate-Sitzung save und update Methoden, ich hoffe, die obigen Beispiele werden Ihnen helfen, etwaige Zweifel zu klären.

Source:
https://www.digitalocean.com/community/tutorials/hibernate-session-merge-vs-update-save-saveorupdate-persist-example