Hi All,
I found a bug in Oracle TopLink used with Glassfish. JPA Model is destroyed
when using OneToOne Lazy Connections.
Soft:
Netbeans 6.1, Glassfish-v2ur2 (came together with Netbeans)
Database:mysql
Here is Db Model:
create table tbl1 (
ID INTEGER AUTO_INCREMENT NOT NULL primary key
);
create table tbl2 (
ID INTEGER AUTO_INCREMENT NOT NULL primary key,
tbl1ID INTEGER not null
);
create table tbl3 (
ID INTEGER AUTO_INCREMENT NOT NULL primary key,
tbl2ID INTEGER not null,
UNIQUE KEY `uk_tbl2ID` (`tbl2ID`)
);
alter table tbl2 add constraint fk_tbl1_tbl2 foreign key (tbl1ID) references
tbl1(ID);
alter table tbl3 add constraint fk_tbl2_tbl3 foreign key (tbl2ID) references
tbl2(ID);
insert into tbl1 values(null);
insert into tbl2 values(null,1);
insert into tbl3 values(null,1);
I create an Ejb Project, the Annotated Entities look like that (see package
db in uploaded File):
Tbl1:
@OneToMany(fetch=FetchType.LAZY, mappedBy = "tbl1ID")
private Collection<Tbl2> tbl2Collection;
Tbl2:
@OneToOne(mappedBy = "tbl2ID", fetch=FetchType.LAZY)
private Tbl3 tbl3;
@JoinColumn(name = "tbl1ID", referencedColumnName = "ID")
@ManyToOne
private Tbl1 tbl1ID;
Tbl3:
@JoinColumn(name = "tbl2ID", referencedColumnName = "ID", unique=true,
nullable=false, updatable = false)
@OneToOne
private Tbl2 tbl2ID;
So, Tbl2 said has a one2one Connection with Tbl3, loading it lazily.
Now here is the Business Logic of the Ejb (package dummy in zip):
public void dummy() {
Logger log = Logger.getLogger(DummyBean.class.getName());
log.info("Sp1");
Tbl1 tbl1 = em.find(Tbl1.class, 1);
log.info("Sp1 after read");
for(Tbl2 tbl2 : tbl1.getTbl2Collection()) {
log.info("Sp2 tbl2.id=" + tbl2.getId());
log.info("Sp3:" + tbl2.getTbl3());
log.info("Sp4:" + tbl2.getTbl1ID());
}
log.info("Sp End");
}
I am calling the Ejb Remote.
The Result is the following:
Sp1
db.Tbl2 actually got transformed
TopLink, version: Oracle TopLink Essentials - 2.0.1 (Build b04-fcs
(04/11/2008))
Server: unknown
Detected Vendor platform:
oracle.toplink.essentials.platform.database.MySQL4Platform
connecting(DatabaseLogin(
platform=>DatabasePlatform
user name=> ""
connector=>JNDIConnector datasource name=>null
))
Connected:
jdbc:mysql://localhost:3306/tib?zeroDateTimeBehavior=convertToNull
User: root_at_localhost
Database: MySQL Version: 5.0.45-community-nt-log
Driver: MySQL-AB JDBC Driver Version: mysql-connector-java-5.1.5 (
Revision: ${svn.Revision} )
connecting(DatabaseLogin(
platform=>MySQL4Platform
user name=> ""
connector=>JNDIConnector datasource name=>null
))
Connected: .......
SELECT ID FROM tbl1 WHERE (ID = ?)
bind => [1]
Sp1 after read
SELECT ID, tbl1ID FROM tbl2 WHERE (tbl1ID = ?)
bind => [1]
Sp2 tbl2.id=1
SELECT ID, tbl2ID FROM tbl3 WHERE (tbl2ID = ?)
bind => [1]
Sp3:null
EJB5018: An exception was thrown during an ejb invocation on [DummyBean]
javax.ejb.EJBException
at
com.sun.ejb.containers.BaseContainer.processSystemException(BaseContainer.java:3869)
at
com.sun.ejb.containers.BaseContainer.completeNewTx(BaseContainer.java:3769)
at
com.sun.ejb.containers.BaseContainer.postInvokeTx(BaseContainer.java:3571)
at
com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:1354)
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 $Proxy140.dummy(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.NoSuchMethodError:
db.Tbl2._toplink_gettbl1ID()Ldb/Tbl1;
at db.Tbl2.getTbl1ID(Tbl2.java:62)
at dummy.DummyBean.dummy(DummyBean.java:33)
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.enterprise.security.application.EJBSecurityManager.runMethod(EJBSecurityManager.java:1067)
at
com.sun.enterprise.security.SecurityUtil.invoke(SecurityUtil.java:176)
at
com.sun.ejb.containers.BaseContainer.invokeTargetBeanMethod(BaseContainer.java:2895)
at
com.sun.ejb.containers.BaseContainer.intercept(BaseContainer.java:3986)
at
com.sun.ejb.containers.EJBObjectInvocationHandler.invoke(EJBObjectInvocationHandler.java:203)
... 17 more
So it says "Caused by: java.lang.NoSuchMethodError:
db.Tbl2._toplink_gettbl1ID()Ldb/Tbl1;" that means Tbl2 hasn't a Link to its
Parent Tbl1.
I tried to run an Ejb Client also with
-javaagent:/..../glassfish-v2ur2/lib/toplink-essentials-agent.jar but I got
the same result.
If I delete the "fetch=FetchType.LAZY" in Tbl2 the Code it works:
Sp1
TopLink, version: Oracle TopLink Essentials - 2.0.1 (Build b04-fcs
(04/11/2008))
Server: unknown
Detected Vendor platform:
oracle.toplink.essentials.platform.database.MySQL4Platform
connecting(DatabaseLogin(
platform=>DatabasePlatform
user name=> ""
connector=>JNDIConnector datasource name=>null
))
Connected:
jdbc:mysql://localhost:3306/tib?zeroDateTimeBehavior=convertToNull
User: root_at_localhost
Database: MySQL Version: 5.0.45-community-nt-log
Driver: MySQL-AB JDBC Driver Version: mysql-connector-java-5.1.5 (
Revision: ${svn.Revision} )
connecting(DatabaseLogin(
platform=>MySQL4Platform
user name=> ""
connector=>JNDIConnector datasource name=>null
))
Connected: ....................
SELECT ID FROM tbl1 WHERE (ID = ?)
bind => [1]
Sp1 after read
SELECT ID, tbl1ID FROM tbl2 WHERE (tbl1ID = ?)
bind => [1]
SELECT ID, tbl2ID FROM tbl3 WHERE (tbl2ID = ?)
bind => [1]
Sp2 tbl2.id=1
Sp3:null
Sp4:db.Tbl1[id=1]
Sp End
I hope it will be a fix... it is quite important Lazy Loading :)
http://www.nabble.com/file/p19048060/toplink_one2one_bug_java.zip
toplink_one2one_bug_java.zip
--
View this message in context: http://www.nabble.com/jpa-TopLink-java.lang.NoSuchMethodError%3A-_toplink_get-when-OneToOne-is-Lazy-tp19048060p19048060.html
Sent from the java.net - glassfish persistence mailing list archive at Nabble.com.