0

I have small project(about 15 tables). I also use Hibernate sessionFactory in my project, and when I try to save some collection, I get SEVERE: org.hibernate.LazyInitializationException: failed to lazily initialize a collection, no session or session was closed (stacktrace below)

I call saving method from XHTML page, but Eclipse IDE dont even catch breakpoint (this is very strange for me, cause another breakpoints catched normally).

Also I use OpenSessionInViewFilter pattern to lazily get collection in view.

<filter>
    <filter-name>hibernateFilter</filter-name>
    <filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
    <init-param>
        <param-name>sessionFactoryBeanName</param-name>
        <param-value>sessionFactory</param-value>
    </init-param>
  </filter>

Here's my bean's header

@ManagedBean(name = "userBean")
@ViewScoped
public class UserBean implements Serializable {

    ...

I use Spring 3.2.5.RELEASE and Hibernate 4.1.0.Final, all the Hibernate stuff is quite standard (@Autowired, currentSession() and so on). I have @Transactional in my services.

SEVERE: org.hibernate.LazyInitializationException: failed to lazily initialize a collection, no session or session was closed
    at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:393)
    at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:385)
    at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:378)
    at org.hibernate.collection.internal.PersistentSet.add(PersistentSet.java:206)
    at com.sun.faces.renderkit.html_basic.MenuRenderer.convertSelectManyValuesForModel(MenuRenderer.java:381)
    at com.sun.faces.renderkit.html_basic.MenuRenderer.convertSelectManyValue(MenuRenderer.java:128)
    at com.sun.faces.renderkit.html_basic.MenuRenderer.getConvertedValue(MenuRenderer.java:314)
    at org.primefaces.component.selectmanymenu.SelectManyMenuRenderer.getConvertedValue(SelectManyMenuRenderer.java:37)
    at javax.faces.component.UIInput.getConvertedValue(UIInput.java:1046)
    at javax.faces.component.UIInput.validate(UIInput.java:976)
    at javax.faces.component.UIInput.executeValidate(UIInput.java:1249)
    at javax.faces.component.UIInput.processValidators(UIInput.java:712)
    at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:1258)
    at javax.faces.component.UIForm.processValidators(UIForm.java:253)
    at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:1258)
    at org.primefaces.component.dialog.Dialog.processValidators(Dialog.java:368)
    at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:1258)
    at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:1258)
    at org.primefaces.component.layout.Layout.processValidators(Layout.java:233)
    at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:1258)
    at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:1258)
    at javax.faces.component.UIViewRoot.processValidators(UIViewRoot.java:1195)
    at com.sun.faces.lifecycle.ProcessValidationsPhase.execute(ProcessValidationsPhase.java:76)
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
    at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:198)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:646)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:118)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:84)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:154)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilter(BasicAuthenticationFilter.java:150)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:199)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:110)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:343)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:260)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
    at org.apache.catalina.core.StandardContextValve.__invoke(StandardContextValve.java:191)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:861)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:606)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
    at java.lang.Thread.run(Thread.java:744)

Also, I cant see the line where exception is thrown, this is very sad :( Can you help me? Thanks in advance.

EDIT:

@Entity
@Table(name = "wbp_user")
public class User extends BaseEntity implements UserDetails {

  private static final long serialVersionUID = 197854700819034127L;
  private String username;
  private String firstname;
  private String lastname;
  private String password;
  private String adNickname;
  private boolean enabled;
  private Team team;
  private Group group;
  private boolean deleted;
  private Set<Group> groups = new HashSet<Group>();
  private Set<Role> roles = new HashSet<Role>();
  private Server server;
  private List<UserPenalty> userPenalties = new ArrayList<UserPenalty>();
  private List<UserProperty> userProperties = new ArrayList<UserProperty>();
  private Date createDate;
  private User createUser;
  private Date updateDate;
  private User updateUser;

  private GroupPropertyStatus status;
  private Date statusSetDate;

  @Column(name = "create_date")
  public Date getCreateDate() {
    return createDate;
  }

  public void setCreateDate(Date createDate) {
    this.createDate = createDate;
  }

  @ManyToOne(cascade = {CascadeType.PERSIST}, fetch = FetchType.LAZY)
  @JoinColumn(name = "create_user")
  public User getCreateUser() {
    return createUser;
  }

  public void setCreateUser(User createUser) {
    this.createUser = createUser;
  }

  @Column(name = "update_date")
  public Date getUpdateDate() {
    return updateDate;
  }

  public void setUpdateDate(Date updateDate) {
    this.updateDate = updateDate;
  }

  @ManyToOne(cascade = {CascadeType.PERSIST}, fetch = FetchType.LAZY)
  @JoinColumn(name = "update_user")
  public User getUpdateUser() {
    return updateUser;
  }

  public void setUpdateUser(User updateUser) {
    this.updateUser = updateUser;
  }

  @OneToMany(cascade = { CascadeType.PERSIST, CascadeType.REMOVE }, fetch = FetchType.LAZY, mappedBy = "user")
  @Fetch(FetchMode.SUBSELECT)
  public List<UserPenalty> getUserPenalties() {
    return userPenalties;
  }

  public void setUserPenalties(List<UserPenalty> userPenalties) {
    this.userPenalties = userPenalties;
  }

  @OneToMany(cascade = { CascadeType.PERSIST, CascadeType.REMOVE }, fetch = FetchType.LAZY, mappedBy = "user")
  @Fetch(FetchMode.SUBSELECT)
  @Where(clause = "enabled = 1")
  public List<UserProperty> getUserProperties() {
    return userProperties;
  }

  public void setUserProperties(List<UserProperty> userProperties) {
    this.userProperties = userProperties;
  }

  @Transient
  public Server getServer() {
    return server;
  }

  public void setServer(Server server) {
    this.server = server;
  }

  @Column(name = "username")
  public String getUsername() {
    return username;
  }

  public void setUsername(String username) {
    this.username = username;
  }

  @Column(name = "firstname")
  public String getFirstname() {
    return firstname;
  }

  public void setFirstname(String firstname) {
    this.firstname = firstname;
  }

  @Column(name = "lastname")
  public String getLastname() {
    return lastname;
  }

  public void setLastname(String lastname) {
    this.lastname = lastname;
  }

  @Column(name = "password")
  public String getPassword() {
    return password;
  }

  public void setPassword(String password) {
    this.password = password;
  }

  @Column(name = "ad_nickname")
  public String getAdNickname() {
    return adNickname;
  }

  public void setAdNickname(String adNickname) {
    this.adNickname = adNickname;
  }

  @Column(name = "enabled")
  public boolean isEnabled() {
    return enabled;
  }

  public void setEnabled(boolean enabled) {
    this.enabled = enabled;
  }

  @ManyToOne(cascade = {CascadeType.PERSIST}, fetch = FetchType.LAZY)
  @JoinColumn(name = "team_id")
  public Team getTeam() {
    return team;
  }

  public void setTeam(Team team) {
    this.team = team;
  }

  @ManyToOne(cascade = {CascadeType.PERSIST}, fetch = FetchType.LAZY)
  @JoinColumn(name = "group_id")
  public Group getGroup() {
    return group;
  }

  public void setGroup(Group group) {
    this.group = group;
  }

  @Column(name = "deleted")
  public boolean isDeleted() {
    return deleted;
  }

  public void setDeleted(boolean deleted) {
    this.deleted = deleted;
  }

  @ManyToMany(fetch = FetchType.EAGER)
  @JoinTable(name = "wbp_user_role", joinColumns = {@JoinColumn(name = "user_id")}, inverseJoinColumns = @JoinColumn(name = "role_id"))
  public Set<Role> getRoles() {
    return roles;
  }

  public void setRoles(Set<Role> roles) {
    this.roles = roles;
  }

  @ManyToMany(fetch = FetchType.EAGER)
  @JoinTable(name = "wbp_user_group", joinColumns = {@JoinColumn(name = "user_id")}, inverseJoinColumns = @JoinColumn(name = "group_id"))
  @Where(clause = "enabled = 1")
  public Set<Group> getGroups() {
    return groups;
  }

  public void setGroups(Set<Group> groups) {
    this.groups = groups;
  }

  @Override
  public String toString() {
    return "id = " + id + ", username = " + username + ", group = " + group.getGroupName() + ", status = " + status;

  }

  @Transient
  public String getStatusDuration(){
    if(statusSetDate != null){
      Long value = new Date().getTime() - statusSetDate.getTime();
      return String.format("%02d:%02d:%02d", TimeUnit.MILLISECONDS.toHours(value), TimeUnit.MILLISECONDS.toMinutes(value) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(value)), TimeUnit.MILLISECONDS.toSeconds(value) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(value)));
    }
    return null;
  }

  @Transient
  public Date getStatusSetDate() {
    return statusSetDate;
  }

  public void setStatusSetDate(Date statusSetDate) {
    this.statusSetDate = statusSetDate;
  }

  @Transient
  public GroupPropertyStatus getStatus() {
    return status;
  }

  public void setStatus(GroupPropertyStatus status) {
    this.status = status;
  }

  @Override
  public boolean equals(Object o) {
    if (this == o) {
      return true;
    }
    if (!(o instanceof User)) {
      return false;
    }
    final User obj = (User) o;

    return generateEquals(getId(), obj.getId());
  }

  @Override
  public int hashCode() {
    return generateHash(31, 42, getId());
  }

  @Transient
  public Set<GrantedAuthority> getAuthorities() {
    Set<GrantedAuthority> authorities = new LinkedHashSet<GrantedAuthority>();
    authorities.addAll(roles);
    return authorities;
  }

  @Transient
  public boolean isUserInRole(String roleName){
    for (Role role : getRoles()) {
      if(role.getRoleName().equals(roleName)){
        return true;
      }
    }
    return false;
  }

  @Transient
  public boolean isAccountNonExpired() {
    return true;
  }

  @Transient
  public boolean isAccountNonLocked() {
    return true;
  }

  @Transient
  public boolean isCredentialsNonExpired() {
    return true;
  }

}

And Group:

@Entity
@Table(name = "wbp_group")
public class Group extends BaseEntity {

  private static final long serialVersionUID = -2237526151218578392L;
  private String groupName;
  private String groupDescription;
  private Set<Queue> queues = new HashSet<Queue>();
  private List<GroupPenalty> groupPenalties = new ArrayList<GroupPenalty>();
  private List<GroupProperty> groupProperties = new ArrayList<GroupProperty>();
  private boolean deleted;
  private boolean enabled;
  private Date createDate;
  private User createUser;
  private Date updateDate;
  private User updateUser;

  @Column(name = "enabled")
  public boolean isEnabled() {
    return enabled;
  }

  public void setEnabled(boolean enabled) {
    this.enabled = enabled;
  }

  @Column(name = "create_date")
  public Date getCreateDate() {
    return createDate;
  }

  public void setCreateDate(Date createDate) {
    this.createDate = createDate;
  }

  @ManyToOne(cascade = {CascadeType.PERSIST}, fetch = FetchType.LAZY)
  @JoinColumn(name = "create_user")
  public User getCreateUser() {
    return createUser;
  }

  public void setCreateUser(User createUser) {
    this.createUser = createUser;
  }

  @Column(name = "update_date")
  public Date getUpdateDate() {
    return updateDate;
  }

  public void setUpdateDate(Date updateDate) {
    this.updateDate = updateDate;
  }

  @ManyToOne(cascade = {CascadeType.PERSIST}, fetch = FetchType.LAZY)
  @JoinColumn(name = "update_user")
  public User getUpdateUser() {
    return updateUser;
  }

  public void setUpdateUser(User updateUser) {
    this.updateUser = updateUser;
  }

  @OneToMany(cascade = {CascadeType.PERSIST, CascadeType.REMOVE}, fetch = FetchType.LAZY, mappedBy = "group")
  @Fetch(FetchMode.SUBSELECT)
  @Where(clause = "enabled = 1")
  public List<GroupProperty> getGroupProperties() {
    return groupProperties;
  }

  public void setGroupProperties(List<GroupProperty> groupProperties) {
    this.groupProperties = groupProperties;
  }

  @Column(name = "group_name")
  public String getGroupName() {
    return groupName;
  }

  public void setGroupName(String groupName) {
    this.groupName = groupName;
  }

  @Column(name = "group_description")
  public String getGroupDescription() {
    return groupDescription;
  }

  public void setGroupDescription(String groupDescription) {
    this.groupDescription = groupDescription;
  }

  @Column(name = "deleted")
  public boolean isDeleted() {
    return deleted;
  }

  public void setDeleted(boolean deleted) {
    this.deleted = deleted;
  }

  @ManyToMany(fetch = FetchType.EAGER)
  @JoinTable(name = "wbp_queue_group", joinColumns = {@JoinColumn(name = "group_id")}, inverseJoinColumns = @JoinColumn(name = "queue_id"))
  @Where(clause = "enabled = 1")
  public Set<Queue> getQueues() {
    return queues;
  }

  public void setQueues(Set<Queue> queues) {
    this.queues = queues;
  }

  @OneToMany(cascade = {CascadeType.PERSIST, CascadeType.REMOVE}, fetch = FetchType.LAZY, mappedBy = "group")
  @Fetch(FetchMode.SUBSELECT)
  public List<GroupPenalty> getGroupPenalties() {
    return groupPenalties;
  }

  public void setGroupPenalties(List<GroupPenalty> groupPenalties) {
    this.groupPenalties = groupPenalties;
  }

  @Override
  public String toString() {
    return "id = " + id + ", groupName = " + groupName;
  }

  @Override
  public boolean equals(Object o) {
    if (this == o) {
      return true;
    }
    if (!(o instanceof Group)) {
      return false;
    }
    final Group obj = (Group) o;

    return generateEquals(getId(), obj.getId());
  }

  @Override
  public int hashCode() {
    return generateHash(31, 42, getId());
  }

}
user2171669
  • 745
  • 1
  • 12
  • 22
  • As your error clearly says that no session available.So You are calling method from JSF page while intermediate where you are saving collection object.It is throwing this error. – Satyam Koyani May 20 '14 at 07:32
  • http://stackoverflow.com/questions/11746499/how-to-resolve-failed-to-lazily-initialize-a-collection-of-role-exception – Pramod S. Nikam May 20 '14 at 07:33
  • I understand, but why? All the stuff is quite standard and should work fine in view. I can get collection, but cant save. – user2171669 May 20 '14 at 07:36
  • Can you post the objects that you are working with, I almost guarantee that you are missing something in your annotations, thus rendering my carefully crafted answer worthless. If you post the objects, I will rectify my answer. Also, what are you actually trying to achieve? Your use of `OpenSessionInViewFilter` makes no sense. Are you using it to actually populate your collection object? – JamesENL May 20 '14 at 07:43
  • This feels like an [X-Y Problem](http://mywiki.wooledge.org/XyProblem) – JamesENL May 20 '14 at 08:00

1 Answers1

2

CLASSIC X-Y PROBLEM.

Answer Given to answer question OP Asked:

You are trying to do something to the value of a collection outside of a @Transactional context. See the example below:

@Service
public class FooServiceImpl implements FooService{
    @Autowired
    private BarDao barDao;

    @Transactional
    public Bar getBar(long barId){
        return barDao.find(barId);
    }
}

@Controller
public class Controller{
    @Autowired
    private FooService fooService;

    @RequestMapping(value="/home")
    public void accessCollectionWrong(){
        Bar bar = fooService.getBar(barId);
        //assume that bar contains a collection of Baz objects
        List<Baz> bazList = bar.getBazList(); <-- THIS THROWS THE EXCEPTION
    }
}

The exception is being thrown because Hibernate has not actually loaded your collection of Baz objects from the database. This is to save time where you don't actually need the objects. But Hibernate detects that you have tried to access the collection of Baz objects and so it goes to the database to actually try and get all the Baz objects. It can't do that because you are in your controller, outside of the @Transactional context, so it has no active session to use to retrieve your objects. The code needs to be redesigned as below:

@Service
public class FooServiceImpl implements FooService{
    @Autowired
    private BarDao barDao;

    @Transactional
    public Bar getBar(long barId){
        return barDao.find(barId);
    }

    @Transactional
    public List<Baz> getBaz(long barId){
        return barDao.find(barId).getBaz();
    }
}

@Controller
public class Controller{
    @Autowired
    private FooService fooService;

    @RequestMapping(value="/home")
    public void accessCollectionWrong(){
        List<Baz> bazList = fooService.getBazList(barId); <-- THIS DOESN'T THROW THE EXCEPTION
    }
}

Does this all make sense? If not, let me know and I can expand on my explanation.

Edit 1: Things to note: Hibernate Session != HTTP Session, Hibernate Session != Application Context, Hibernate Session != Session Scoped Beans Session. A Hibernate session is a totally different concept, that revolves around the database and its interactions with the database.

Each Hibernate session is scoped around your @Transactional annotations. Each time you enter a @Transactional method, Hibernate creates a new session for you (using the SessionFactory and assuming you haven't specified a Propagation level). That's why your call to sessionFactory.getCurrentSession() succeeds and doesn't return null. When you exit the @Transactional method your database changes are automatically committed by Hibernate and the current Hibernate session is closed. Once the session is closed then Hibernate can't get your collection without opening another session by entering an annotated @Transactional method.

The reason that in my example I used barDao.find(barId).getBaz() was that it is always better to get a fresh instance of the object that your collection is stored in before actually asking for the collection. That way you are sure that you are not going to suffer from phantom reads/writes etc. I believe that if you try to access the collection in a new session with a stale object, you get a StaleStateException.

Actual Answer OP Wanted:

You have 2 objects, a User has a collection of Group's and you want to cascade operations on a User to a Group.

public class User{
    //Normal Id's and other fields
    @OneToMany(mappedBy="user" cascade=CascadeType.ALL, orphanRemoval=true)
    private List<Group> groups = new ArrayList<Group>();
}

public class Group{
    //Normal Id's and other fields.
    @ManyToOne
    @JoinColumn(name="userId")
    private User user;
}

The annotations do the following:

OneToMany says that there is a collection of Group objects that have a link to this User object, Hibernate should cascade all operations to the Group table. Hibernate should remove orphaned Group objects from the database.

@ManyToOne & @JoinColumn says that this Group object has a link to a User object and that it should join around the column called userId in the User table. Basically turns the PK in User into the FK for the Group table.

So if you create a List of Group objects and go User.setGroups(groupList) and then call userDao.save(user) Hibernate will create X Group records in the database by cascade.

Again, if this doesn't make sense, tell me.

JamesENL
  • 6,400
  • 6
  • 39
  • 64
  • I dont need to get all objects within @Transactional, I need to keep my session open, but how to do it? Can I reattach collection to new session? – user2171669 May 20 '14 at 07:51
  • I understood, going to try your approach and mark answer as solution. I'll let you know. Thanks for helping me. – user2171669 May 20 '14 at 08:00
  • I have Users, they have lazy Groups (collection). I have @Transactionsl saveUser(User u), isnt this enough? Whats the proper pattern to save collection using the way you described? I loaded collection normally, I mentioned. – user2171669 May 20 '14 at 08:19
  • Can you post the `Users` object and the `Groups` object – JamesENL May 20 '14 at 08:20
  • I'm not going to ask why in Gods name you are composing the `User` object into itself, and just roll with it. I've updated my answer. – JamesENL May 20 '14 at 08:37
  • '@ManyToMany' is right option, cause different users can have the same group. Adding cascade=CascadeType.ALL to '@ManyToMany' didnt help, exception still occurs. – user2171669 May 20 '14 at 09:26
  • Sorry, I can't help you any more, your classes are too much of a mess. You have seem to be randomly composing objects in the hope that something will end up working. This design is fatally flawed at a fundamental level. – JamesENL May 21 '14 at 03:14