2 Replies Latest reply on Feb 26, 2009 4:13 PM by cretz

    EJB Merge doesn't merge existing entities

    atish.singh

      Hi everyone,

      i have a client application (Batch) which accesses a self-written EJB Service (running on jboss AS 4.2.3).
      Through this EJB Service the client can retrieve Entities, and merge changes back to the DB.

      My Problem comes up when i try to use the EntityManager.merge() Method. Instead of overwriting the existing entity in the DB, it creates a new entry. Further i´ve noticed that the old entry has Version-Column set to 1 and the new one has Version-Column set to 0.

      I also tried to upgrade to the newest hibernate version but without success.

      Can anyone come up with a solution, how to use the merge method? I appreciate any help!!!!

      I've attached some of my sources:

      merge-method call in EJB Service-Class

       @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
       public void updateDealer(Dealer dealer) {
       em.merge(dealer);
       em.flush();
       }
      


      getEntity / getDealer Call in EJB Service Class
      public Dealer getDealer(int agDealerCode) {
       Dealer dealer = null;
      
       Query q = em.createQuery("From Dealer Where dealerNo = :dealerno");
      
       q.setParameter("dealerno", agDealerCode);
      
       try {
       dealer = (Dealer) q.getSingleResult();
       } catch (NoResultException nrEx) {
       // do nothing just return null value;
       }
       return dealer;
       }
      


      Dealer Entity
      package ch.hstService.client.model;
      
      import java.io.Serializable;
      import java.util.ArrayList;
      import java.util.Collection;
      import java.util.HashSet;
      import java.util.Set;
      
      import javax.persistence.CascadeType;
      import javax.persistence.Column;
      import javax.persistence.Entity;
      import javax.persistence.FetchType;
      import javax.persistence.GeneratedValue;
      import javax.persistence.GenerationType;
      import javax.persistence.Id;
      import javax.persistence.JoinColumn;
      import javax.persistence.OneToMany;
      import javax.persistence.Table;
      import javax.persistence.Version;
      
      @Entity
      @Table(schema="HAENDLERSTAMM")
      public class Dealer implements Serializable {
      
       /******** Properties *******/
      
       @Id @GeneratedValue(strategy=GenerationType.SEQUENCE)
       @Column(name="id_dealer")
       private Long id = null;
      
       @Version
       private Long version;
      
      
       @Column(length=200)
       private String dpName;
      
       @Column(length=50)
       private String dealerType;
      
       @Column(name="market_name_official", length=200)
       private String marketNameOfficial;
      
       @Column(name="owner_dpname", length=200)
       private String ownerDpName;
      
       @Column(name="outlet_type_architectural", length=100)
       private String outletTypeArchitectural;
      
       @Column(length=200)
       private String name;
      
       @Column(name="additional_name", length=200)
       private String additionalName;
      
       @Column(name="vat_number", length=20)
       private String vatNumber;
      
       @Column(name="default_language", length=15)
       private String defaultLanguage;
      
       private int dealerNo;
      
       @Column(length=200)
       private String otherMakes;
      
       @OneToMany(cascade={CascadeType.ALL}, fetch=FetchType.EAGER )
       @JoinColumn(name="id_dealer",referencedColumnName = "id_dealer")
       private Set<Address> addresses = new HashSet<Address>();
      
       @OneToMany(cascade={CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REMOVE}, fetch=FetchType.EAGER)
       @JoinColumn(name="id_dealer",referencedColumnName = "id_dealer")
       private Set<Email> emails = new HashSet<Email>();
      
       @OneToMany(cascade={CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REMOVE }, fetch=FetchType.EAGER)
       @JoinColumn(name="id_dealer",referencedColumnName = "id_dealer")
       private Set<Phone> phones = new HashSet<Phone>();
      
       @OneToMany(mappedBy="dealer", cascade={CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REMOVE}, fetch=FetchType.EAGER)
       @JoinColumn(name="id_dealer")
       private Set<Contract> contracts = new HashSet<Contract>();
      
       @OneToMany(cascade={CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REMOVE }, fetch=FetchType.EAGER)
       @JoinColumn(name="id_dealer",referencedColumnName = "id_dealer")
       private Set<URL> urls = new HashSet<URL>();
      
       /******** Konstruktoren *******/
      
       public Dealer() { //Paket-weiter Konstruktor
       }
      
      
       /******** Getter / Setter *******/
      }
      


        • 1. Re: EJB Merge doesn't merge existing entities
          wolfgangknauf

          Hi,

          hard to say what goes wrong.

          The only possible problem I saw: the field "dealerNo" does not contain a @Column annotation:

          private int dealerNo;


          So maybe this field is not set synchronized with the database, so that your "getDealer" method does not find anything and the client creates a new entity?

          If this does not help: please post the code snippet of your client.
          It might also help to activate SQL logging in persistence.xml and take a look at the SQL statements. You should find an insert statement instead of an update there.

          Hope this helps

          Wolfgang

          • 2. Re: EJB Merge doesn't merge existing entities
            cretz

            A couple of issues I saw:

            1. I think @Version should have a column mapping
            2. The column for the @Id should be unique = true
            3. You should always return the value from merge

            Can you debug and guarantee that version and id fields are populated in your object before you call merge? If not, it will do an insert instead of an update...I think.