1

I am working on an application that is built using Spring MVC, it is using Hibernate to interact with the data store. While I was trying to implement delete functionality, I figured out that there are multiple ways to implement session.delete(). Out of all, I am confused which one out of the following two is the better way(more specifically, standard way) to implement Hibernate seesion.delete().

As this API call would be turned into micro-service in the future stage, I guess it is the standard way to get userId from the web and not the entire object.

Method 1:

@Transactional    
public void deleteUser(User user) {
    sessionFactory.getCurrentSession().delete(user);
}

Method 2:

@Transactional
public void deleteUser(int userId) {
    Query q = session.createQuery("delete User where id = :userId");
    query.setParameter("userId", userId);
    q.executeUpdate();
}

Method 3:

@Transactional
public void deleteOrg(int userId) {
    User user = sessionFactory.getCurrentSession().get(User.class, userId);
    sessionFactory.getCurrentSession().delete(user);
}
Dharita Chokshi
  • 1,133
  • 3
  • 16
  • 39

2 Answers2

4

Some more details to Gauillaume F.'s answer. I recommend going with method 4 (efficient, exposable as a service and idiomatic use of Hibernate).

Method 1

@Transactional    
public void deleteUser(User user) {
    sessionFactory.getCurrentSession().delete(user);
}
  • Deletion is synchronized with session cache
  • user must be an instance under Hibernate's control. So it cannot be directly exposed as a service.
  • Sufficiently efficient. It depends on how the instance is retrieved in the first place.

Method 2

@Transactional
public void deleteUser(int userId) {
    Query q = session.createQuery("delete User where id = :userId");
    query.setParameter("userId", userId);
    q.executeUpdate();
}
  • Efficient (no instance is loaded from database or put into session cache)
  • Can be directly exposed as a service
  • Not synchronized with session cache
  • Unnecessary use of HQL

Method 3

@Transactional
public void deleteOrg(int userId) {
    User user = sessionFactory.getCurrentSession().get(User.class, userId);
    sessionFactory.getCurrentSession().delete(user);
}
  • Sufficiently efficient (instance is first loaded from database, put into the session cache and then deleted)
  • Can be directly exposed as a service
  • Synchronized with session cache

Method 4

@Transactional
public void deleteOrg(int userId) {
    User user = sessionFactory.getCurrentSession().load(User.class, userId);
    sessionFactory.getCurrentSession().delete(user);
}
  • Efficient (no data is loaded; a proxy is put into the session cache instead)
  • Can be directly exposed as a service
  • Synchronized with session cache
Codo
  • 75,595
  • 17
  • 168
  • 206
2

The second method is not good because Hibernate won't be able to tell the object has been deleted; it can create issues with its internal session cache.

The first and third methods are very similar. Instead of get(User.class, userId) you should use load(..) which is faster since it returns a proxy object instead of fetching the data.

Guillaume F.
  • 5,905
  • 2
  • 31
  • 59
  • q.executeUpdate(); returns int value (0 or 1) indicating wheter query is executed successfully or not. – Dharita Chokshi Jul 09 '18 at 12:39
  • Yes @DharitaChokshi, but the issue is not about *you* being able to tell if the row has been deleted or not, it's about Hibernate's session cache. – Guillaume F. Jul 09 '18 at 12:41
  • Yes, you are right. In that case, I am more confused. Your answer is conflicting with @locus2k 's answer. – Dharita Chokshi Jul 09 '18 at 12:43
  • Not really conflicting, Locus is right as well. The entity is marked for deletion, and it will be commited only when the transaction is closed. Except in the second case because you bypass Hibernate and delete it right away. It is indeed "faster", but can also cause a lots of issues with the Session cache for more complex transactions, which is why I won't recommend this method. – Guillaume F. Jul 09 '18 at 12:48