Tutorials  /  JavaScript

Hibernate Session: Merge, Update, Save, SaveOrUpdate, Persist Example

Ccentron Redaktion · December 2024 ·7 min read ·JavaScript, Tutorial

Hibernate Session is the interface between java application and hibernate framework. Today we will look into Session important methods for saving and updating data in tables - save, saveOrUpdate, persist, update and merge.

The Hibernate Session

Hibernate Session merge, persist, save, saveOrUpdate methods examples

VM

Matching infrastructure at centron

Node applications need somewhere to run: ccloud³ VMs with full root access from €3.12 per month – or as a managed server if you would rather not run it yourself. Rent a cloud server →

Hibernate Session save

As the method name suggests, hibernate save() can be used to save entity to database. We can invoke this method outside a transaction, that’s why I don’t like this method to save data. If we use this without transaction and we have cascading between entities, then only the primary entity gets saved unless we flush the session. For our testing purposes we have two entity beans - Employee and Address.

Go
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 methods

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

}
Go
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 methods

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

Here is a simple hibernate program where we are invoking save() method in different cases.

Go
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) {
		
		// Prep Work
		SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
		
		//save example - without transaction
		Session session = sessionFactory.openSession();
		Employee emp = getTestEmployee();
		long id = (Long) session.save(emp);
		System.out.println("1. Employee save called without transaction,*****");
		
		//save example - with transaction
		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,3. Before committing save transaction");
		tx1.commit();
		System.out.println("4. After committing save transaction");
		System.out.println("*****");
		
		//save example - existing row in table
		Session session6 = sessionFactory.openSession();
		Transaction tx6 = session6.beginTransaction();
		Employee emp6 =  (Employee) session6.load(Employee.class, new Long(20));
		
		//update some data
		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,6. Before committing save transaction");
		tx6.commit();
		System.out.println("7. After committing save transaction");
		System.out.println("*****");
		
		// Close resources
		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;
	}
}

When we execute above program, it produces following output.

Code
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
*****

Few important points that we can confirm from above output are:

  • We should avoid save outside transaction boundary, otherwise mapped entities will not be saved causing data inconsistency. It’s very normal to forget flushing the session because it doesn’t throw any exception or warnings.
  • Hibernate save method returns the generated id immediately, this is possible because primary object is saved as soon as save method is invoked.
  • If there are other objects mapped from the primary object, they get saved at the time of committing transaction or when we flush the session.
  • For objects that are in persistent state, save updates the data through update query. Notice that it happens when transaction is committed. If there are no changes in the object, there won’t be any query fired. If you will run above program multiple times, you will notice that update queries are not fired next time because there is no change in the column values.
  • Hibernate save loads entity object to persistent context. If you update the object properties after the save call but before the transaction is committed, it will be saved into the database.

Hibernate Persist

Hibernate persist is similar to save (with transaction) and it adds the entity object to the persistent context, so any further changes are tracked. If the object properties are changed before the transaction is committed or session is flushed, it will also be saved into the database. Second difference is that we can use persist() method only within the boundary of a transaction, so it’s safe and takes care of any cascaded objects. Finally, persist doesn’t return anything so we need to use the persisted object to get the generated identifier value. Let’s look at hibernate persist with a simple program.

Go
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) {
		
		// Prep Work
		SessionFactory sessionFactory = HibernateUtil.getSessionFactory();	
		
		//persist example - with transaction
		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,, address*****");
		
		// Close resources
		sessionFactory.close();

	}
}

Output produced by above code is:

Code
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=?
*****

Notice that first employee object is inserted, then at the time of transaction commit, update query is executed to update the name value. Also mapped object address is saved into database.

Hibernate saveOrUpdate

Hibernate saveOrUpdate results into insert or update queries based on the provided data. If the data is present in the database, update query is executed. We can use saveOrUpdate() without transaction also, but again you will face the issues with mapped objects not getting saved if session is not flushed. Hibernate saveOrUpdate adds the entity object to persistent context and tracks any further changes. Any further changes are saved at the time of committing transaction, like persist.

Go
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) {
		
		// Prep Work
		SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
		
		//saveOrUpdate example - without transaction
		Session session5 = sessionFactory.openSession();
		Employee emp5 = HibernateSaveExample.getTestEmployee();
		session5.saveOrUpdate(emp5);
		System.out.println("*****");
		
		//saveOrUpdate example - with transaction
		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("*****");

		// Close resources
		sessionFactory.close();

	}
}

Above program produces following output.

Code
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
*****

Notice that without transaction, only Employee gets saved and address information is lost. With transaction, employee object is tracked for any changes, that’s why in last call there is no update in Employee table even though the value was changed in between, the final value remains the same.

Hibernate update

Hibernate update should be used where we know that we are only updating the entity information. This operation adds the entity object to persistent context, and further changes are tracked and saved when the transaction is committed. Let’s check this behavior with a simple program.

Go
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) {

		// Prep Work
		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();

		// update example
		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");

		// Close resources
		sessionFactory.close();

	}
}

When we execute above program for the first time, we get the following output.

Code
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

On further execution, we get the following output.

Code
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

Notice that there are no updates fired after the first execution because there are no updates in values. Also, notice the employee name is “Final updated name” that we set after invoking the update() method. This confirms that Hibernate was tracking the object for any changes, and at the time of committing the transaction, this value got saved.

Hibernate Merge

Hibernate merge can be used to update existing values; however, this method creates a copy from the passed entity object and returns it. The returned object is part of the persistent context and tracked for any changes, while the passed object is not tracked. This is the major difference with merge() from all other methods. Let’s look at this with a simple program.

Go
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) {

		// Prep Work
		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 example - data already present in tables
		 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");

		// Close resources
		sessionFactory.close();

	}
}

Output in the first execution is:

Code
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

In further execution, the output produced is:

Code
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

Notice that the entity object returned by merge() is different from the passed entity. Also, notice that in further execution, the name is “Kumar”; this is because the returned object is tracked for any changes. That’s all for Hibernate Session save and update methods. I hope that the examples above will help you in clarifying any doubts you have.

Jetzt 200 € Guthaben sichern

Testen Sie Ihr Setup auf ccloud³

Registrieren Sie sich in der ccloud³ und erhalten Sie 200 € Startguthaben für Ihr Projekt – z. B. für eine PostgreSQL-VM mit automatischen Backups.

centron Redaktion Technische Redaktion

Das Redaktionsteam von centron schreibt Anleitungen aus dem Betriebsalltag: getestet auf unserer eigenen Plattform, betrieben im Rechenzentrum in Hallstadt bei Bamberg.

Kategorie JavaScript
Teilen
Noch offene Fragen?

Unser Team hilft Ihnen bei Ihrem konkreten Setup weiter – von Menschen, die die Plattform selbst betreiben.

War dieses Tutorial hilfreich?

Ihre Antwort wird anonym gespeichert und hilft uns, die Tutorials zu verbessern.

Kommentare

Noch keine Kommentare – stellen Sie die erste Frage zu diesem Tutorial.

Zum Kommentieren anmelden

Kommentare stehen centron-Kunden offen. Melden Sie sich in Ihrem Konto an, um eine Frage zu diesem Tutorial zu stellen.

Weiterlesen

Das könnte Sie auch interessieren

Jetzt kostenlos anfangen

Melden Sie sich an und erhalten Sie in den ersten 60 Tagen ein Guthaben von 200 € bei centron.

Dieses Werbeangebot gilt nur für neue Konten. Angebot ausschließlich für Gewerbetreibende.

Jetzt loslegen Sales kontaktieren