Home » Hibernate » Difference between hibernate save(),saveOrUpdate() and persist() methods

Difference between hibernate save(),saveOrUpdate() and persist() methods

What is difference between save and saveOrUpdate or Difference between save and persist are most important question in any Hibernate interview.

Session interface in Hibernate provides a couple of methods to move an object from new or transient state to persistent state e.g. save(), saveOrUpdate() and persist() are used to store an object into the database, but there are some significant differences between them.

Difference between save() and saveOrUpdate() in Hibernate

  • Main difference between save and saveOrUpdate method is that save() generates a new identifier and INSERT record into database while saveOrUpdate can either INSERT or UPDATE based upon existence of record.save() method will fail if the primary key is already persistent i.e. object already exists in the database. This is why, you should only call save() with an absolutely new object which doesn't have any database identifier. Calling save() method on the detached object will throw exception.
  • The Session.save() method does an INSERT to store the object into the database and return the identifier generated by the database.On the other hand, saveOrUpdate() can do INSERT or UPDATE depending upon whether object exists in database or not. saveOrUpdate is more flexible in terms of use but it involves an extra processing to find out whether record already exists in table or not.saveOrUpdate does a select first to determine if it needs to do an insert or an update. It will insert data if primary key not exist otherwise it will update data.
  • Another key difference between save() and saveOrUpdate() method is that save() method is used to bring a transient object to persistent state but saveOurUpdate() can bring both transient (new) and detached (existing) object into persistent state. It is often used to re-attach a detached object into Session.

Summary:

save() method saves records into database by INSERT SQL query, Generates a new identifier and return the Serializable identifier back. On the other hand saveOrUpdate() method either INSERT or UPDATE based upon existence of object in database. If persistence object already exists in database then UPDATE SQL will execute and if there is no corresponding object in database than INSERT will run.

Example:

Below is example of both save and saveOrUpdate() method. You can easily identify the difference in generated SQL statement in the console.

Entity Class


package com.jwt.hibernate;

import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "STUDENT")
public class Student {
	private long id;
	private String name;
	private String degree;
	private String roll;
	private String phone;

	@Id
	public long getId() {
		return id;
	}

	public void setId(long id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

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

	public String getDegree() {
		return degree;
	}

	public void setDegree(String degree) {
		this.degree = degree;
	}

	public String getRoll() {
		return roll;
	}

	public void setRoll(String roll) {
		this.roll = roll;
	}

	public String getPhone() {
		return phone;
	}

	public void setPhone(String phone) {
		this.phone = phone;
	}

}

Configuration File


<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
	<session-factory>
		<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
		<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernate</property>
		<property name="hibernate.connection.username">root</property>
		<property name="hibernate.connection.password">mukesh</property>
		<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
		<property name="show_sql">true</property>
		<property name="format_sql">true</property>
		<property name="hbm2ddl.auto">create </property>
		<mapping class="com.jwt.hibernate.Student" />
	</session-factory>
</hibernate-configuration>

save() method


package com.jwt.hibernate.test;

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

import com.jwt.hibernate.Student;

public class SaveTest {
	public static void main(String[] args) {
		Session session = new AnnotationConfiguration().configure()
				.buildSessionFactory().openSession();

		Transaction t = session.beginTransaction();
		Student student = new Student();
		student.setId(1);
		student.setName("Mukesh");
		student.setRoll("101");
		student.setDegree("B.E");
		student.setPhone("99999");
		Long studentId = (Long) session.save(student);
		t.commit();
		session.close();
		System.out.println(" Identifier : " + studentId);
		System.out.println("successfully saved");

	}
}

Output:


log4j:WARN No appenders could be found for logger (org.hibernate.type.BasicTypeRegistry).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
Hibernate: 
    insert 
    into
        STUDENT
        (degree, name, phone, roll, id) 
    values
        (?, ?, ?, ?, ?)
 Identifier : 1
successfully saved

Look at the above output carefully, save() method first generates identifier and then inserts data into database. We printed the value of the identifier after saving the object. You can clearly see the insert query in the console output.

saveOrUpdate() method


package com.jwt.hibernate.test;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.cfg.AnnotationConfiguration;

import com.jwt.hibernate.Student;

public class SaveOrUpdateTest {
	public static void main(String[] args) {
		Session session = new AnnotationConfiguration().configure()
				.buildSessionFactory().openSession();

		Transaction t = session.beginTransaction();
		Student student = new Student();
		student.setId(101);
		student.setName("Ravi");
		student.setRoll("10");
		student.setDegree("B.E");
		student.setPhone("8888");
		session.saveOrUpdate(student);
		t.commit();
		session.close();
		System.out.println("successfully saved");

}
}

Output:


log4j:WARN No appenders could be found for logger (org.hibernate.type.BasicTypeRegistry).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
Hibernate: 
    select
        student_.id,
        student_.degree as degree0_,
        student_.name as name0_,
        student_.phone as phone0_,
        student_.roll as roll0_ 
    from
        STUDENT student_ 
    where
        student_.id=?
Hibernate: 
    insert 
    into
        STUDENT
        (degree, name, phone, roll, id) 
    values
        (?, ?, ?, ?, ?)
successfully saved

The above output shows that the entity with specified identifier does not exist in database by running select query. So it applied insert query to persist data.

Now check the output for such situation where entity for the given identifier is already exist in database. In the above example just change the name and phone number. Modified code is given below.


package com.jwt.hibernate.test;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.cfg.AnnotationConfiguration;

import com.jwt.hibernate.Student;

public class SaveOrUpdateTest {
	public static void main(String[] args) {
		Session session = new AnnotationConfiguration().configure()
				.buildSessionFactory().openSession();

		Transaction t = session.beginTransaction();
		Student student = new Student();
		student.setId(101);
		student.setName("Mukesh");
		student.setRoll("10");
		student.setDegree("B.E");
		student.setPhone("9999");
		session.saveOrUpdate(student);
		t.commit();
		session.close();
		System.out.println("successfully saved");

}
}

Output:


log4j:WARN No appenders could be found for logger (org.hibernate.type.BasicTypeRegistry).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
Hibernate: 
    select
        student_.id,
        student_.degree as degree0_,
        student_.name as name0_,
        student_.phone as phone0_,
        student_.roll as roll0_ 
    from
        STUDENT student_ 
    where
        student_.id=?
Hibernate: 
    update
        STUDENT 
    set
        degree=?,
        name=?,
        phone=?,
        roll=? 
    where
        id=?
successfully saved

In the above output, first select query runs to check existence of data for given identifier and since data is there, so update query runs to update data.


Difference between save() and persist() methods

  • Main difference of save() and persist() is return type of the save() method is java.io.Serializable it returns the generated identity value whereas the return type of persist method is void i.e, it will not return any value.persist() is similar to Session.save() i.e. it is used to move a transient object to the persistent state by storing it into the database but it doesn't return the database identifier.
  • Another key difference is Persist method can be used only within the boundary of a transaction whereas save method can be used inside or outside the transaction boundaries.persist() method guarantees that it will not execute an INSERT statement if it is called outside of transaction boundaries. But in the case of save() INSERT happens immediately, no matter if you are inside or outside of a transaction. This is not good in a long-running conversation with an extended Session/persistence context.

For example:


System.out.println(session.save(student));

Above code will print the generated primary key because save() method will return the generated identifier, but the below line of code will throw a compile time error because persist() method return type is void.


System.out.println(session.persist(student));

Previous Next Article

comments powered by Disqus