Я работаю над грубым веб-приложением, использующим отношения «многие ко многим», но у меня действительно проблема с обновлением строки.Когда я вызываю currentSession.saveOrUpdate(user)
из репозитория пользователя, выдается следующее исключение: org.hibernate.NonUniqueObjectException: A different object with the same identifier value was already associated with the session
.
Вот мой код:
Контроллер:
@Autowired
private UserService userService;
@Autowired
private TeamService teamService;
@GetMapping("/")
public String listProjects(Model theModel) {
/*
* To get the username using Spring Security
*/
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
String username = auth.getName();
theModel.addAttribute("username", username);
/*
* Get the current user by username
*/
User user = userService.findByUsername(username);
/*
* Get the teams of the current user
*/
List<Team> theTeams = user.getTeams();
System.out.println(user);
System.out.println(theTeams);
//Add teams to the model attribute
theModel.addAttribute("teams", theTeams);
return "home";
}
@GetMapping("renameTeamForm")
public String showNewTeamForm(@RequestParam("teamId") int teamId, Model theModel) {
Team team = teamService.findTeamById(teamId);
// team.setTeamName(team.getTeamName());
theModel.addAttribute("team",team);
return "rename-team-form";
}
@PostMapping("/saveTeam") public String
saveOrUpdateTeam(@ModelAttribute("team") Team theTeam) {
Authentication auth =
SecurityContextHolder.getContext().getAuthentication(); String username =
auth.getName();
User user = userService.findByUsername(username);
// GET TEAMS OF CURRENT USER
System.out.println("Inside showNewTeamForm method");
System.out.println(user.getTeams());
user.addTeam(theTeam);
System.out.println("The Team: " + theTeam);
userService.saveUser(user);
return "redirect:/"; }
Сущности:
@Entity
@Table(name = "users")
public class User {
@Id
@Column(name = "username", unique = true,
nullable = false, length = 50)
private String userName;
@Column(name = "password",
nullable = false, length = 68)
private String password;
@Column(name = "enabled", nullable = false)
private int enabled;
@ManyToMany(cascade= CascadeType.ALL , fetch = FetchType.LAZY)
@JoinTable(name="users_teams",
joinColumns=@JoinColumn(name="username"),
inverseJoinColumns=@JoinColumn(name="teams_id"))
private List<Team> teams;
public User() {
}
public User(String userName, int enabled, List<Team> teams) {
this.userName = userName;
this.enabled = enabled;
this.teams = teams;
}
public String getUserName() {
return this.userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return this.password;
}
public void setPassword(String password) {
this.password = password;
}
public int isEnabled() {
return this.enabled;
}
public void setEnabled(int enabled) {
this.enabled = enabled;
}
public List<Team> getTeams() {
return teams;
}
public void setTeams(List<Team> teams) {
this.teams = teams;
}
public void addTeam(Team team) {
if (teams == null) {
teams = new ArrayList<>();
}
teams.add(team);
}
}
.
@Entity
@Table(name = "teams")
public class Team {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="id")
private int id;
@Column(name = "teamname")
private String teamName;
@ManyToMany(cascade= CascadeType.ALL,fetch = FetchType.LAZY)
@JoinTable(name="users_teams",
joinColumns=@JoinColumn(name="teams_id"),
inverseJoinColumns=@JoinColumn(name="username"))
private List<User> users;
// getters and setters
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Team() {
// TODO Auto-generated constructor stub
}
public Team(String teamName) {
this.teamName = teamName;
}
public String getTeamName() {
return teamName;
}
public List<User> getUsers() {
return users;
}
public void setUsers(List<User> users) {
this.users = users;
}
public void setTeamName(String teamName) {
this.teamName = teamName;
}
}
Хранилища:
@Repository
public class UserDaoImpl implements UserDao {
@Autowired
SessionFactory sessionFactory;
@Override
public User findUserByUsername(String email) {
Session currentSession = sessionFactory.getCurrentSession();
String hql = "from User u where u.userName = :username";
Query<User> query = currentSession.createQuery(hql, User.class);
query.setParameter("username",email);
User user = (User) query.getSingleResult();
if (user !=null) {
Hibernate.initialize(user.getTeams());
}
return user;
}
@Override public void saveUser(User user) {
Session currentSession = sessionFactory.getCurrentSession();
currentSession.saveOrUpdate(user);
}
@Override
public List<User> findAllUsers() {
Session currentSession = sessionFactory.getCurrentSession();
String hql = "from User order by userName";
Query<User> query = currentSession.createQuery(hql, User.class);
List<User> users = query.getResultList();
return users;
}
.
@Repository
public class TeamDaoImpl implements TeamDao {
@Autowired
private SessionFactory sessionFactory;
@Override
public List<Team> findAllTeams() {
System.out.println("Finding all groups");
// get the current hibernate session
Session currentSession =
sessionFactory.getCurrentSession();
// Find all groups
Query<Team> theQuery = currentSession.createQuery("from Team order by teamName", Team.class);
// execute query and get result list
List<Team> teams = theQuery.getResultList();
// return the results
return teams;
}
@Override
public List<Team> findTeamsByUsername(String email) {
// get the current hibernate session
Session currentSession = sessionFactory.getCurrentSession();
// Find all groups
Query<Team> theQuery = currentSession.createQuery("from Team order by teamName", Team.class);
// execute query and get result list
List<Team> teams = theQuery.getResultList();
// return the results
return teams;
}
@Override
public void saveTeam(Team theTeam) {
Session currentSession = sessionFactory.getCurrentSession();
//save team
currentSession.save(theTeam);
}
@Override
public void deleteTeam(int teamId) {
Session currentSession = sessionFactory.getCurrentSession();
//delete object with primary key
Query theQuery = currentSession.createQuery("delete from Team where id=:teamId");
theQuery.setParameter("teamId", teamId);
theQuery.executeUpdate();
}
@Override
public Team findTeamById(int teamId) {
Session currentSession = sessionFactory.getCurrentSession();
String hql = "FROM Team T WHERE T.id = :teamid";
Query<Team> query = currentSession.createQuery(hql, Team.class);
query.setParameter("teamid",teamId);
Team team = (Team) query.getSingleResult();
if (team !=null) {
Hibernate.initialize(team.getUsers());
}
return team;
}
}
Услуги:
@Service
@Transactional
public class UserServiceImpl implements UserService {
@Autowired
private UserDao dao;
@Override
public User findByUsername(String email) {
// TODO Auto-generated method stub
return dao.findUserByUsername(email);
}
@Override public void saveUser(User user) {
dao.saveUser(user);
}
@Override
public List<User> findAllUsers() {
return dao.findAllUsers();
}
}
.
@Service
@Transactional
public class TeamServiceImpl implements TeamService {
@Autowired
private TeamDao dao;
@Override
public List<Team> findAllTeams() {
return dao.findAllTeams();
}
@Override
public void saveTeam(Team theTeam) {
dao.saveTeam(theTeam);
}
@Override
public void deleteTeam(int teamId) {
dao.deleteTeam(teamId);
}
@Override
public Team findTeamById(int teamId) {
return dao.findTeamById(teamId);
}
}
Я попытался заменить saveOrUpdate слиянием, и оно не сработало, выдав исключение Multiple representations of the same entity
.
Я также добавил session.evict()
после session.saveOrUpdate()
, и произошло то же исключение.
В чем проблема в моем коде?Я не вижу дубликатов моей объектной команды, вызванной в моей транзакции ... Что-то мне не хватает?