我有两个实体作为User和Projects,它们之间有@ManyToMany关系,如下所示。
实体类
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课程
@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
@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);
}
}
其他代码
User user = userService.findByCredentials("xyz@pqr.com", "abc");
user.setLastLogInDate(new Date());
userService.updateUser(user);
我的问题是当我更新用户的'LastLogInDate'时 那么分配给该用户的所有项目实体都会得到更新(不必要的火灾更新声明) 由于这个原因,我的应用程序性能很低。我怎么解决这个问题。我怎样才能更好地做到这一点。谢谢你的帮助。
这是我的SQL日志
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=?
答案 0 :(得分:2)
您必须设置级联,因为在运行期间无法设置级联(保存):
@Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE})
您必须至少删除CascadeType.MERGE
。因为MERGE意味着复杂的东西近似“保存”,但更像是“将这个分离的实体推回到托管状态并保存其状态变化”。级联意味着所有关联的实体都以相同的方式被推回,并且您从.merge()获得的托管实体句柄具有与之关联的所有托管实体。
答案 1 :(得分:-1)
删除所有级联选项。这将解决您的问题
1解决方案:
解决方案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;
项目类
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "user_projects", joinColumns = { @JoinColumn(name = "fk_project_id") }, inverseJoinColumns = { @JoinColumn(name = "fk_user_id") })
private Set<User> userSet;