Reputation: 2819
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=?
Upvotes: 3
Views: 3169
Reputation: 9
Remove all cascade options. This will solve your problem
1 solutions:
Solution 1:
USer class:
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = "user_projects", joinColumns = { @JoinColumn(name = "fk_project_id") }, inverseJoinColumns = { @JoinColumn(name = "fk_user_id") })
private Set<Projects> projects;
Projects Class
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "user_projects", joinColumns = { @JoinColumn(name = "fk_project_id") }, inverseJoinColumns = { @JoinColumn(name = "fk_user_id") })
private Set<User> userSet;
Upvotes: -1
Reputation: 31
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.
Upvotes: 2