merge/update object in collection

View: New views
2 Messages — Rating Filter:   Alert me  

merge/update object in collection

by SMaton :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi everyone,

I've a strange problem on hand which I've been discussing with several people but up to date no one could help me. So, here we go:

I've a class named Investor which holds a collection of email addresses. Each email address is itself a class object containing the email string and the email type (private, business, ...).

The downstripped versions look like this:

@Entity
@Table(name = "INVESTORS")
@UniqueInvestorName
public class Investor extends BasicBO implements
                be.sidema.model.Investor {

        @OneToMany(fetch=FetchType.LAZY, cascade= {CascadeType.ALL}, targetEntity=be.sidema.model.jpa.InvestorEmail.class)
        @JoinColumn(name="investor_id")
        @PrivateOwned
        public List<InvestorEmail> emails = new ArrayList<InvestorEmail>();

        public List<? extends InvestorEmail> getEmails() {
                return emails;
        }

        public void setEmails(List<InvestorEmail> emails) {
                Object oldValue = this.emails;
                this.emails = emails;
                firePropertyChange(PROPERTY_EMAILS, oldValue, this.emails);
        }

        public void addEmail(InvestorEmail _email) {
                int oldSize = this.emails.size();
                emails.add(_email);
                firePropertyChange(PROPERTY_EMAILS, oldSize, this.emails.size());
        }

        public void removeEmail(InvestorEmail _email) {
                int oldSize = this.emails.size();
                emails.remove(_email);
                firePropertyChange(PROPERTY_EMAILS, oldSize, this.emails.size());
        }
}

@Entity
@Table(name = "INVESTOR_EMAILS")
public class InvestorEmail extends BasicBO implements
                be.sidema.model.InvestorEmail {

        @ManyToOne(targetEntity = be.sidema.model.jpa.InvestorEmailType.class, cascade= {CascadeType.ALL})
        @JoinColumn(name = "email_type_id")
        private InvestorEmailType type;

        private String email;

        public InvestorEmailType getType() {
                return type;
        }

        public void setType(InvestorEmailType type) {
                Object oldValue = this.type;
                this.type = type;
                firePropertyChange(PROPERTY_TYPE, oldValue, this.type);
        }

        public String getEmail() {
                return email;
        }

        public void setEmail(String email) {
                Object oldValue = this.email;
                this.email = email;
                firePropertyChange(PROPERTY_EMAIL, oldValue, this.email);
        }
}

@Entity
@Table(name = "INVESTOR_EMAIL_TYPES")
public class InvestorEmailType extends BasicBO implements
be.sidema.model.InvestorEmailType {

        private String type;
       
        public String getType() {
                return type;
        }

        public String toString() {
                return getType();
        }

        public void setType(String type) {
                Object oldValue = this.type;
                this.type = type;
                firePropertyChange(PROPERTY_TYPE, oldValue, this.type);
        }
}

Problem description:

In my database I have an existing Investor who has an existing email address. The email type is set to "business". Within my UI I have opened an editor displaying the investor data. From within this editor I open a second editor enabling me to alter the email address content.

I change the email address content from "Business" to "Private" and do a merge to the InvestorEmailAddress object in my service:

        @Override
        @Transactional
        public InvestorEmail saveEmail(InvestorEmail _email) {
                _email.markCommitted();
                InvestorEmail result = entityManager.merge(_email);
                entityManager.flush();
                return result;
        }

Upon the first merge, the debug output I get is:

UPDATE INVESTOR_EMAILS SET email_type_id = ? WHERE (ID = ?)
        bind => [2, 2451]

I use the return value of the merge operation to update my email address editor.

At this point the data within the collection of my investor reflects the right state (which is "Private").

Without quitting the email editor I then re-edit the address type back from "Private" to "Business". Upon the merge I now get this:

UPDATE INVESTOR_EMAILS SET UPDATED_AT = ?, email_type_id = ? WHERE (ID = ?)
        bind => [2009-10-30 10:21:22.253, 1, 2451]

Any further merge does look like this from now on. The UPDATED_AT is set.


The problem:

After the second and any further merge operation, the content of the collection of my investor does not reflect the changes to the email object. The collection doesn't get "refreshed" upon the next access.

I am aware that the object can change when a merge is done, but I thought that I don't have to "pass by hand" the change to the collection of my investor.

Am I missing something?

Best regards,
Stefan

Re: merge/update object in collection

by James Sutherland :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Not sure what you are doing.  Perhaps include your logs and some more detail on exactly what you are doing, and what you want to occur.

In general merge() is used when you have a copy of an object, normally through object serialization, such as across RMI.  Are you serializing objects to the UI?  Or why are you using merge?  It seems you may be getting confused on you copies of objects and corrupting your object copies.