JSF selectCheckboxMenu & Hibernate @ManyToMany remove values
up vote
1
down vote
favorite
First of all some details von the used software: I'm working with primefaces 6.2.11 on Wildfly 14.0.1Final with JSF 2.3.
Problemdescription: I have two entities (User & Group) related many2many and I want to remove a relation on the side which is not the owner (the entity with the mappedBy). I cant change the owner sides because this is legacy code. I know that I have to remove the relation on both ends but my code does not work. Adding values to the list is no problem but removing them is not possible.
I tried this several days ago with Wildfly 10 and it was okay but not with the new one.
One problem is that the primefaces list does no notify me via ajax event when an item will be removed. If this would be the case I could handle the remove from my group list and user list in the group. Because I dont have an event like that I tried to handle this in my service which tries to save the user.
I have two entities:
@Entity
@Table(name = "USER")
public class User implements Serializable {
private static final long serialVersionUID = -1699265057144017750L;
@Column(name = "ID", nullable = false)
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column(name = "USER_NAME", length = 45, unique = true)
@Basic
@NotNull
private String userName;
@ManyToMany(fetch = FetchType.LAZY, targetEntity = Group.class, mappedBy = "userList")
@OrderBy("groupName")
private Set<Group> groupList;
// getter setter ...
}
@Entity
@Table(name = "GROUP")
public class User implements Serializable {
private static final long serialVersionUID = -3403518747362744630L;
@Column(name = "ID", nullable = false)
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@ManyToMany(fetch = FetchType.LAZY, targetEntity = User.class, cascade = {CascadeType.MERGE, CascadeType.PERSIST})
@JoinTable(name = "USER_GROUP",
joinColumns = {@JoinColumn(name = "GROUP_ID", referencedColumnName = "ID")},
inverseJoinColumns = {@JoinColumn(name = "USER_ID", referencedColumnName = "ID")})
@OrderBy("userName")
private Set<User> userList;
// getter setter ...
}
I created a form to edit users. This form has a lot of inputs and one is for adding and removing groups from the user. It is a simpel primefaces selectCheckboxMenu. This allowes the user to choose new groups and remove old groups. The value(s) is/are directly retrieved from the user entity and the values which can be selected are served by an seperate service.
<p:selectCheckboxMenu id="groupList" multiple="true" filter="true" filterMatchMode="contains"
value="#{editUserBean.authUser.groupList}"
required="true" requiredMessage="At least one group is needed"
converter="cs.argos.gui.jsf.converter.groupConverter" collectionType="java.util.LinkedHashSet">
<f:selectItems value="#{groupService.groups}" var="group" itemValue="#{group}" itemLabel="#{group.authGroupName}"/>
</p:selectCheckboxMenu>
Converter:
@FacesConverter(value = "groupConverter", managed = true)
public class GroupConverter implements Converter {
@Inject
GroupService groupService;
@Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
if(null == value || value.isEmpty()) {
return null;
}
try {
return groupService.getGroupWithCollections(Integer.parseInt(value));
} catch (NumberFormatException e) {
throw new ConverterException(new FacesMessage("Invalid Group ID"), e);
}
}
@Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
Group group = (Group) value;
if (null == group) {
return "";
}
if(null != group.getId()) {
return ""+group.getId();
} else {
throw new ConverterException(new FacesMessage("Invalid Group ID"));
}
}
}
When the used hits a button I'm calling the following service:
@Transactional(Transactional.TxType.REQUIRED)
public User persistWithDeps(User user2Save) {
User user = user = baseEm.contains(user2Save) ? user2Save : baseEm.merge(user2Save);
// Check if we have a new object (case when: baseEm.merge(user2Save))
if (user != user2Save) {
if (null != user.getGroupList()) {
// remove groups
if (!user2Save.getGroupList().containsAll(user.getGroupList())) {
// remove groups from user
Iterator<Group> iterator = user.getGroupList().iterator();
while (iterator.hasNext()) {
Group group = iterator.next();
if (!user2Save.getGroupList().contains(group)) {
group.getuser2SaveList().remove(user);
iterator.remove();
}
}
}
// Add groups to user
user.getGroupList().forEach(group -> {
if (!group.getUserList().contains(user)) {
group.getUserList().add(user);
}
});
}
}
baseEm.persist(user);
return user;
}
hibernate jsf primefaces many-to-many jsf-2.3
add a comment |
up vote
1
down vote
favorite
First of all some details von the used software: I'm working with primefaces 6.2.11 on Wildfly 14.0.1Final with JSF 2.3.
Problemdescription: I have two entities (User & Group) related many2many and I want to remove a relation on the side which is not the owner (the entity with the mappedBy). I cant change the owner sides because this is legacy code. I know that I have to remove the relation on both ends but my code does not work. Adding values to the list is no problem but removing them is not possible.
I tried this several days ago with Wildfly 10 and it was okay but not with the new one.
One problem is that the primefaces list does no notify me via ajax event when an item will be removed. If this would be the case I could handle the remove from my group list and user list in the group. Because I dont have an event like that I tried to handle this in my service which tries to save the user.
I have two entities:
@Entity
@Table(name = "USER")
public class User implements Serializable {
private static final long serialVersionUID = -1699265057144017750L;
@Column(name = "ID", nullable = false)
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column(name = "USER_NAME", length = 45, unique = true)
@Basic
@NotNull
private String userName;
@ManyToMany(fetch = FetchType.LAZY, targetEntity = Group.class, mappedBy = "userList")
@OrderBy("groupName")
private Set<Group> groupList;
// getter setter ...
}
@Entity
@Table(name = "GROUP")
public class User implements Serializable {
private static final long serialVersionUID = -3403518747362744630L;
@Column(name = "ID", nullable = false)
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@ManyToMany(fetch = FetchType.LAZY, targetEntity = User.class, cascade = {CascadeType.MERGE, CascadeType.PERSIST})
@JoinTable(name = "USER_GROUP",
joinColumns = {@JoinColumn(name = "GROUP_ID", referencedColumnName = "ID")},
inverseJoinColumns = {@JoinColumn(name = "USER_ID", referencedColumnName = "ID")})
@OrderBy("userName")
private Set<User> userList;
// getter setter ...
}
I created a form to edit users. This form has a lot of inputs and one is for adding and removing groups from the user. It is a simpel primefaces selectCheckboxMenu. This allowes the user to choose new groups and remove old groups. The value(s) is/are directly retrieved from the user entity and the values which can be selected are served by an seperate service.
<p:selectCheckboxMenu id="groupList" multiple="true" filter="true" filterMatchMode="contains"
value="#{editUserBean.authUser.groupList}"
required="true" requiredMessage="At least one group is needed"
converter="cs.argos.gui.jsf.converter.groupConverter" collectionType="java.util.LinkedHashSet">
<f:selectItems value="#{groupService.groups}" var="group" itemValue="#{group}" itemLabel="#{group.authGroupName}"/>
</p:selectCheckboxMenu>
Converter:
@FacesConverter(value = "groupConverter", managed = true)
public class GroupConverter implements Converter {
@Inject
GroupService groupService;
@Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
if(null == value || value.isEmpty()) {
return null;
}
try {
return groupService.getGroupWithCollections(Integer.parseInt(value));
} catch (NumberFormatException e) {
throw new ConverterException(new FacesMessage("Invalid Group ID"), e);
}
}
@Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
Group group = (Group) value;
if (null == group) {
return "";
}
if(null != group.getId()) {
return ""+group.getId();
} else {
throw new ConverterException(new FacesMessage("Invalid Group ID"));
}
}
}
When the used hits a button I'm calling the following service:
@Transactional(Transactional.TxType.REQUIRED)
public User persistWithDeps(User user2Save) {
User user = user = baseEm.contains(user2Save) ? user2Save : baseEm.merge(user2Save);
// Check if we have a new object (case when: baseEm.merge(user2Save))
if (user != user2Save) {
if (null != user.getGroupList()) {
// remove groups
if (!user2Save.getGroupList().containsAll(user.getGroupList())) {
// remove groups from user
Iterator<Group> iterator = user.getGroupList().iterator();
while (iterator.hasNext()) {
Group group = iterator.next();
if (!user2Save.getGroupList().contains(group)) {
group.getuser2SaveList().remove(user);
iterator.remove();
}
}
}
// Add groups to user
user.getGroupList().forEach(group -> {
if (!group.getUserList().contains(user)) {
group.getUserList().add(user);
}
});
}
}
baseEm.persist(user);
return user;
}
hibernate jsf primefaces many-to-many jsf-2.3
1
"code does not work" is not that self explaining. As you did not clarify how it does not work (error message in log, console or browser, methods not invoked anyway, so many other possibilities) I can only guess that your code does not compile becaus you useuser2Save
as varialbe and type.
– Selaron
Nov 20 at 8:38
Sorry for my bad explanation. The codes does compile, this was a type caused by stripping down my example for stackoverflow. The problem is, that I cant delete any group from the list. Hibernate does not delete relation
– Sebastian S.
Nov 20 at 9:42
Hence a Minimal, Complete, and Verifiable example is always required. And did you try to add ajax to your select to keep track of what is and what is not selected?
– Kukeltje
Nov 20 at 9:42
1
I can try to create a more complete example, later. Yes, I added some ajax and everything is just fine. I pass the correct list to the merge/persist method but hibernate does not execute any delete statement.
– Sebastian S.
Nov 20 at 9:46
1
Then it is not a jsf(2.3) or PrimeFaces issue but a pure hibernate (or even JPA) question. Maybe creating a simple unittest would be better
– Kukeltje
Nov 20 at 9:49
add a comment |
up vote
1
down vote
favorite
up vote
1
down vote
favorite
First of all some details von the used software: I'm working with primefaces 6.2.11 on Wildfly 14.0.1Final with JSF 2.3.
Problemdescription: I have two entities (User & Group) related many2many and I want to remove a relation on the side which is not the owner (the entity with the mappedBy). I cant change the owner sides because this is legacy code. I know that I have to remove the relation on both ends but my code does not work. Adding values to the list is no problem but removing them is not possible.
I tried this several days ago with Wildfly 10 and it was okay but not with the new one.
One problem is that the primefaces list does no notify me via ajax event when an item will be removed. If this would be the case I could handle the remove from my group list and user list in the group. Because I dont have an event like that I tried to handle this in my service which tries to save the user.
I have two entities:
@Entity
@Table(name = "USER")
public class User implements Serializable {
private static final long serialVersionUID = -1699265057144017750L;
@Column(name = "ID", nullable = false)
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column(name = "USER_NAME", length = 45, unique = true)
@Basic
@NotNull
private String userName;
@ManyToMany(fetch = FetchType.LAZY, targetEntity = Group.class, mappedBy = "userList")
@OrderBy("groupName")
private Set<Group> groupList;
// getter setter ...
}
@Entity
@Table(name = "GROUP")
public class User implements Serializable {
private static final long serialVersionUID = -3403518747362744630L;
@Column(name = "ID", nullable = false)
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@ManyToMany(fetch = FetchType.LAZY, targetEntity = User.class, cascade = {CascadeType.MERGE, CascadeType.PERSIST})
@JoinTable(name = "USER_GROUP",
joinColumns = {@JoinColumn(name = "GROUP_ID", referencedColumnName = "ID")},
inverseJoinColumns = {@JoinColumn(name = "USER_ID", referencedColumnName = "ID")})
@OrderBy("userName")
private Set<User> userList;
// getter setter ...
}
I created a form to edit users. This form has a lot of inputs and one is for adding and removing groups from the user. It is a simpel primefaces selectCheckboxMenu. This allowes the user to choose new groups and remove old groups. The value(s) is/are directly retrieved from the user entity and the values which can be selected are served by an seperate service.
<p:selectCheckboxMenu id="groupList" multiple="true" filter="true" filterMatchMode="contains"
value="#{editUserBean.authUser.groupList}"
required="true" requiredMessage="At least one group is needed"
converter="cs.argos.gui.jsf.converter.groupConverter" collectionType="java.util.LinkedHashSet">
<f:selectItems value="#{groupService.groups}" var="group" itemValue="#{group}" itemLabel="#{group.authGroupName}"/>
</p:selectCheckboxMenu>
Converter:
@FacesConverter(value = "groupConverter", managed = true)
public class GroupConverter implements Converter {
@Inject
GroupService groupService;
@Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
if(null == value || value.isEmpty()) {
return null;
}
try {
return groupService.getGroupWithCollections(Integer.parseInt(value));
} catch (NumberFormatException e) {
throw new ConverterException(new FacesMessage("Invalid Group ID"), e);
}
}
@Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
Group group = (Group) value;
if (null == group) {
return "";
}
if(null != group.getId()) {
return ""+group.getId();
} else {
throw new ConverterException(new FacesMessage("Invalid Group ID"));
}
}
}
When the used hits a button I'm calling the following service:
@Transactional(Transactional.TxType.REQUIRED)
public User persistWithDeps(User user2Save) {
User user = user = baseEm.contains(user2Save) ? user2Save : baseEm.merge(user2Save);
// Check if we have a new object (case when: baseEm.merge(user2Save))
if (user != user2Save) {
if (null != user.getGroupList()) {
// remove groups
if (!user2Save.getGroupList().containsAll(user.getGroupList())) {
// remove groups from user
Iterator<Group> iterator = user.getGroupList().iterator();
while (iterator.hasNext()) {
Group group = iterator.next();
if (!user2Save.getGroupList().contains(group)) {
group.getuser2SaveList().remove(user);
iterator.remove();
}
}
}
// Add groups to user
user.getGroupList().forEach(group -> {
if (!group.getUserList().contains(user)) {
group.getUserList().add(user);
}
});
}
}
baseEm.persist(user);
return user;
}
hibernate jsf primefaces many-to-many jsf-2.3
First of all some details von the used software: I'm working with primefaces 6.2.11 on Wildfly 14.0.1Final with JSF 2.3.
Problemdescription: I have two entities (User & Group) related many2many and I want to remove a relation on the side which is not the owner (the entity with the mappedBy). I cant change the owner sides because this is legacy code. I know that I have to remove the relation on both ends but my code does not work. Adding values to the list is no problem but removing them is not possible.
I tried this several days ago with Wildfly 10 and it was okay but not with the new one.
One problem is that the primefaces list does no notify me via ajax event when an item will be removed. If this would be the case I could handle the remove from my group list and user list in the group. Because I dont have an event like that I tried to handle this in my service which tries to save the user.
I have two entities:
@Entity
@Table(name = "USER")
public class User implements Serializable {
private static final long serialVersionUID = -1699265057144017750L;
@Column(name = "ID", nullable = false)
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column(name = "USER_NAME", length = 45, unique = true)
@Basic
@NotNull
private String userName;
@ManyToMany(fetch = FetchType.LAZY, targetEntity = Group.class, mappedBy = "userList")
@OrderBy("groupName")
private Set<Group> groupList;
// getter setter ...
}
@Entity
@Table(name = "GROUP")
public class User implements Serializable {
private static final long serialVersionUID = -3403518747362744630L;
@Column(name = "ID", nullable = false)
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@ManyToMany(fetch = FetchType.LAZY, targetEntity = User.class, cascade = {CascadeType.MERGE, CascadeType.PERSIST})
@JoinTable(name = "USER_GROUP",
joinColumns = {@JoinColumn(name = "GROUP_ID", referencedColumnName = "ID")},
inverseJoinColumns = {@JoinColumn(name = "USER_ID", referencedColumnName = "ID")})
@OrderBy("userName")
private Set<User> userList;
// getter setter ...
}
I created a form to edit users. This form has a lot of inputs and one is for adding and removing groups from the user. It is a simpel primefaces selectCheckboxMenu. This allowes the user to choose new groups and remove old groups. The value(s) is/are directly retrieved from the user entity and the values which can be selected are served by an seperate service.
<p:selectCheckboxMenu id="groupList" multiple="true" filter="true" filterMatchMode="contains"
value="#{editUserBean.authUser.groupList}"
required="true" requiredMessage="At least one group is needed"
converter="cs.argos.gui.jsf.converter.groupConverter" collectionType="java.util.LinkedHashSet">
<f:selectItems value="#{groupService.groups}" var="group" itemValue="#{group}" itemLabel="#{group.authGroupName}"/>
</p:selectCheckboxMenu>
Converter:
@FacesConverter(value = "groupConverter", managed = true)
public class GroupConverter implements Converter {
@Inject
GroupService groupService;
@Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
if(null == value || value.isEmpty()) {
return null;
}
try {
return groupService.getGroupWithCollections(Integer.parseInt(value));
} catch (NumberFormatException e) {
throw new ConverterException(new FacesMessage("Invalid Group ID"), e);
}
}
@Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
Group group = (Group) value;
if (null == group) {
return "";
}
if(null != group.getId()) {
return ""+group.getId();
} else {
throw new ConverterException(new FacesMessage("Invalid Group ID"));
}
}
}
When the used hits a button I'm calling the following service:
@Transactional(Transactional.TxType.REQUIRED)
public User persistWithDeps(User user2Save) {
User user = user = baseEm.contains(user2Save) ? user2Save : baseEm.merge(user2Save);
// Check if we have a new object (case when: baseEm.merge(user2Save))
if (user != user2Save) {
if (null != user.getGroupList()) {
// remove groups
if (!user2Save.getGroupList().containsAll(user.getGroupList())) {
// remove groups from user
Iterator<Group> iterator = user.getGroupList().iterator();
while (iterator.hasNext()) {
Group group = iterator.next();
if (!user2Save.getGroupList().contains(group)) {
group.getuser2SaveList().remove(user);
iterator.remove();
}
}
}
// Add groups to user
user.getGroupList().forEach(group -> {
if (!group.getUserList().contains(user)) {
group.getUserList().add(user);
}
});
}
}
baseEm.persist(user);
return user;
}
hibernate jsf primefaces many-to-many jsf-2.3
hibernate jsf primefaces many-to-many jsf-2.3
edited Nov 20 at 9:41
asked Nov 20 at 7:27
Sebastian S.
123212
123212
1
"code does not work" is not that self explaining. As you did not clarify how it does not work (error message in log, console or browser, methods not invoked anyway, so many other possibilities) I can only guess that your code does not compile becaus you useuser2Save
as varialbe and type.
– Selaron
Nov 20 at 8:38
Sorry for my bad explanation. The codes does compile, this was a type caused by stripping down my example for stackoverflow. The problem is, that I cant delete any group from the list. Hibernate does not delete relation
– Sebastian S.
Nov 20 at 9:42
Hence a Minimal, Complete, and Verifiable example is always required. And did you try to add ajax to your select to keep track of what is and what is not selected?
– Kukeltje
Nov 20 at 9:42
1
I can try to create a more complete example, later. Yes, I added some ajax and everything is just fine. I pass the correct list to the merge/persist method but hibernate does not execute any delete statement.
– Sebastian S.
Nov 20 at 9:46
1
Then it is not a jsf(2.3) or PrimeFaces issue but a pure hibernate (or even JPA) question. Maybe creating a simple unittest would be better
– Kukeltje
Nov 20 at 9:49
add a comment |
1
"code does not work" is not that self explaining. As you did not clarify how it does not work (error message in log, console or browser, methods not invoked anyway, so many other possibilities) I can only guess that your code does not compile becaus you useuser2Save
as varialbe and type.
– Selaron
Nov 20 at 8:38
Sorry for my bad explanation. The codes does compile, this was a type caused by stripping down my example for stackoverflow. The problem is, that I cant delete any group from the list. Hibernate does not delete relation
– Sebastian S.
Nov 20 at 9:42
Hence a Minimal, Complete, and Verifiable example is always required. And did you try to add ajax to your select to keep track of what is and what is not selected?
– Kukeltje
Nov 20 at 9:42
1
I can try to create a more complete example, later. Yes, I added some ajax and everything is just fine. I pass the correct list to the merge/persist method but hibernate does not execute any delete statement.
– Sebastian S.
Nov 20 at 9:46
1
Then it is not a jsf(2.3) or PrimeFaces issue but a pure hibernate (or even JPA) question. Maybe creating a simple unittest would be better
– Kukeltje
Nov 20 at 9:49
1
1
"code does not work" is not that self explaining. As you did not clarify how it does not work (error message in log, console or browser, methods not invoked anyway, so many other possibilities) I can only guess that your code does not compile becaus you use
user2Save
as varialbe and type.– Selaron
Nov 20 at 8:38
"code does not work" is not that self explaining. As you did not clarify how it does not work (error message in log, console or browser, methods not invoked anyway, so many other possibilities) I can only guess that your code does not compile becaus you use
user2Save
as varialbe and type.– Selaron
Nov 20 at 8:38
Sorry for my bad explanation. The codes does compile, this was a type caused by stripping down my example for stackoverflow. The problem is, that I cant delete any group from the list. Hibernate does not delete relation
– Sebastian S.
Nov 20 at 9:42
Sorry for my bad explanation. The codes does compile, this was a type caused by stripping down my example for stackoverflow. The problem is, that I cant delete any group from the list. Hibernate does not delete relation
– Sebastian S.
Nov 20 at 9:42
Hence a Minimal, Complete, and Verifiable example is always required. And did you try to add ajax to your select to keep track of what is and what is not selected?
– Kukeltje
Nov 20 at 9:42
Hence a Minimal, Complete, and Verifiable example is always required. And did you try to add ajax to your select to keep track of what is and what is not selected?
– Kukeltje
Nov 20 at 9:42
1
1
I can try to create a more complete example, later. Yes, I added some ajax and everything is just fine. I pass the correct list to the merge/persist method but hibernate does not execute any delete statement.
– Sebastian S.
Nov 20 at 9:46
I can try to create a more complete example, later. Yes, I added some ajax and everything is just fine. I pass the correct list to the merge/persist method but hibernate does not execute any delete statement.
– Sebastian S.
Nov 20 at 9:46
1
1
Then it is not a jsf(2.3) or PrimeFaces issue but a pure hibernate (or even JPA) question. Maybe creating a simple unittest would be better
– Kukeltje
Nov 20 at 9:49
Then it is not a jsf(2.3) or PrimeFaces issue but a pure hibernate (or even JPA) question. Maybe creating a simple unittest would be better
– Kukeltje
Nov 20 at 9:49
add a comment |
1 Answer
1
active
oldest
votes
up vote
1
down vote
It is JPA related. You put the cascade on the wrong entity:
@ManyToMany(fetch = FetchType.LAZY, targetEntity = Group.class, mappedBy = "userList", , cascade = {CascadeType.MERGE, CascadeType.PERSIST})
Then, you do persist i.s.o. merge:
baseEm.merge(user);
Persist must only be used for creating new objects. Since you are updating an object, use merge.
Also, the method persistWithDeps is written in a very bizar way. When Primefaces correctly updates the groupList in the User object, this is sufficient:
public User persistWithDeps(User user2Save) {
return baseEm.merge(user2save);
}
JPA will automatically generate the necessary SQL for removing or adding the group entity in the many to many table.
Also be aware that the add and remove operations are based on equals and hashcode behind the scenes. They must be correctly programmed, and if not it can have the effect that nothing happens.
So, try to replace the method with mine. If it still doesn't work, put a breakpoint on return baseEm.merge(user2save);
and check user.getGroupList(). It must have the correct number of groups you expect. If it is like this, and the merge still doesn't work, you need to change your equals and hashcode methods. If on the breakpoint you have an incorrect number of groups you didn't expect, it means something went wrong between your JSF linked bean (editUserBean) and the call to persistWithDeps.
Btw, your selectCheckboxMenu tag and converter looks ok.
Good luck!
add a comment |
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
1
down vote
It is JPA related. You put the cascade on the wrong entity:
@ManyToMany(fetch = FetchType.LAZY, targetEntity = Group.class, mappedBy = "userList", , cascade = {CascadeType.MERGE, CascadeType.PERSIST})
Then, you do persist i.s.o. merge:
baseEm.merge(user);
Persist must only be used for creating new objects. Since you are updating an object, use merge.
Also, the method persistWithDeps is written in a very bizar way. When Primefaces correctly updates the groupList in the User object, this is sufficient:
public User persistWithDeps(User user2Save) {
return baseEm.merge(user2save);
}
JPA will automatically generate the necessary SQL for removing or adding the group entity in the many to many table.
Also be aware that the add and remove operations are based on equals and hashcode behind the scenes. They must be correctly programmed, and if not it can have the effect that nothing happens.
So, try to replace the method with mine. If it still doesn't work, put a breakpoint on return baseEm.merge(user2save);
and check user.getGroupList(). It must have the correct number of groups you expect. If it is like this, and the merge still doesn't work, you need to change your equals and hashcode methods. If on the breakpoint you have an incorrect number of groups you didn't expect, it means something went wrong between your JSF linked bean (editUserBean) and the call to persistWithDeps.
Btw, your selectCheckboxMenu tag and converter looks ok.
Good luck!
add a comment |
up vote
1
down vote
It is JPA related. You put the cascade on the wrong entity:
@ManyToMany(fetch = FetchType.LAZY, targetEntity = Group.class, mappedBy = "userList", , cascade = {CascadeType.MERGE, CascadeType.PERSIST})
Then, you do persist i.s.o. merge:
baseEm.merge(user);
Persist must only be used for creating new objects. Since you are updating an object, use merge.
Also, the method persistWithDeps is written in a very bizar way. When Primefaces correctly updates the groupList in the User object, this is sufficient:
public User persistWithDeps(User user2Save) {
return baseEm.merge(user2save);
}
JPA will automatically generate the necessary SQL for removing or adding the group entity in the many to many table.
Also be aware that the add and remove operations are based on equals and hashcode behind the scenes. They must be correctly programmed, and if not it can have the effect that nothing happens.
So, try to replace the method with mine. If it still doesn't work, put a breakpoint on return baseEm.merge(user2save);
and check user.getGroupList(). It must have the correct number of groups you expect. If it is like this, and the merge still doesn't work, you need to change your equals and hashcode methods. If on the breakpoint you have an incorrect number of groups you didn't expect, it means something went wrong between your JSF linked bean (editUserBean) and the call to persistWithDeps.
Btw, your selectCheckboxMenu tag and converter looks ok.
Good luck!
add a comment |
up vote
1
down vote
up vote
1
down vote
It is JPA related. You put the cascade on the wrong entity:
@ManyToMany(fetch = FetchType.LAZY, targetEntity = Group.class, mappedBy = "userList", , cascade = {CascadeType.MERGE, CascadeType.PERSIST})
Then, you do persist i.s.o. merge:
baseEm.merge(user);
Persist must only be used for creating new objects. Since you are updating an object, use merge.
Also, the method persistWithDeps is written in a very bizar way. When Primefaces correctly updates the groupList in the User object, this is sufficient:
public User persistWithDeps(User user2Save) {
return baseEm.merge(user2save);
}
JPA will automatically generate the necessary SQL for removing or adding the group entity in the many to many table.
Also be aware that the add and remove operations are based on equals and hashcode behind the scenes. They must be correctly programmed, and if not it can have the effect that nothing happens.
So, try to replace the method with mine. If it still doesn't work, put a breakpoint on return baseEm.merge(user2save);
and check user.getGroupList(). It must have the correct number of groups you expect. If it is like this, and the merge still doesn't work, you need to change your equals and hashcode methods. If on the breakpoint you have an incorrect number of groups you didn't expect, it means something went wrong between your JSF linked bean (editUserBean) and the call to persistWithDeps.
Btw, your selectCheckboxMenu tag and converter looks ok.
Good luck!
It is JPA related. You put the cascade on the wrong entity:
@ManyToMany(fetch = FetchType.LAZY, targetEntity = Group.class, mappedBy = "userList", , cascade = {CascadeType.MERGE, CascadeType.PERSIST})
Then, you do persist i.s.o. merge:
baseEm.merge(user);
Persist must only be used for creating new objects. Since you are updating an object, use merge.
Also, the method persistWithDeps is written in a very bizar way. When Primefaces correctly updates the groupList in the User object, this is sufficient:
public User persistWithDeps(User user2Save) {
return baseEm.merge(user2save);
}
JPA will automatically generate the necessary SQL for removing or adding the group entity in the many to many table.
Also be aware that the add and remove operations are based on equals and hashcode behind the scenes. They must be correctly programmed, and if not it can have the effect that nothing happens.
So, try to replace the method with mine. If it still doesn't work, put a breakpoint on return baseEm.merge(user2save);
and check user.getGroupList(). It must have the correct number of groups you expect. If it is like this, and the merge still doesn't work, you need to change your equals and hashcode methods. If on the breakpoint you have an incorrect number of groups you didn't expect, it means something went wrong between your JSF linked bean (editUserBean) and the call to persistWithDeps.
Btw, your selectCheckboxMenu tag and converter looks ok.
Good luck!
edited Nov 29 at 8:36
answered Nov 29 at 8:23
devcjm
213
213
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53388142%2fjsf-selectcheckboxmenu-hibernate-manytomany-remove-values%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
"code does not work" is not that self explaining. As you did not clarify how it does not work (error message in log, console or browser, methods not invoked anyway, so many other possibilities) I can only guess that your code does not compile becaus you use
user2Save
as varialbe and type.– Selaron
Nov 20 at 8:38
Sorry for my bad explanation. The codes does compile, this was a type caused by stripping down my example for stackoverflow. The problem is, that I cant delete any group from the list. Hibernate does not delete relation
– Sebastian S.
Nov 20 at 9:42
Hence a Minimal, Complete, and Verifiable example is always required. And did you try to add ajax to your select to keep track of what is and what is not selected?
– Kukeltje
Nov 20 at 9:42
1
I can try to create a more complete example, later. Yes, I added some ajax and everything is just fine. I pass the correct list to the merge/persist method but hibernate does not execute any delete statement.
– Sebastian S.
Nov 20 at 9:46
1
Then it is not a jsf(2.3) or PrimeFaces issue but a pure hibernate (or even JPA) question. Maybe creating a simple unittest would be better
– Kukeltje
Nov 20 at 9:49