• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

testing jpa - OneToMany

 
Greenhorn
Posts: 26
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I'm trying out some basic stuff with EJB3/JPA. Using glassfish V2 and first Toplink then Hibernate (does seem to work better).

I've made what I think is the most basic example possible, but somehow it doesn't work:

I'll post the code here, only the relevant bits:

I have a Medic entity:



And a Patient entity which has no relations (the oneToMany is unidirectional) and only an @Id / @GeneratedValue annotation (same as medic)

Then I have a SLSB:



Now when I create a Medic and then call this createPatient a few times the following happens:

Using Toplink => patients are created and assigned correct Ids, but the jointable (which is also correctly created) remains empty.

In Hibernate the same thing happens, but there the last patient / medic combo is found in the MEDIC_PATIENT table. But if I then call Medic.getPatients().size() it still says 0.

I'm sure I just did something stupid, but I just can't see what.
 
Ranch Hand
Posts: 153
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hello Peter,

Generally most of the OnetoMany relationship should be bidirectional. In your case @OneToMany relationship exists between the owning side Medic and the Patient. Your join table is MEDIC_PATIENT which should be specified on the target (Patient) entity with a @ManytoOne(mappedBy="patients") annotation. You should also use the @JoinTable annotation on the Patient entity.

JPA won't know of your join table unless you specify it somewhere.
 
peter coster
Greenhorn
Posts: 26
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Shailesh,

Thank you for the reply. I'm using schema generation. And the jointable is automatically generated. So the JPA provider does now about it. It just doesn't seem to understand that it needs to persist the relation.

However, I did try to do your suggestion and make it bidirectional, even adding patient.setMedic(mergedMedic); explicitly to the code. But this didn't change the outcome.
 
Shailesh Kini
Ranch Hand
Posts: 153
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hello Peter,

Can you please add the Patient entity code to your post?
 
peter coster
Greenhorn
Posts: 26
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
This is the patient code - meanwhile with the manytoone relationship:



I've also added to the onetomany annotation in the medic class.

what happens now is that the manytoneone side works and medicIds are stored in the patient table (so no jointable, just a joincolumn ) medic.Getpatients has no result..

I don't understand....
 
author
Posts: 304
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by peter coster:
I'm trying out some basic stuff with EJB3/JPA. Using glassfish V2 and first Toplink then Hibernate (does seem to work better).


Peter,

Don't blame TopLink or Hibernate for working better or less better in this case. The problem is your code :-). I can't give you all the details because I don't know the code that invokes the createPatient() method, but I can give you a good hint.

You are obtaining (creating?) a Medic somewhere in the calling code and passing it into the createPatient() method. Then you (correctly) in the createPatient() method use the medic returned from the merge() call and modify it by adding a patient. The problem is that you are never refreshing your original medic that you are passing in. Depending upon where the transaction is demarcated, and when the provider actually allocated the generated id, the merge may be merging in an entirely new object, or it may be overwriting the previous medic (and its previous relationship) with the client version of the medic that does not have that modified relationship in it.

The code to fix it would be to simply return the medic (with its associated related patients hanging off it) instead of the patient, and then use the returned medic in the calling code to pass back into createPatient() the next time.

Note that this does not have anything to do with whether the relationship is uni or bidirectional. Both cases should work fine once you have fixed your code.
 
peter coster
Greenhorn
Posts: 26
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Mike,

It works now, and looking at it now it does seem very logic, I can't believe that I didn't see this earlier, lesson learned, thanks.

However I did find other things working less well on toplink essentials, which is a shame as I really like Glassfish.
 
Mike Keith
author
Posts: 304
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Peter,

What do you mean by "less well"? Did you find a bug during your experiences, or was it an extra feature that you felt was missing? From the configuration perspective picking up a single jar and putting it in your classpath seems to me to be the simplest thing possible, but I'm sure the contributors to the TopLink Essentials project would like to hear any feedback that you may have.
 
Shailesh Kini
Ranch Hand
Posts: 153
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Mike,

First of all I would like to thank you for the wonderful Pro EJB 3: Java Persistence API book. It is a must have for everyone interested in working with or just wanting to know about JPA.

We are using Toplink essentials and just went live with it. No bugs to report so far.

In my opinion the most important feature missing from JPA is the built-in support for clustering. However, there are different approaches available to add it manually.
[ January 15, 2008: Message edited by: Shailesh Kini ]
 
peter coster
Greenhorn
Posts: 26
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Mike,

Like I said, this was just a quick test for me. So I certainly wouldn't use the word bug.
But these are a few things:

  • I used auto schema creation - this caused warnings for sequences that already existed, hibernate does it different.
  • the combination of OneToMany and a joinColumn was not allowed, I tought this was legal ? Haven't tried it with hibernate.


  • This experience and comments from colleagues who had started projects with Toplink but switched to Hibernate because of problems (don't know what specifically), made me switch. More to have a quick result then for anything else really.
     
    Mike Keith
    author
    Posts: 304
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Thanks, Shailesh. Glad to hear about your successes.

    Originally posted by peter coster:
    Mike,

  • I used auto schema creation - this caused warnings for sequences that already existed, hibernate does it different.


  • Okay. I guess that's just a matter of taste and what you are used to. Some people like to be told if an object is being reused instead of being created and initialized.
  • the combination of OneToMany and a joinColumn was not allowed, I tought this was legal ? Haven't tried it with hibernate.

  • This kind of uni-directional foreign key OneToMany is not legal in JPA 1.0, and we tried hard to discourage people from supporting such a thing. It is viewed as being a bad mapping strategy and contrary to good object-relational design. Unfortunately we will probably end up including support for it in JPA 2.0, though, but I don't like it.
    [/QB]
    This experience and comments from colleagues who had started projects with Toplink but switched to Hibernate because of problems (don't know what specifically), made me switch. More to have a quick result then for anything else really.[/QB]
    I can't speak to third-hand general comments, but I would be surprised if there was any substance to it. In my experience (I have talked to a lot of people at a lot of conferences and user groups) and I find that all of the major providers have done a pretty good job on their JPA impls. The bug count does not vary much in quantity between them (I can actually list a couple of gotcha bugs from each vendor that regularly get people ;-). They are just different, and in the end it comes down to taste, and which features people feel more comfortable with. If someone feels more comfortable with one then they can switch, and if switching was fairly easy to do then we did our spec job well, I think.
     
    If you believe you can tell me what to think, I believe I can tell you where to go. Go read this tiny ad!
    a bit of art, as a gift, that will fit in a stocking
    https://gardener-gift.com
    reply
      Bookmark Topic Watch Topic
    • New Topic