• 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

How to add JPA ManyToMany records?

 
Ranch Hand
Posts: 235
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi All,

I would like to find out how to add records to JPA ManyToMany relationship tables. Below are the code snippets for each Java EE 5 components so far:

These createCustomer() methods resulted in multiple identical telephone numbers but I am looking for a unique normalize record in both tables.

I am running JDK1.6.0_17, GF2.1 on Windows XP.

Please advice on how this approach could be achieved. There are a few examples available but none specific to this requirement.

Any assistance would be much appreciated.

Thanks in advance,

Jack

 
Ranch Hand
Posts: 553
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
If you want the same phone number, then you need to use the same one, not a new instance. Generally you would need to query it.

If the EJB is a remote bean, then you would need to first find the phone number and call merge in the create customer instead of persist.

In general, objects like a phone number are normally not worth sharing, and each Customer would have a OneToMany to a dependent set of phone numbers.


 
Jack Bush
Ranch Hand
Posts: 235
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi James,

Thanks for responding to this threat.

JS wrote:
> If you want the same phone number, then you need to use the same one, not a new instance. Generally
you would need to query it.

> If the EJB is a remote bean, then you would need to first find the phone number and call merge in the
create customer instead of persist.


Good suggestion but I need 2 clarification due to lack of experience in JPA:

( i ) Currently, there is only the following CustomerBean to service Customer object:



Are you suggesting that I should create the following TelephoneBean in order to determine whether a telephone number has been added using its findTelephone():


( i )My dilemma is how to link the telephone_id returned from findTelephone(String telephone) to a new Customer instance. Any idea on how this could be achieved?

( ii ) At the same time, would updateTelephone(Telephone telephone) be able to merge current telephone number with existing record even though this step does not appears to be necessary, unless it will also link the uniquely merged telephone record with newly created Customer entity?

( iii ) Lastly, would by adding existing telephone as suggested with the following statements correctly link the same telephone record, created earlier to both wife & son with using merge() in updateTelephone method:


JS wrote:
> In general, objects like a phone number are normally not worth sharing, and each Customer would have a OneToMany to a dependent set of phone numbers.


Fair enough. This ManyToMany Customer Telephone relational model used is meant to as an example only, but the actual data used in my application is critical that must be stored in a separate secondary table.

Again, your advice would be invaluable to coming up with best simple working solution.

Thanks again,

Jack
 
Jack Bush
Ranch Hand
Posts: 235
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi James,

Please excuse my midnight typing error for having entered Hotel object as opposed to Telephone in CustomerBean . Below are the code snippets for CustomerBean and TelephoneBean:


Which object would you suggest to merge? The Customer or Telephone? More importantly, will it associate the Telephone record found with a new Customer object?

Thanks,

Jack
 
James Sutherland
Ranch Hand
Posts: 553
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
A few things,

1 - I would still recommend making the Telephone a dependent part of the Customer, have a OneToMany, and don't worry about trying to share phone numbers.

2 - If you want to share phone numbers, creating the Telephone SessionBean is correct, you will need to use the findTelephone() to get the existing Telephone, and assign it to the Customer object before insert/updating it.

3 - For Customer your insert() must use merge() not persist, as the telephone may need to be merged if it is existing (merge works for both new and existing objects)

4 - So find a Telephone by name just use, "Select t from Telephone t where t.number = :number"

5 - Using the name and dob for the CustomPK is a very bad design, generate an Id instead. (what if there name changes?)

 
Jack Bush
Ranch Hand
Posts: 235
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi James,

The first attempt to implement your suggestion 1, 3 and 4 with the following code changes:


However, this change has resulted in the following exception:

com.sun.enterprise.appclient.MainWithModuleSupport <init>
WARNING: ACC003: Application threw an exception.
javax.ejb.EJBException: nested exception is: java.rmi.ServerException: RemoteException occurred in server thread; nested exception is:
java.rmi.RemoteException: null; nested exception is:
java.lang.IllegalStateException: Query argument number not found in the list of parameters provided during query execution.
java.rmi.ServerException: RemoteException occurred in server thread; nested exception is:
java.rmi.RemoteException: null; nested exception is:
java.lang.IllegalStateException: Query argument number not found in the list of parameters provided during query execution.
at com.sun.corba.ee.impl.javax.rmi.CORBA.Util.mapSystemException(Util.java:243)
Likewise, GF 2.1 server log showed similar error exception:

EJB5018: An exception was thrown during an ejb invocation on [TelephoneBean]
javax.ejb.EJBException
at com.sun.ejb.containers.BaseContainer.processSystemException(BaseContainer.java:3894)
at com.sun.ejb.containers.BaseContainer.completeNewTx(BaseContainer.java:3794)
at com.sun.ejb.containers.BaseContainer.postInvokeTx(BaseContainer.java:3596)
at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:1379)
at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:1316)
at com.sun.ejb.containers.EJBObjectInvocationHandler.invoke(EJBObjectInvocationHandler.java:210)
at com.sun.ejb.containers.EJBObjectInvocationHandlerDelegate.invoke(EJBObjectInvocationHandlerDelegate.java:117)
at $Proxy47.findHotel(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.sun.corba.ee.impl.presentation.rmi.ReflectiveTie._invoke(ReflectiveTie.java:154)
at com.sun.corba.ee.impl.protocol.CorbaServerRequestDispatcherImpl.dispatchToServant(CorbaServerRequestDispatcherImpl.java:687)
at com.sun.corba.ee.impl.protocol.CorbaServerRequestDispatcherImpl.dispatch(CorbaServerRequestDispatcherImpl.java:227)
at com.sun.corba.ee.impl.protocol.CorbaMessageMediatorImpl.handleRequestRequest(CorbaMessageMediatorImpl.java:1846)
at com.sun.corba.ee.impl.protocol.CorbaMessageMediatorImpl.handleRequest(CorbaMessageMediatorImpl.java:1706)
at com.sun.corba.ee.impl.protocol.CorbaMessageMediatorImpl.handleInput(CorbaMessageMediatorImpl.java:1088)
at com.sun.corba.ee.impl.protocol.giopmsgheaders.RequestMessage_1_2.callback(RequestMessage_1_2.java:223)
at com.sun.corba.ee.impl.protocol.CorbaMessageMediatorImpl.handleRequest(CorbaMessageMediatorImpl.java:806)
at com.sun.corba.ee.impl.protocol.CorbaMessageMediatorImpl.dispatch(CorbaMessageMediatorImpl.java:563)
at com.sun.corba.ee.impl.protocol.CorbaMessageMediatorImpl.doWork(CorbaMessageMediatorImpl.java:2567)
at com.sun.corba.ee.impl.orbutil.threadpool.ThreadPoolImpl$WorkerThread.run(ThreadPoolImpl.java:555)
Caused by: java.lang.IllegalStateException: Query argument number not found in the list of parameters provided during query execution.
at oracle.toplink.essentials.internal.ejb.cmp3.base.EJBQueryImpl.processParameters(EJBQueryImpl.java:559)
at oracle.toplink.essentials.internal.ejb.cmp3.base.EJBQueryImpl.executeReadQuery(EJBQueryImpl.java:329)
at oracle.toplink.essentials.internal.ejb.cmp3.base.EJBQueryImpl.getResultList(EJBQueryImpl.java:478)
at ejb.TelephoneBean.findTelephone(TelephoneBean.java:35)
The second attempt below used example from a recent EJB (JBoss) exercise when using createQuery:



However, this approach produced other communication errors that I will ignore for the moment. As a result of different version/syntax around, could I ask if you could provide the correct code for .findTelephone()?

Lastly, suggestion 5 is correct but once again I am simply using name and dob for CustomPK as an example in this threat only. Good advice nevertheless.

Thanks again,

Jack
 
James Sutherland
Ranch Hand
Posts: 553
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
"FROM Telephone t where t.number = :number" is not valid JPQL, you need a select clause.

 
Jack Bush
Ranch Hand
Posts: 235
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi James,

There has been a significant reduction on the number of Telephone duplicate records added from 6 to 2 after having implemented all the above suggestions except number 3, since the use of Customer.merge() has resulted in 6 records been created again. However, I am still puzzled as to why the second Telephone record was created in the first place even though the debug statements (System.out.println) displayed only a single Customer.create(Telephone) line.

The same duplicate Telephone records exist whether a OneToMany (Unidirectional) or ManyToMany (bi-directional) JPA relational Model is used. Below are the code snippets of both ImportCustomerApplicationClient.java and TelephoneBean.java records:


Any idea on how I could further diagnose where the remaining duplicate Telephone record, and why Customer.persist(Telephone) got better result than Customer.merge(Telephone)?

Thanks a lot,

Jack
 
Jack Bush
Ranch Hand
Posts: 235
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Sorry James,

Yet another typing error. Here is the correct Telephone.java:


Thanks,

Jack
 
Consider Paul's rocket mass heater.
reply
    Bookmark Topic Watch Topic
  • New Topic