-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 11 posts ] 
Author Message
 Post subject: can't insert a collection of elemenets
PostPosted: Wed Mar 04, 2009 11:56 am 
Newbie

Joined: Wed Mar 04, 2009 11:22 am
Posts: 6
Hello,
I have a problem usin annotations. I have one entity (EntA):

Code:


@Entity
@Table(name = "ENT_A")
public class EntA implements Serializable {
...

@Id
public Long getOid() {
      return oid;
   }


[b]@CollectionOfElements(targetElement = EntB.class)
   @JoinTable(name = "ENT_B", joinColumns = @JoinColumn(name = "OID_ENT_A"))
   @MapKey(columns = @Column(name = "CODENTB"))
   public Map<String, EntB > getEntb() {
      return this.entB;
   }[/b]
...



And it have a collection of EntB:


Code:
@Entity
@Table(name = "ENT_B")
@IdClass(EntBPK.class)
public class EntB implements Serializable {
   @Id
   public Long getOidEntA() {
      return oidEntA;
   }

   @Id
   public String getCodEntB() {
      return codEntB;
   }

   @Column(name = "IMP_PART")
   public BigDecimal getImpPart() {
      return impPart;
   }

...
}


This class uses yhis PK:

Code:
public class EntBPK  implements Serializable {

   @Column (name = "OID_ENTA")
   public Long getOidEntA() {
      return oidEntA;
   }

   @Column
   public String getCodEntB() {
      return codPartida;
   }
}


When I try to insert EntityA with save(), there is a problem with entitiB. EntityA saves OK, but EntityB throws errors. In the log of hibernate I see this:


Quote:
Hibernate: insert into ENT_B (OID_ENT_A, CODENTB, entB_OID_ENT_B, entB_codEntB) values (?, ?, ?, ?)



those last fields in insert statement doesn't exists, so Oracle throws an error.

I don't know if I have any mistake with my annotations, but I have tried many things and I couldn't find anything

can anybody see anything wrong?

thanks in advance

R.Hernando


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 04, 2009 12:16 pm 
Expert
Expert

Joined: Thu Jan 08, 2009 6:16 am
Posts: 661
Location: Germany
The problem is, that you use "ENT_B" as Join-Table and as Table for class EntB.

If you don't want to use a seperate JoinTable map it like this:
Code:
    @OneToMany
    @JoinColumn(name = "OID_ENT_A")
    @MapKey(columns=@Column(name="CODENTB"))
    public Map<String, EntB > getEntb() {
      return this.entB;
    }

_________________
-----------------
Need advanced help? http://www.viada.eu


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 04, 2009 12:38 pm 
Newbie

Joined: Wed Mar 04, 2009 11:22 am
Posts: 6
ok, I changed it.

Now the problem is that it doesn't make insert. it does one update for each row.
I think it's trying to change only its PK


Quote:
Hibernate: update ENT_B set OID_ENT_A=?, CODENTB=? where OID_ENT_A=? and codEntA=?


But those rows haven't been inserted yet.

then I tried with @Cascade.ALL and I have a different error. It's before inserting EntA:

log:
Quote:
Hibernate: select SEQ_ENT_A.nextval from dual
Hibernate: select entb_.OID_ENT_A, entb_.codEntB, entb_.IMPPART as IMPPART4_ from ENT_B entb_ where entb_.OID_ENT_A=? and entb_.codEntB=?


error:
Quote:
org.springframework.orm.hibernate3.HibernateSystemException: a different object with the same identifier value was already associated with the session:

Now I supossed that it's trying to find a row of Entb before inserting EntA


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 04, 2009 12:51 pm 
Expert
Expert

Joined: Thu Jan 08, 2009 6:16 am
Posts: 661
Location: Germany
I don't really understand your mapping or your kind of association. Do you really want to have the Id's of EntB as JoinColumns and value-columns for your map?
If not try just different names:
Code:
@OneToMany
    @JoinColumn(name = "EntAJoinColumn")
    @MapKey(columns=@Column(name="EntAMapKey"))
    public Map<String, EntB > getEntb() {
      return this.entB;
    }

_________________
-----------------
Need advanced help? http://www.viada.eu


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 04, 2009 1:09 pm 
Newbie

Joined: Wed Mar 04, 2009 11:22 am
Posts: 6
I'll show my schema:

table ENT_A (Long oid // PK, ...)

table ENT_B (Long oid_ent_a, // foreign key
String codentb,
Bigdecimal impart,...)

I can't use another MapKey, because the unique key with a OID is in entB.

I changed here the names of my app to make it more understandable, if you mean that.

I tried to use Set instead of Map, but I got same result.

I have other table mapped, almost the same, but ENT_B has only three fields, so I could map it as a MAP<String, BigDecimal>, without using another mapped class, and it works fine.


thanks a lot for your time


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 04, 2009 5:23 pm 
Expert
Expert

Joined: Thu Jan 08, 2009 6:16 am
Posts: 661
Location: Germany
Does EntB not have a primary key? If it is oid_ent_A then you actually got a one-to-one association there.

_________________
-----------------
Need advanced help? http://www.viada.eu


Top
 Profile  
 
 Post subject:
PostPosted: Thu Mar 05, 2009 3:23 am 
Newbie

Joined: Wed Mar 04, 2009 11:22 am
Posts: 6
EntB's primary key is the pair OID_ENT_A-codentB, so there is a one-to-many association.

for the moment I have to insert ENT_B making a loop after inserting ENT_A


Top
 Profile  
 
 Post subject:
PostPosted: Thu Mar 05, 2009 4:25 am 
Expert
Expert

Joined: Thu Jan 08, 2009 6:16 am
Posts: 661
Location: Germany
Well, that's a strange case that you got there and I created a test just out of curiosity. This case works as you maybe want, but not if you cascade all operations (maybe its a bug, what do the others say?)
Code:
@Entity
public class Customer {
    private long id;
       
    private Map<String, MapToMany> toManyMap;

    @Id
    @GeneratedValue
    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    @OneToMany(mappedBy="id.customer")
    @MapKey(columns=@Column(name="mapKey"))
    //Does not work on merge
    //    @Cascade({CascadeType.ALL})
    //works
    @Cascade({CascadeType.DELETE, CascadeType.PERSIST})
    public Map<String, MapToMany> getToManyMap() {
        return toManyMap;
    }

    public void setToManyMap(Map<String, MapToMany> toManyMap) {
        this.toManyMap= toManyMap;
    }
}

Code:
@Entity
public class MapToMany {
   
    private MapToManyId id;

    private BigDecimal impPart;

    @EmbeddedId
    public MapToManyId getId() {
        return id;
    }
    public void setId(MapToManyId id) {
        this.id = id;
    }
   

    @Column(name = "IMP_PART")
    public BigDecimal getImpPart() {
        return impPart;
    }
    public void setImpPart(BigDecimal impPart) {
        this.impPart = impPart;
    }
}

Code:
@Embeddable
public class MapToManyId implements Serializable
{
    private Customer customer;   
    private String mapKey;
   
    @ManyToOne
//    @Column(name="customer_id")
    public Customer getCustomer() {
        return customer;
    }
    public void setCustomer(Customer customer) {
        this.customer = customer;
    }
    public String getMapKey() {
        return mapKey;
    }
    public void setMapKey(String mapKey) {
        this.mapKey = mapKey;
    }
   
   
}

Testclass:
Code:
public class TestMap {
    public static void main(String[] args) throws Exception {
        EntityManagerFactory factory = Persistence.createEntityManagerFactory("TestUnit",
                Collections.EMPTY_MAP);
        EntityManager em = factory.createEntityManager();
        Session s = (Session) em.getDelegate();
        em.getTransaction().begin();
       
        Customer customer = em.find(Customer.class, 1L);
               
        if(customer == null)
        {
            fillTables(em);
            em.clear();
            customer = em.find(Customer.class, 1L);
        }

        System.out.println(customer.getToManyMap().size());

        em.clear();
        System.out.println("----Cleared-----");

        //causes exception, if cascaded
        em.merge(customer);
       
        em.flush();

        em.getTransaction().commit();
    }
   
    private static void fillTables(EntityManager em)
    {
        Customer customer = new Customer();
        customer.setToManyMap(new HashMap<String, MapToMany>());
       
        MapToMany mk = new MapToMany();
        MapToManyId id = new MapToManyId();
        id.setCustomer(customer);
        id.setMapKey("key");
        mk.setId(id);
        mk.setImpPart(new BigDecimal(12));
        customer.getToManyMap().put(id.getMapKey(), mk);
       
        em.persist(customer);
        em.flush();
        System.out.println("-----------Finished Inserting---------");
    }
}




So, if you map it like this, you maybe get it working (rating is welcome, then ;-)).

But I am interested in what the others say. Is it a bug, that it does not work (infinite recursion) when merge is cascaded?

_________________
-----------------
Need advanced help? http://www.viada.eu


Top
 Profile  
 
 Post subject:
PostPosted: Thu Mar 05, 2009 5:39 am 
Newbie

Joined: Wed Mar 04, 2009 11:22 am
Posts: 6
:)
it works!

I've changed mapping and now it inserts/deletes Ok.
It's curious, but putting @Cascade({CascadeType.DELETE, CascadeType.PERSIST}) does not insert my collection (because I'm inserting objects with save(Obj)), and I tried to put Cascade.all and works fine.


thanks a lot, mmerder

regards,
R.Hernando


Top
 Profile  
 
 Post subject:
PostPosted: Thu Mar 05, 2009 9:52 am 
Expert
Expert

Joined: Thu Jan 08, 2009 6:16 am
Posts: 661
Location: Germany
CascadeType.SAVE_UPDATE would probably have helped you. Don't you get errors when merging objects of EntA (with an initialized EntB map)?

_________________
-----------------
Need advanced help? http://www.viada.eu


Top
 Profile  
 
 Post subject:
PostPosted: Fri Mar 06, 2009 7:27 am 
Newbie

Joined: Wed Mar 04, 2009 11:22 am
Posts: 6
I need cascade to save and delete, so I'm using all. is it better to use only the types i will use?

I didn't have any error saving objects ( entA whit a full collection of entB). I don't understand exactly what you mean.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 11 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.