Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hibernate updating child entities while updating parent entity

I have two entities as User and Projects having @ManyToMany relationship between them as follows.

Entity Classes

import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;

@Entity
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column (name = "id")
    private int id;
    @Column (name = "email")
    private String email;
    @Column (name = "password")
        private String password;
    @Column (name = "last_login")
    private Date lastLogInDate; 
    @ManyToMany(fetch = FetchType.EAGER)
        @Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE})
        @JoinTable(name = "project_assigned", joinColumns = { @JoinColumn(name = "fk_user_id")  }, inverseJoinColumns = { @JoinColumn(name = "fk_project_id") } )
    private Set<Projects> projects = new HashSet<Projects>(0);  

    // setter and getter methods.
}

@Entity
@Table(name = "projects")
public class Projects {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private int id;
    @Column (name = "name")
    private String name;    
    @ManyToMany(fetch = FetchType.LAZY)
    @JoinTable(name = "user_projects", joinColumns = { @JoinColumn(name = "fk_project_id") }, inverseJoinColumns = { @JoinColumn(name = "fk_user_id") })
    private Set<User> userSet = new HashSet<User>(0);   

}

DAO Class

@Repository
public class UserDAO {

    public User findByCredentials(String email, String password) {
        String queryString = " from User u where u.email = ? and u.password = ?";
        Query query = sessionFactory.getCurrentSession().createQuery(queryString);
        query.setString(0, email);
        query.setString(1, password);       
        return (User) query.uniqueResult();     
    }

    public boolean updateUser(User user) {
        boolean result = true;
        Session session = null;
        try {
            session = sessionFactory.getCurrentSession();
            session.update(user);
        } catch (HibernateException e) {
            result = false;
            logger.error("Can not Update User"+e);
            e.printStackTrace();
        } 
        return result;
    }           
}

Service Class

@Service
@Transactional(readOnly = true,propagation=Propagation.SUPPORTS)
public class UserService {

    @Autowired
    private UserDAO userDAO;

    public User findByCredentials(String userName, String lastName) {
        return userDAO.findByCredentials(userName, lastName);   
    }

    @Transactional(readOnly = false,propagation=Propagation.REQUIRED)
    public boolean updateUser(User user) {
        return userDAO.updateUser(user);
    }
}

Other Code

User user = userService.findByCredentials("[email protected]", "abc");
user.setLastLogInDate(new Date());
userService.updateUser(user);

My problem is that when I am updating the 'LastLogInDate' of an User then all Project Entities assigned to that user are getting updated (unnecessary fire update statement) due to this my application performance is low. How can I solve this problem. and how can I do this in better way. Thanks for your help.

Here is my SQL logs

DEBUG org.hibernate.SQL#log  - update users set email=?, password=?, last_login=? where id=?
DEBUG org.hibernate.SQL#log  - update user_projects set name=? where id=?
DEBUG org.hibernate.SQL#log  - update user_projects set name=? where id=?
DEBUG org.hibernate.SQL#log  - update user_projects set name=? where id=?
DEBUG org.hibernate.SQL#log  - update user_projects set name=? where id=?
DEBUG org.hibernate.SQL#log  - update user_projects set name=? where id=?
like image 542
Ashish Jagtap Avatar asked Dec 31 '25 04:12

Ashish Jagtap


1 Answers

you must set your cascade since cascade can't be set during runtime (save):

@Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE})

you must at least remove the CascadeType.MERGE. because MERGE means something complex that approximates "save" but is more like "push this detached entity back into managed status and save its state changes". the cascading means that all associated entities get pushed back the same way, and the managed-entity handle you get back from .merge() has all managed entities associated with it.

like image 69
Lau Avatar answered Jan 03 '26 12:01

Lau



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!