You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@openjpa.apache.org by egoosen <eg...@metropolitan.co.za> on 2008/10/01 12:02:27 UTC
Re: Non dirty entity version field update SUPER URGENT!!!
I found the problem.
I performed a test using an entity with the least mapped relationships:
TblPdtcde.class:
// Mapped Relationships
@OneToMany(mappedBy="tblPdtcde",fetch = FetchType.LAZY)
private Collection<TblScmpdt> tblScmpdts = new ArrayList<TblScmpdt>();
@Test
public void testMergeUnchangedEntityAPIs() {
EntityManagerFactory emf =
Persistence.createEntityManagerFactory("status");
EntityManager em = emf.createEntityManager();
TblPdtcde e = em.find(TblPdtcde.class, "F");
// e.getTblScmpdts();
e = ((OpenJPAEntityManager)em).detach(e);
assertNotNull(e);
assertFalse(em.contains(e));
Object eOld = e;
TblPdtcdeDTO dto = copyBean(e, TblPdtcdeDTO.class);
e = copyBean(dto, TblPdtcde.class);
assertNotSame(eOld, e);
em.getTransaction().begin();
em.merge(e);
em.getTransaction().commit();
em.close();
}
The version number increments when I comment out "e.getTblScmpdts();" (which
loads the related TblScmpdt entities).
Copying from the DTO to the entity causes the entity to become dirty,
because the DTO sets the tblScmpdts collection to empty collection instead
of null.
TblPdtcdeDTO:
public Collection getTblScmpdts() {
if (tblScmpdts == null) {
tblScmpdts = new ArrayList();
}
return tblScmpdts;
}
StateManagerImpl.settingObjectField (line 1862) gets called curVal =
Collection<TblScmpdt>, newVal = empty collection.
This therefore triggers a version increment.
This is going to be a tricky one to fix...
--
View this message in context: http://n2.nabble.com/Non-dirty-entity-version-field-update-SUPER-URGENT%21%21%21-tp1120307p1131090.html
Sent from the OpenJPA Users mailing list archive at Nabble.com.
Re: Non dirty entity version field update SUPER URGENT!!!
Posted by egoosen <eg...@metropolitan.co.za>.
Hi Mike,
Yeah, I haven't fully tested this, so I guess this change could introduce
other problems.
To answer your question regarding lazy initialization...
I mostly use lazy initialization, but during the process of copying model to
DTO, and back again, an initially null (lazy field) becomes in this case, an
empty collection, which OpenJPA sees as a dirty field.
For example:
TblFndmst has a Collection<TblScmpdt> tblScmpdts's. (@OneToMany)
TblFndmstDTO (GWT 1.4 friendly DTO) will have the exact same fields as
TblFndmst.
The getter method on TblFndmstDTO:
public Collection getTblScmpdts() {
if (tblScmpdts == null) {
tblScmpdts = new ArrayList();
}
return tblScmpdts;
}
So when the DTO comes into the service layer from the GWT frontend, I use
Dozer to copy DTO fields to a "new" TblFndmst entity, to be merged back into
the datastore.
So during this copy process, the model that was initially loaded with a null
value for tblScmpdts, now has an empty collection value, since the getter
method never returns a null value.
Can you run your unit tests with my change, and see if it breaks anything?
Without this change, I will need to rewrite my DTO's to not return empty
collections instead of null, which will probably break my frontend code in
some places.
Kind regards,
Enrico
Michael Dick wrote:
>
> Hi,
>
> Calling merge on a 'new' entity is one of the more error prone aspects of
> JPA. The patch you've proposed will resolve the issue in your scenario but
> it could introduce problems in other scenarios.
>
> The change you made deals with what assumptions OpenJPA can make when we
> find a field that is set to null in a 'new' entity.
>
> Currently if the field is null and we can assume that null fields were not
> loaded we ignore the field. With your change we would ignore such a field
> if
> the collection is empty or null (and we can assuming nulls were not
> loaded).
> Where this goes wrong is if the application intended to set the field to
> an
> empty collection (if I'm reading the code correctly it's a bit more
> complicated than that, but bear with me). There's room for improvement in
> the way we handle merging new instances and we might be able to do
> something
> similar to your patch, but I'd have to take a closer look before I can
> sign
> off on it.
>
> Instead of updating the OpenJPA code, have you tried using lazy
> initialization on the field (I'm assuming you initialize it to an empty
> collection).
>
> -mike
>
--
View this message in context: http://n2.nabble.com/Non-dirty-entity-version-field-update-SUPER-URGENT%21%21%21-tp1120307p1141645.html
Sent from the OpenJPA Users mailing list archive at Nabble.com.
Re: Non dirty entity version field update SUPER URGENT!!!
Posted by Michael Dick <mi...@gmail.com>.
Hi,
Calling merge on a 'new' entity is one of the more error prone aspects of
JPA. The patch you've proposed will resolve the issue in your scenario but
it could introduce problems in other scenarios.
The change you made deals with what assumptions OpenJPA can make when we
find a field that is set to null in a 'new' entity.
Currently if the field is null and we can assume that null fields were not
loaded we ignore the field. With your change we would ignore such a field if
the collection is empty or null (and we can assuming nulls were not loaded).
Where this goes wrong is if the application intended to set the field to an
empty collection (if I'm reading the code correctly it's a bit more
complicated than that, but bear with me). There's room for improvement in
the way we handle merging new instances and we might be able to do something
similar to your patch, but I'd have to take a closer look before I can sign
off on it.
Instead of updating the OpenJPA code, have you tried using lazy
initialization on the field (I'm assuming you initialize it to an empty
collection).
-mike
On Thu, Oct 2, 2008 at 4:14 AM, egoosen <eg...@metropolitan.co.za> wrote:
>
> Fixed the compilation problem in my previous post, by running: mvn clean
> package
> --
> View this message in context:
> http://n2.nabble.com/Non-dirty-entity-version-field-update-SUPER-URGENT%21%21%21-tp1120307p1133460.html
> Sent from the OpenJPA Users mailing list archive at Nabble.com.
>
>
Re: Non dirty entity version field update SUPER URGENT!!!
Posted by egoosen <eg...@metropolitan.co.za>.
Fixed the compilation problem in my previous post, by running: mvn clean
package
--
View this message in context: http://n2.nabble.com/Non-dirty-entity-version-field-update-SUPER-URGENT%21%21%21-tp1120307p1133460.html
Sent from the OpenJPA Users mailing list archive at Nabble.com.
Re: Non dirty entity version field update SUPER URGENT!!!
Posted by egoosen <eg...@metropolitan.co.za>.
Further to my previous post, I've altered one line of code in
org.apache.openjpa.kernel.AttachStrategy (line 210):
if ((frmc == null || frmc.isEmpty()) && !nullLoaded) //changed from: if
(frmc == null && !nullLoaded)
...and this seems to fix my problem, but I just tested standalone, not via
my web app.
When I re-built my web app, and ran it, I got this exception on startup, and
I have no idea how to fix it:
SEVERE: StandardWrapper.Throwable
java.lang.Error: Unresolved compilation problems:
JPQLTreeConstants cannot be resolved to a type
JJTFROMITEM cannot be resolved
JJTSUBSELECT cannot be resolved
JJTFROM cannot be resolved
JJTABSTRACTSCHEMANAME cannot be resolved
JJTSUBSELECT cannot be resolved
JJTINNERJOIN cannot be resolved
JJTPATH cannot be resolved
JPQL cannot be resolved to a type
JPQL cannot be resolved to a type
JJTSELECT cannot be resolved
JJTSELECT cannot be resolved
JJTSUBSELECT cannot be resolved
JJTDELETE cannot be resolved
JJTUPDATE cannot be resolved
JJTGROUPBY cannot be resolved
JJTHAVING cannot be resolved
JJTORDERBY cannot be resolved
JJTASCENDING cannot be resolved
JJTSELECTCLAUSE cannot be resolved
JJTDISTINCT cannot be resolved
JJTCONSTRUCTOR cannot be resolved
JJTSELECTEXPRESSIONS cannot be resolved
JJTOUTERFETCHJOIN cannot be resolved
JJTINNERFETCHJOIN cannot be resolved
JJTUPDATEITEM cannot be resolved
JJTWHERE cannot be resolved
JJTFROM cannot be resolved
JJTFROMITEM cannot be resolved
JJTOUTERJOIN cannot be resolved
JJTINNERJOIN cannot be resolved
JJTINNERFETCHJOIN cannot be resolved
JJTOUTERFETCHJOIN cannot be resolved
JJTABSTRACTSCHEMANAME cannot be resolved
JJTWHERE cannot be resolved
JJTBOOLEANLITERAL cannot be resolved
JJTINTEGERLITERAL cannot be resolved
JJTDECIMALLITERAL cannot be resolved
JJTSTRINGLITERAL cannot be resolved
JJTTRIMCHARACTER cannot be resolved
JJTESCAPECHARACTER cannot be resolved
JJTPATTERNVALUE cannot be resolved
JJTNAMEDINPUTPARAMETER cannot be resolved
JJTPOSITIONALINPUTPARAMETER cannot be resolved
JJTOR cannot be resolved
JJTAND cannot be resolved
JJTEQUALS cannot be resolved
JJTNOTEQUALS cannot be resolved
JJTLESSTHAN cannot be resolved
JJTLESSOREQUAL cannot be resolved
JJTGREATERTHAN cannot be resolved
JJTGREATEROREQUAL cannot be resolved
JJTADD cannot be resolved
JJTSUBTRACT cannot be resolved
JJTMULTIPLY cannot be resolved
JJTDIVIDE cannot be resolved
JJTBETWEEN cannot be resolved
JJTIN cannot be resolved
JJTISNULL cannot be resolved
JJTPATH cannot be resolved
JJTIDENTIFIER cannot be resolved
JJTIDENTIFICATIONVARIABLE cannot be resolved
JJTNOT cannot be resolved
JJTLIKE cannot be resolved
JJTESCAPECHARACTER cannot be resolved
JJTISEMPTY cannot be resolved
JJTSIZE cannot be resolved
JJTUPPER cannot be resolved
JJTLOWER cannot be resolved
JJTLENGTH cannot be resolved
JJTABS cannot be resolved
JJTSQRT cannot be resolved
JJTMOD cannot be resolved
JJTTRIM cannot be resolved
JJTTRIMLEADING cannot be resolved
JJTTRIMTRAILING cannot be resolved
JJTTRIMLEADING cannot be resolved
JJTTRIMTRAILING cannot be resolved
JJTTRIMBOTH cannot be resolved
JJTCONCAT cannot be resolved
JJTSUBSTRING cannot be resolved
JJTLOCATE cannot be resolved
JJTAGGREGATE cannot be resolved
JJTCOUNT cannot be resolved
JJTMAX cannot be resolved
JJTMIN cannot be resolved
JJTSUM cannot be resolved
JPQL cannot be resolved to a type
JJTNEGATIVE cannot be resolved
Node cannot be resolved to a type
JPQL cannot be resolved to a type
JPQL cannot be resolved to a type
Node cannot be resolved to a type
Node cannot be resolved to a type
Node cannot be resolved to a type
Node cannot be resolved to a type
The method jjtGetChild(int) from the type JPQLExpressionBuilder.JPQLNode
refers to the missing type Node
Token cannot be resolved to a type
JPQLTreeConstants cannot be resolved
JPQL cannot be resolved to a type
at
org.apache.openjpa.kernel.jpql.JPQLExpressionBuilder$ParsedJPQL.<init>(JPQLExpressionBuilder.java:71)
at org.apache.openjpa.kernel.jpql.JPQLParser.parse(JPQLParser.java:48)
at
org.apache.openjpa.kernel.ExpressionStoreQuery.newCompilation(ExpressionStoreQuery.java:149)
at org.apache.openjpa.kernel.QueryImpl.newCompilation(QueryImpl.java:657)
at
org.apache.openjpa.kernel.QueryImpl.compilationFromCache(QueryImpl.java:639)
at
org.apache.openjpa.kernel.QueryImpl.compileForCompilation(QueryImpl.java:605)
at
org.apache.openjpa.kernel.QueryImpl.compileForExecutor(QueryImpl.java:667)
at org.apache.openjpa.kernel.QueryImpl.compile(QueryImpl.java:574)
at
org.apache.openjpa.persistence.EntityManagerImpl.createNamedQuery(EntityManagerImpl.java:901)
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:585)
at
org.springframework.orm.jpa.JpaTemplate$CloseSuppressingInvocationHandler.invoke(JpaTemplate.java:400)
at $Proxy72.createNamedQuery(Unknown Source)
at za.co.metcapri.dao.jpa.BaseJPADAO$2.doInJpa(BaseJPADAO.java:201)
at org.springframework.orm.jpa.JpaTemplate.execute(JpaTemplate.java:191)
at
org.springframework.orm.jpa.JpaTemplate.executeFind(JpaTemplate.java:158)
at za.co.metcapri.dao.jpa.BaseJPADAO.findRecordsByName(BaseJPADAO.java:199)
at
za.co.metcapri.dao.jpa.codedes.TblCdedesJPADAO.findTblCdedessByCdetypTxt(TblCdedesJPADAO.java:28)
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:585)
at
org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:299)
at
org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:172)
at
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:139)
at
org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:54)
at
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:161)
at
org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:54)
at
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:161)
at
org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:89)
at
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:161)
at
org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at $Proxy35.findTblCdedessByCdetypTxt(Unknown Source)
at
za.co.metcapri.status.business.DataLookupManagerBean.getLookupData(DataLookupManagerBean.java:95)
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:585)
at
org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:299)
at
org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:172)
at
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:139)
at
org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:107)
at
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:161)
at
org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:54)
at
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:161)
at
org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:89)
at
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:161)
at
org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at $Proxy48.getLookupData(Unknown Source)
at
za.co.metcapri.status.server.services.AppInitServiceBean.init(AppInitServiceBean.java:65)
at javax.servlet.GenericServlet.init(GenericServlet.java:212)
at
org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1161)
at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:981)
at
org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4045)
at
org.apache.catalina.core.StandardContext.start(StandardContext.java:4351)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
at org.apache.catalina.core.StandardHost.start(StandardHost.java:719)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:443)
at org.apache.catalina.core.StandardService.start(StandardService.java:516)
at org.apache.catalina.core.StandardServer.start(StandardServer.java:710)
at org.apache.catalina.startup.Catalina.start(Catalina.java:566)
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:585)
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:288)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413)
--
View this message in context: http://n2.nabble.com/Non-dirty-entity-version-field-update-SUPER-URGENT%21%21%21-tp1120307p1131754.html
Sent from the OpenJPA Users mailing list archive at Nabble.com.