persistence@glassfish.java.net

Re: [Issue 1059] New - native queries not being committed

From: Mitesh Meswani <Mitesh.Meswani_at_Sun.COM>
Date: Tue, 05 Sep 2006 10:00:32 -0700
Hi Gordon, Tom,

I am proposing following change to the test. Can you verify with the test author whether it is consistent with intent of the test.

diff -r1.9 SQLResultSetMappingTestSuite.java
90c90,91
<             assertFalse("Object was not refreshed", buyer.getDescription().equals("To A new changed description"));
---
>             Buyer buyerRetrieved = (Buyer)results.get(0);
>             assertFalse("Object was not refreshed", buyerRetrieved.getDescription().equals("To A new changed description"));

Thanks,
Mitesh

Gordon Yorke wrote:
Hello Mitesh,
   I am not sure what this test is attempting to test but it will have to change.  I think the second check that is verfying no "refresh" should be removed.
--Gordon

-----Original Message-----
From: Mitesh.Meswani@Sun.COM [mailto:Mitesh.Meswani@Sun.COM]On Behalf Of
Mitesh Meswani
Sent: Friday, September 01, 2006 9:46 PM
To: Gordon Yorke
Cc: persistence@glassfish.dev.java.net
Subject: Re: [Issue 1059] New - native queries not being committed


Removing Binod from the spam...

Hi Gordon,

While running entity-persistence-test with these changes,
SQLResultSetMappingTestSuite#testInheritanceNoDiscriminatorColumn
failed. The test is as follows

    public void testInheritanceNoDiscriminatorColumn() throws Exception {
        SQLResultSetMapping resultSetMapping = new
SQLResultSetMapping("testInheritanceNoDiscriminatorColumn");
        EntityResult entityResult = new EntityResult(Buyer.class);
        resultSetMapping.addResult(entityResult);
        entityResult.setDiscriminatorColumn("DTYPE_DESCRIM");
 
        SQLCall call = new SQLCall("SELECT t0.BUYER_ID, t0.DTYPE AS
DTYPE_DESCRIM, t0.BUYER_NAME, t0.DESCRIP, t0.VERSION, t1.PURCHASES FROM
CMP3_BUYER t0, CMP3_PBUYER t1 WHERE t1.BUYER_ID = t0.BUYER_ID");
        ResultSetMappingQuery query = new ResultSetMappingQuery(call);
        query.setSQLResultSetMapping(resultSetMapping);
        query.setShouldRefreshIdentityMapResult(true);
        EntityManager em = createEntityManager();
        em.getTransaction().begin();
        try{
            List results =
(List)((EntityManagerImpl)em).getServerSession().executeQuery(query);
            assertNotNull("No result returned", results);
 
            Buyer buyer = (Buyer)results.get(0);
            buyer.setDescription("To A new changed description");
            results =
(List)((EntityManagerImpl)createEntityManager()).getActiveSession().executeQuery(query);
<-----(1)
            assertNotNull("No result returned", results);
            *assertFalse("Object was not refreshed",
buyer.getDescription().equals("To A new changed description")); <-----
This assert fails*
        }finally{
            if (em.getTransaction().isActive()){
                em.getTransaction().rollback();
            }
        }
    }

We are getting a copy of the buyer object when we execute (1). I think
the test needs to change to accommodate the new semantics. What do you
think?

Thanks,
Mitesh

Gordon Yorke wrote:
  
Mitesh,
   This looks good.  Alternately you could simply call unitOfWork.beginEarlyTransaction() instead of the other 2 calls but it really makes no difference.
--Gordon

-----Original Message-----
From: Mitesh.Meswani@Sun.COM [mailto:Mitesh.Meswani@Sun.COM]On Behalf Of
Mitesh Meswani
Sent: Friday, September 01, 2006 4:23 PM
To: persistence@glassfish.dev.java.net
Cc: Binod P G; Gordon Yorke
Subject: Re: [Issue 1059] New - native queries not being committed


Hi Gordon,

Seems that the persistence alias is very slow today. I sent out a bit
different proposal few mins ago. But I think the proposal below makes
more sense. Attached are proposed changes to ResultSetMappingQuery to
implement the first part. Please review. We can implement the hint to
execute it in outside transaction later on.

Thanks,
Mitesh

Gordon Yorke wrote:

    
Marina,
    Given that Native Queries are generally going to be used for special cases having them part of the transaction is probably best although it will sacrifice efficiency for users who are doing simple selects.  We should not rollback the changes though (unless you are talking about the UR1 branch?) but for now should have all Native Queries "begin an early transaction" in the UnitOfWork as the ModifyAllQuery does.  In the future we can add a hint to allow users to have native queries that can read outside of the transaction.
--Gordon

-----Original Message-----
From: Marina.Vatkina@Sun.COM [mailto:Marina.Vatkina@Sun.COM]On Behalf Of
Marina Vatkina
Sent: Friday, September 01, 2006 3:01 PM
To: persistence@glassfish.dev.java.net
Cc: Binod P G
Subject: Re: [Issue 1059] New - native queries not being committed


Gordon,

As the changes to use non-tx connections broke existing functionality,
we can't require users to add hints to get it back. It's possible
though to add hints to request new functionality.

As this bug is a show-stopper for UR1 release, can we rollback the
original changes?

thanks,
-marina

Gordon Yorke wrote:


      
Having a query use the transactional connection in TopLink is not as simple as it seems and caries with it some side effects on subsequent queries.  I think we should have an option to force the query into the transaction that can be initiated by the user and we should attempt to detect pessimistic lock clauses.
--Gordon

-----Original Message-----
From: Marina.Vatkina@Sun.COM [mailto:Marina.Vatkina@Sun.COM]On Behalf Of
Marina Vatkina
Sent: Friday, September 01, 2006 1:37 PM
To: persistence@glassfish.dev.java.net
Cc: Binod P G
Subject: Re: [Issue 1059] New - native queries not being committed


Hi Mitesh,

I don't think that the answer is in the connection pool code. Non-tx connections
are not suitable for select ... for update, as such selects must be transactional.

Gordon,

Unless there is a complete parser in place that can understand what exactly a
native query is doing, I would think that native queries should be excluded
from non-tx connections optimizations.

thanks,
-marina

Mitesh Meswani wrote:



        
Gordon Yorke wrote:




          
Hello Mitesh,
 In July (around the 20th) code was changed where if the SELECT was executed before a flush() or bulk update in the transaction then it would use the non-tx connection.  (Select for update was not considered).

Is it possible that the connection pool was giving us the tx connection anyway?



            
We will have to wait for Binod's reply. But, looking at the fisheye logs
it does not seem that there was any change in the jdbcra module either
in trunk <http://fisheye5.cenqua.com/changelog/glassfish/jdbcra>  or in
the branch
<http://fisheye5.cenqua.com/changelog/%7Ebr=SJSAS90_FCS_BRANCH/glassfish/jdbcra>
post Marrch 2006 so most probably the code change above should be the
root cause




          
A bug should be entered for the custom SQL SELECT FOR UPDATE case.




            
Issue 1059 corresponds to this issue. Any hints on how it can be resolved?

Thanks,
Mitesh




          
--Gordon

-----Original Message-----
From: Mitesh.Meswani@Sun.COM [mailto:Mitesh.Meswani@Sun.COM]On Behalf Of
Mitesh Meswani
Sent: Friday, September 01, 2006 3:10 AM
To: persistence
Cc: Binod P G
Subject: Re: [Issue 1059] New - native queries not being committed


Hi Tom, Gordon,

I am trying to investigate this issue. I observed that current toplink
code uses non-tx connection to execute the query. To experiment I
changed toplink code to use the transactional connection
(maindataSource) instead of non-tx connection (readDatasource) to
execute the query and the hang goes away.
Looks like the cause for this issue is one of following.
(1). Toplink was changed to use non-tx connection between June 29th
(date of merge that corresponds to build 8) to Aug 30 (date of merge
that corresponds to build 9). Do you think it is the case? Or any other
changes that you might suspect?
(2). The non-tx connection pool impl of glassfish has changed and is not
properly delisting the connection.

Hi Binod,
Stepping throu gh toplink's code, I observed that toplink does properly
close the non-tx connection after executing the query. Do you think
anything has changed in the connection pool impl in this area between
UR1 build 8 and 9 that correposnds to (2) above ? Any other hints you
can think of to debug this issue?

Thanks,
Mitesh

sdo@dev.java.net wrote:





            
https://glassfish.dev.java.net/issues/show_bug.cgi?id=1059
               Issue #|1059
               Summary|native queries not being committed
             Component|glassfish
               Version|9.0peur1
              Platform|All
            OS/Version|All
                   URL|
                Status|UNCONFIRMED
     Status whiteboard|
              Keywords|
            Resolution|
            Issue type|DEFECT
              Priority|P3
          Subcomponent|entity-persistence
           Assigned to|mvatkina
           Reported by|sdo






------- Additional comments from sdo@dev.java.net Thu Aug 31 18:40:04 +0000 2006 -------
Starting with nightly builds for 9.0_01 this week, native queries are no longer
being committed. I don't know the exactly nightly it was introduce, but
somewhere between promoted build 8 and the August 30 nightly build.

See the attachment for the test case. Essentially, we have this code (executed
within a stateless session bean with default transaction semantics):

Query q = em.createNativeQuery("select object(c) ... for update");
Object o = q.getSingleResult();

The first time this executes, the row lock is placed on the database, and the
session bean executes -- this should end the transaction and commit the database
work. However, that doesn't happen, and hence a second call to the same code
will hang because it can't access that row in the database.

---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@glassfish.dev.java.net
For additional commands, e-mail: issues-help@glassfish.dev.java.net






              

    

/*
 * The contents of this file are subject to the terms
 * of the Common Development and Distribution License
 * (the "License"). You may not use this file except
 * in compliance with the License.
 *
 * You can obtain a copy of the license at
 * glassfish/bootstrap/legal/CDDLv1.0.txt or
 * https://glassfish.dev.java.net/public/CDDLv1.0.html.
 * See the License for the specific language governing
 * permissions and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL
 * HEADER in each file and include the License file at
 * glassfish/bootstrap/legal/CDDLv1.0.txt. If applicable,
 * add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your
 * own identifying information: Portions Copyright [yyyy]
 * [name of copyright owner]
 */
// Copyright (c) 1998, 2006, Oracle. All rights reserved.


package oracle.toplink.essentials.testing.tests.cmp3.advanced;


import java.util.Iterator;
import java.util.List;
import java.util.Vector;

import javax.persistence.EntityManager;

import oracle.toplink.essentials.queryframework.ResultSetMappingQuery;
import oracle.toplink.essentials.queryframework.SQLCall;
import oracle.toplink.essentials.testing.models.cmp3.advanced.AdvancedTableCreator;
import oracle.toplink.essentials.testing.models.cmp3.advanced.EmployeePopulator;
import oracle.toplink.essentials.testing.models.cmp3.advanced.LargeProject;
import oracle.toplink.essentials.testing.models.cmp3.advanced.Project;
import oracle.toplink.essentials.testing.models.cmp3.advanced.SmallProject;
import oracle.toplink.essentials.testing.models.cmp3.advanced.Employee;
import oracle.toplink.essentials.testing.models.cmp3.advanced.Buyer;
import oracle.toplink.essentials.testing.models.cmp3.advanced.PlatinumBuyer;
import oracle.toplink.essentials.internal.ejb.cmp3.EntityManagerImpl;
import oracle.toplink.essentials.queryframework.ColumnResult;
import oracle.toplink.essentials.queryframework.EntityResult;
import oracle.toplink.essentials.queryframework.FieldResult;
import oracle.toplink.essentials.queryframework.SQLResultSetMapping;
import oracle.toplink.essentials.testing.framework.junit.JUnitTestCase;
import junit.framework.TestSuite;
import junit.framework.Test;
import junit.extensions.TestSetup;

public class SQLResultSetMappingTestSuite extends JUnitTestCase {
    protected boolean m_reset = false; // reset gets called twice on error

        
    public SQLResultSetMappingTestSuite() {
    }
    
    public SQLResultSetMappingTestSuite(String name) {
        super(name);
    }
    
    public void setUp () {
        m_reset = true;
        super.setUp();
        clearCache();
    }

    public void testInheritanceNoDiscriminatorColumn() throws Exception {
        SQLResultSetMapping resultSetMapping = new SQLResultSetMapping("testInheritanceNoDiscriminatorColumn");
        EntityResult entityResult = new EntityResult(Buyer.class);
        resultSetMapping.addResult(entityResult);
        entityResult.setDiscriminatorColumn("DTYPE_DESCRIM");
        
        SQLCall call = new SQLCall("SELECT t0.BUYER_ID, t0.DTYPE AS DTYPE_DESCRIM, t0.BUYER_NAME, t0.DESCRIP, t0.VERSION, t1.PURCHASES FROM CMP3_BUYER t0, CMP3_PBUYER t1 WHERE t1.BUYER_ID = t0.BUYER_ID");
        ResultSetMappingQuery query = new ResultSetMappingQuery(call);
        query.setSQLResultSetMapping(resultSetMapping);
        query.setShouldRefreshIdentityMapResult(true);
        EntityManager em = createEntityManager();
        em.getTransaction().begin();
        try{
            List results = (List)((EntityManagerImpl)em).getServerSession().executeQuery(query);
            assertNotNull("No result returned", results);
            
            Buyer buyer = (Buyer)results.get(0);
            buyer.setDescription("To A new changed description");
            results = (List)((EntityManagerImpl)createEntityManager()).getActiveSession().executeQuery(query);
            assertNotNull("No result returned", results);
            Buyer buyerRetrieved = (Buyer)results.get(0);
            assertFalse("Object was not refreshed", buyerRetrieved.getDescription().equals("To A new changed description"));
        }finally{
            if (em.getTransaction().isActive()){
                em.getTransaction().rollback();
            }
        }
    }

    public void testComplicateResultWithInheritance() throws Exception {
        SQLResultSetMapping resultSetMapping = new SQLResultSetMapping("ComplicatedInheritance");
        resultSetMapping.addResult(new ColumnResult("BUDGET_SUM"));
        EntityResult entityResult = new EntityResult(Project.class);
        resultSetMapping.addResult(entityResult);
        entityResult = new EntityResult(SmallProject.class);
        entityResult.addFieldResult(new FieldResult("id", "SMALL_ID"));
        entityResult.addFieldResult(new FieldResult("name", "SMALL_NAME"));
        entityResult.addFieldResult(new FieldResult("description", "SMALL_DESCRIPTION"));
        entityResult.addFieldResult(new FieldResult("teamLeader", "SMALL_TEAMLEAD"));
        entityResult.addFieldResult(new FieldResult("version", "SMALL_VERSION"));
        entityResult.setDiscriminatorColumn("SMALL_DESCRIM");
        resultSetMapping.addResult(entityResult);
        
        SQLCall call = new SQLCall("SELECT (t1.BUDGET/t0.PROJ_ID) AS BUDGET_SUM, t0.PROJ_ID, t0.PROJ_TYPE, t0.PROJ_NAME, t0.DESCRIP, t0.LEADER_ID, t0.VERSION, t1.BUDGET, t2.PROJ_ID AS SMALL_ID, t2.PROJ_TYPE AS SMALL_DESCRIM, t2.PROJ_NAME AS SMALL_NAME, t2.DESCRIP AS SMALL_DESCRIPTION, t2.LEADER_ID AS SMALL_TEAMLEAD, t2.VERSION AS SMALL_VERSION FROM CMP3_PROJECT t0, CMP3_PROJECT t2, CMP3_LPROJECT t1 WHERE t1.PROJ_ID = t0.PROJ_ID AND t2.PROJ_TYPE='S'");
        ResultSetMappingQuery query = new ResultSetMappingQuery(call);
        query.setSQLResultSetMapping(resultSetMapping);
        List results = (List)((EntityManagerImpl)createEntityManager()).getActiveSession().executeQuery(query);
        assertNotNull("No result returned", results);
        assertTrue("Empty list returned", (results.size()!=0));
        
        for (Iterator iterator = results.iterator(); iterator.hasNext(); ){
            Object[] resultElement = (Object[])iterator.next();
            assertTrue("Failed to Return 3 items", (resultElement.length == 3));
            // Using Number as Different db/drivers can return different types
            // e.g. Oracle with ijdbc14.jar returns BigDecimal where as
            // Derby with derbyclient.jar returns Double
            assertTrue("Failed to return column",(resultElement[0] instanceof Number) );
            assertTrue("Failed to return LargeProject", (resultElement[1] instanceof LargeProject) );
            assertTrue("Failed To Return SmallProject", (resultElement[2] instanceof SmallProject) );
            assertFalse("Returned same data in both result elements",((SmallProject)resultElement[2]).getName().equals(((LargeProject)resultElement[1]).getName()));
        }
    }
    
    public void testRefresh() throws Exception {
        SQLResultSetMapping resultSetMapping = new SQLResultSetMapping("ComplicatedInheritance");
        EntityResult entityResult = new EntityResult(Project.class);
        resultSetMapping.addResult(entityResult);
        entityResult.setDiscriminatorColumn("SMALL_DESCRIM");
        
        SQLCall call = new SQLCall("SELECT t0.PROJ_ID, t0.PROJ_TYPE AS SMALL_DESCRIM, t0.PROJ_NAME, t0.DESCRIP, t0.LEADER_ID, t0.VERSION, t1.BUDGET FROM CMP3_PROJECT t0, CMP3_PROJECT t2, CMP3_LPROJECT t1 WHERE t1.PROJ_ID = t0.PROJ_ID");
        ResultSetMappingQuery query = new ResultSetMappingQuery(call);
        query.setSQLResultSetMapping(resultSetMapping);
        query.setShouldRefreshIdentityMapResult(true);
        EntityManager em = createEntityManager();
        em.getTransaction().begin();
        try{
            List results = (List)((EntityManagerImpl)em).getActiveSession().executeQuery(query);
            assertNotNull("No result returned", results);
            Project project = (Project)results.get(0);
            project.setDescription("To A new changed description");
            results = (List)((EntityManagerImpl)em).getActiveSession().executeQuery(query);
            assertNotNull("No result returned", results);
            assertTrue("Empty list returned", (results.size()!=0));
            assertFalse("Object was not refreshed", project.getDescription().equals("To A new changed description"));
        }finally{
            ((EntityManagerImpl)em).getTransaction().rollback();
        }
    }

    public void testBindParameters() throws Exception {
        SQLResultSetMapping resultSetMapping = new SQLResultSetMapping("BindParameters");
        EntityResult entityResult = new EntityResult(Project.class);
        resultSetMapping.addResult(entityResult);
        entityResult.setDiscriminatorColumn("SMALL_DESCRIM");
        
        SQLCall call = new SQLCall("SELECT t0.PROJ_ID, t0.PROJ_TYPE AS SMALL_DESCRIM, t0.PROJ_NAME, t0.DESCRIP, t0.LEADER_ID, t0.VERSION, t1.BUDGET FROM CMP3_PROJECT t0, CMP3_LPROJECT t1 WHERE t1.PROJ_ID = t0.PROJ_ID AND t1.BUDGET > ? AND t1.BUDGET < 30000000");
        ResultSetMappingQuery query = new ResultSetMappingQuery(call);
        query.setSQLResultSetMapping(resultSetMapping);
        query.setShouldRefreshIdentityMapResult(false);
        query.setShouldBindAllParameters(true);
        query.addArgument("1");
        Vector params = new Vector();
        //4000 is a more reasonable budget given test data if results are expected
        params.add(new Integer(4000));
        List results = (List)((EntityManagerImpl)createEntityManager()).getActiveSession().executeQuery(query, params);
        assertNotNull("No result returned", results);
        assertTrue("Empty list returned", (results.size()!=0));
    }

    public void testBindParametersWithPostitional() throws Exception {
        SQLResultSetMapping resultSetMapping = new SQLResultSetMapping("BindParameters");
        EntityResult entityResult = new EntityResult(Project.class);
        resultSetMapping.addResult(entityResult);
        entityResult.setDiscriminatorColumn("SMALL_DESCRIM");
        
        SQLCall call = new SQLCall("SELECT t0.PROJ_ID, t0.PROJ_TYPE AS SMALL_DESCRIM, t0.PROJ_NAME, t0.DESCRIP, t0.LEADER_ID, t0.VERSION, t1.BUDGET FROM CMP3_PROJECT t0, CMP3_LPROJECT t1 WHERE t1.PROJ_ID = t0.PROJ_ID AND t1.BUDGET > ? AND t1.BUDGET < 30000000");
        ResultSetMappingQuery query = new ResultSetMappingQuery(call);
        query.setSQLResultSetMapping(resultSetMapping);
        query.setShouldRefreshIdentityMapResult(false);
        query.setShouldBindAllParameters(true);
        query.addArgument("1");
        Vector params = new Vector();
        params.add(new Integer(4000));
        List results = (List)((EntityManagerImpl)createEntityManager()).getActiveSession().executeQuery(query, params);
        assertNotNull("No result returned", results);
        assertTrue("Empty list returned", (results.size()!=0));
    }
    public void testSimpleInheritance() throws Exception {
        SQLResultSetMapping resultSetMapping = new SQLResultSetMapping("SimpleInheritance");
        EntityResult entityResult = new EntityResult(Project.class);
        entityResult.setDiscriminatorColumn("SMALL_DESCRIM");
        resultSetMapping.addResult(entityResult);

        //Use ANSI outer join sytax so that the query works on most of the databases.
        //SQLCall call = new SQLCall("SELECT t0.PROJ_ID, t0.PROJ_TYPE AS SMALL_DESCRIM, t0.PROJ_NAME, t0.DESCRIP, t0.LEADER_ID, t0.VERSION, t1.BUDGET FROM CMP3_PROJECT t0, CMP3_LPROJECT t1 WHERE t1.PROJ_ID (+)= t0.PROJ_ID");
        SQLCall call = new SQLCall("SELECT t0.PROJ_ID, t0.PROJ_TYPE AS SMALL_DESCRIM, t0.PROJ_NAME, t0.DESCRIP, t0.LEADER_ID, t0.VERSION, t1.BUDGET FROM CMP3_PROJECT t0 left outer join CMP3_LPROJECT t1 on t1.PROJ_ID = t0.PROJ_ID");
        ResultSetMappingQuery query = new ResultSetMappingQuery(call);
        query.setSQLResultSetMapping(resultSetMapping);
        List results = (List)((EntityManagerImpl)createEntityManager()).getActiveSession().executeQuery(query);
        assertNotNull("No result returned", results);
        assertTrue("Empty list returned", (results.size()!=0));
        for (Iterator iterator = results.iterator(); iterator.hasNext(); ){
            Object project = iterator.next();
            assertTrue("Failed to return a project", (project instanceof Project) );
        }
    }

    public void testPessimisticLocking() throws Exception {
        EntityManager em = createEntityManager();
        SmallProject smallProject = (SmallProject)((EntityManagerImpl)em).getActiveSession().readObject(SmallProject.class);
        SQLResultSetMapping resultSetMapping = new SQLResultSetMapping("PessimisticLocking");
        EntityResult entityResult = new EntityResult(SmallProject.class);
        resultSetMapping.addResult(entityResult);
        
        SQLCall call = new SQLCall("SELECT t0.PROJ_ID, t0.PROJ_TYPE, t0.PROJ_NAME, t0.DESCRIP, t0.LEADER_ID, t0.VERSION FROM CMP3_PROJECT t0 WHERE t0.PROJ_ID = " + smallProject.getId() + " FOR UPDATE");
        ResultSetMappingQuery query = new ResultSetMappingQuery(call);
        query.setSQLResultSetMapping(resultSetMapping);
        query.setLockMode(query.LOCK);
        em.getTransaction().begin();
        try{
            List results = (List)((EntityManagerImpl)em).getActiveSession().executeQuery(query);
            assertNotNull("No result returned", results);
            assertTrue("Empty list returned", (results.size()!=0));
            smallProject = (SmallProject)(results.get(0));
            smallProject.setDescription("A relatively new Description");
            em.getTransaction().commit();
        }catch (RuntimeException ex){
            if (em.getTransaction().isActive()){
                em.getTransaction().rollback();
            }
            em.close();
            throw ex;
        }
                
        smallProject = em.find(SmallProject.class, smallProject.getId());
        em.close();
        assertTrue("Failed to update the new description", smallProject.getDescription().equals("A relatively new Description"));
       
    }
    
    /** tests that embeddable and dot notation for fieldresults work */
     public void testComplicateResults() throws Exception {
        SQLResultSetMapping resultSetMapping = new SQLResultSetMapping("ComplicatedInheritance");
        EntityResult entityResult;
        
        entityResult = new EntityResult(Employee.class);
        entityResult.addFieldResult(new FieldResult("period.startDate", "STARTDATE"));
        entityResult.addFieldResult(new FieldResult("address.id", "EMP_ADDR"));

        resultSetMapping.addResult(entityResult);
        SQLCall call = new SQLCall("SELECT t0.EMP_ID, t1.EMP_ID, t0.F_NAME, t0.L_NAME, t0.VERSION, t1.SALARY, t0.START_DATE AS STARTDATE, t0.END_DATE, t0.ADDR_ID AS EMP_ADDR, t0.manager_EMP_ID FROM CMP3_EMPLOYEE t0, CMP3_SALARY t1 WHERE ((t1.EMP_ID = t0.EMP_ID) AND ( t0.L_NAME = 'Smith' ))");
        ResultSetMappingQuery query = new ResultSetMappingQuery(call);
        query.setSQLResultSetMapping(resultSetMapping);
        List results = (List)((EntityManagerImpl)createEntityManager()).getActiveSession().executeQuery(query);
        assertNotNull("No result returned", results);
        assertTrue("Incorrect number of results returned, expected 2 got "+results.size(), (results.size()==2));
        
        for (Iterator iterator = results.iterator(); iterator.hasNext(); ){
            Object resultElement = iterator.next();
            assertTrue("Failed to return Employee", (resultElement instanceof Employee) );
            Employee emp = (Employee)resultElement;
            assertNotNull("Failed to get an address for Employee "+emp.getFirstName(), emp.getAddress() );
        }
    }


    public void tearDown () {
        if (m_reset) {
            m_reset = false;
        }
        super.tearDown();
    }
    
    public static Test suite() {
        TestSuite suite = new TestSuite(SQLResultSetMappingTestSuite.class);
        
        suite.setName("SQLResultSetMappingTestSuite");
        
        return new TestSetup(suite) {
        
            protected void setUp(){
            
              new AdvancedTableCreator().replaceTables(((EntityManagerImpl)createEntityManager()).getServerSession());
         
                EmployeePopulator employeePopulator = new EmployeePopulator();
         
               employeePopulator.buildExamples();
                
              //Persist the examples in the database
              employeePopulator.persistExample(getServerSession());
            }

            protected void tearDown() {
                clearCache();
            }
        };
    }
    

}