[jboss-user] [EJB 3.0] - Only on specific scenario - "all-delete-orphan" was no longe
Oberiko
do-not-reply at jboss.com
Thu Jan 24 16:15:54 EST 2008
Hello.
I have a demo app where the user can enter people and save them to a database. Each person can have 0..* email addresses. The user can also go to a seperate page where the people are listed and select one to edit (taking them back to the first screen, now pre-populated with the person data)
The following use cases work just fine:
* Save new person with and without emails
* Edit person with emails
* Edit person without emails, who formerly had emails
* Edit person (who had an email added, and removed before being saved)
* Save new person without email, go to list page, select the person, then edit them
* Etc.
What's odd is that in one scenario, it doesn't work. That's if I create a new person, save them (without adding any emails), then modify them and save again (still without adding any emails). If, at any point, I add an email, even without saving it, it works.
The error I get when this does happen is as such:
A collection with cascade="all-delete-orphan" was no longer referenced by the owning entity instance
Here's the relevant snippets of my code:
| @Stateful
| @Name("editPerson")
| public class EditPersonForm implements EditPersonLocal {
| @PersistenceContext(type = EXTENDED)
| private EntityManager em;
|
| @In(required = false)
| @Out(scope = ScopeType.PAGE)
| private Person person;
|
| @In(required = false)
| @Out(required = false)
| private EmailAddress emailAddress;
|
| public void addEmail() {
| log.info("Adding email address #0", emailAddress.getUrl());
| person.addEmailAddress(emailAddress);
|
| //Blank the email address entry point
| emailAddress = new EmailAddress();
| }
|
| public void removeEmail(EmailAddress emailAddress) {
| log.info("Removing email address #0", emailAddress.getUrl());
| person.removeEmailAddress(emailAddress);
| }
|
| public void savePerson() {
| if (person.getId() != null){
| em.merge(person);
| }
| else {
| em.persist(person);
| }
|
| // Note that the id of our person was generated and populated.
| facesMessages.add("#0 was saved with an id of #1", person.getName(), person.getId());
|
| log.info(person.getName() + " was saved.");
| }
| }
|
| Name:
| <h:inputText value="#{person.name}" required="true"
| requiredMessage="You need to enter a name" />
| <h:outputText value="#{person.id}" />
| <br />
| <hr />
| Emails:<br />
| URL: <h:inputText value="#{emailAddress.url}" />
| <h:commandButton action="#{editPerson.addEmail()}" value="Add email" />
|
| <h:dataTable id="emailTable" value="#{person.emailAddresses}"
| var="email" rendered="#{not empty person.emailAddresses}">
| <h:column>
| <f:facet name="header">
| <h:outputText value="URL" />
| </f:facet>
| <h:outputText value="#{email.url}" />
| </h:column>
| <h:column>
| <f:facet name="header">
| <h:outputText value="Action" />
| </f:facet>
| <h:commandButton value="Remove"
| action="#{editPerson.removeEmail(email)}" />
| </h:column>
| </h:dataTable>
| <hr />
| <h:commandButton value="Save" action="#{editPerson.savePerson()}" />
| <h:commandButton value="New" action="#{editPerson.newPerson()}" />
|
| @Entity
| @Name("person")
| public class Person {
|
| @Id @GeneratedValue
| private Long id;
|
| @NotNull
| private String name;
|
| @OneToMany(cascade = CascadeType.ALL, fetch=FetchType.EAGER, mappedBy="person")
| @org.hibernate.annotations.Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
| private Collection<EmailAddress> emailAddresses;
|
| public Long getId() {return id;}
| public void setId(Long id) {this.id = id;}
|
| public String getName() {return name;}
| public void setName(String name) {this.name = name;}
|
| public Collection<EmailAddress> getEmailAddresses() {
| return emailAddresses;
| }
| public void setEmailAddresses(Collection<EmailAddress> emailAddresses) {
| this.emailAddresses = emailAddresses;
| }
| public void addEmailAddress(EmailAddress email){
| if (emailAddresses == null) emailAddresses= new ArrayList<EmailAddress>();
| email.setPerson(this);
| emailAddresses.add(email);
| }
| public void removeEmailAddress(EmailAddress emailAddress){
| if (emailAddresses != null){
| emailAddresses.remove(emailAddress);
| }
| }
| }
|
| @Entity
| @Name("emailAddress")
| public class EmailAddress {
|
| @Id @GeneratedValue
| private Long id;
|
| @NotNull
| private String url;
|
| @ManyToOne
| @JoinColumn(name="person_id")
| private Person person;
|
| public Long getId() {return id;}
| public void setId(Long id) {this.id = id;}
|
| public String getUrl() {
| return url;
| }
| public void setUrl(String url) {
| this.url = url;
| }
|
| public Person getPerson() {
| return person;
| }
| public void setPerson(Person person) {
| this.person = person;
| }
| }
|
Now, I have found that if I put the following code right before the "em.merge(person)" (in the top code block), I no longer have this issue and it works.
| if (person.getEmailAddresses() == null)
| person.setEmailAddresses(new ArrayList<EmailAddress>());
|
Is this a known issue? Oh, and I apologize if this is isn't the correct forum for this, I wasn't sure if it was more EJB or Hibernate related.
View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4123200#4123200
Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4123200
More information about the jboss-user
mailing list