You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by ch...@apache.org on 2015/07/12 15:53:24 UTC

olingo-odata2 git commit: [OLINGO-720] - Provide capability to extend JPA Query object

Repository: olingo-odata2
Updated Branches:
  refs/heads/master 9a7e91357 -> cb29fa48d


[OLINGO-720] - Provide capability to extend JPA Query object

Signed-off-by: Chandan V A <ch...@sap.com>

Project: http://git-wip-us.apache.org/repos/asf/olingo-odata2/repo
Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata2/commit/cb29fa48
Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata2/tree/cb29fa48
Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata2/diff/cb29fa48

Branch: refs/heads/master
Commit: cb29fa48da7d712083cda21e0cd6e543389e64ba
Parents: 9a7e913
Author: Chandan V A <ch...@sap.com>
Authored: Sun Jul 12 19:23:05 2015 +0530
Committer: Chandan V A <ch...@sap.com>
Committed: Sun Jul 12 19:23:05 2015 +0530

----------------------------------------------------------------------
 .../ODataJPAQueryExtensionEntityListener.java   | 116 +++++++++
 .../api/ODataJPATombstoneEntityListener.java    |   7 +
 .../jpa/processor/api/jpql/JPQLContext.java     |   4 +-
 .../core/access/data/JPAProcessorImpl.java      | 256 +++++-------------
 .../core/access/data/JPAQueryBuilder.java       | 259 +++++++++++++++++++
 .../core/ODataJPAProcessorDefaultTest.java      |  43 +--
 .../core/access/data/JPAProcessorImplTest.java  |   2 +
 .../core/access/data/JPAQueryBuilderTest.java   | 254 ++++++++++++++++++
 .../processor/core/mock/ODataContextMock.java   |   7 +
 .../core/mock/ODataJPAContextMock.java          |   1 +
 .../jpa/processor/ref/model/Customer.java       |   2 +
 .../ref/web/JPAReferenceServiceFactory.java     |   1 +
 12 files changed, 744 insertions(+), 208 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/cb29fa48/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/ODataJPAQueryExtensionEntityListener.java
----------------------------------------------------------------------
diff --git a/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/ODataJPAQueryExtensionEntityListener.java b/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/ODataJPAQueryExtensionEntityListener.java
new file mode 100644
index 0000000..0ad3ac4
--- /dev/null
+++ b/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/ODataJPAQueryExtensionEntityListener.java
@@ -0,0 +1,116 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+package org.apache.olingo.odata2.jpa.processor.api;
+
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+
+import org.apache.olingo.odata2.api.uri.info.DeleteUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntityCountUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntitySetCountUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntitySetUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntityUriInfo;
+import org.apache.olingo.odata2.api.uri.info.PutMergePatchUriInfo;
+
+/**
+ * Extend this class to build JPA Query object for a given OData request. The extended class can be registered as JPA
+ * entity listeners.The implemented JPA Entity Listener classes will be called back from OData JPA Processor Library.
+ */
+public abstract class ODataJPAQueryExtensionEntityListener extends ODataJPATombstoneEntityListener {
+  /**
+   * Override this method to build JPA Query for OData request - GetEntitySet; SELECT *
+   * @param uriInfo is a reference to OData request
+   * @param em is a reference to {@link javax.persistence.EntityManager}
+   * @return an instance of type {@link javax.persistence.Query}
+   */
+  public Query getQuery(GetEntitySetUriInfo uriInfo, EntityManager em) {
+    return null;
+  }
+
+  /**
+   * Override this method to build JPA Query for OData request - GetEntity; SELECT SINGLE with key in WHERE
+   * clause
+   * @param uriInfo is a reference to OData request
+   * @param em is a reference to {@link javax.persistence.EntityManager}
+   * @return an instance of type {@link javax.persistence.Query}
+   */
+  public Query getQuery(GetEntityUriInfo uriInfo, EntityManager em) {
+    return null;
+  }
+
+  /**
+   * Override this method to build JPA Query for OData request - GetEntity Count; SELECT SINGLE with key in WHERE
+   * clause
+   * @param uriInfo is a reference to OData request
+   * @param em is a reference to {@link javax.persistence.EntityManager}
+   * @return an instance of type {@link javax.persistence.Query}
+   */
+  public Query getQuery(GetEntityCountUriInfo uriInfo, EntityManager em) {
+    return null;
+  }
+
+  /**
+   * Override this method to build JPA Query for OData request - GetEntitySet Count; SELECT COUNT(*)
+   * @param uriInfo is a reference to OData request
+   * @param em is a reference to {@link javax.persistence.EntityManager}
+   * @return an instance of type {@link javax.persistence.Query}
+   */
+  public Query getQuery(GetEntitySetCountUriInfo uriInfo, EntityManager em) {
+    return null;
+  }
+
+  /**
+   * Override this method to build JPA Query for OData request - Update; SELECT SINGLE with key in WHERE
+   * clause
+   * @param uriInfo is a reference to OData request
+   * @param em is a reference to {@link javax.persistence.EntityManager}
+   * @return an instance of type {@link javax.persistence.Query}
+   */
+  public Query getQuery(PutMergePatchUriInfo uriInfo, EntityManager em) {
+    return null;
+  }
+
+  /**
+   * Override this method to build JPA Query for OData request - Delete; SELECT SINGLE with key in WHERE
+   * clause
+   * @param uriInfo is a reference to OData request
+   * @param em is a reference to {@link javax.persistence.EntityManager}
+   * @return an instance of type {@link javax.persistence.Query}
+   */
+  public Query getQuery(DeleteUriInfo uriInfo, EntityManager em) {
+    return null;
+  }
+
+  @Override
+  public String generateDeltaToken(List<Object> deltas, Query query) {
+    return null;
+  }
+
+  /**
+   * Implement this method to indicate whether the extended class can handle OData Tombstone feature as well
+   * @return false by default
+   */
+  @Override
+  public boolean isTombstoneSupported() {
+    return false;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/cb29fa48/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/ODataJPATombstoneEntityListener.java
----------------------------------------------------------------------
diff --git a/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/ODataJPATombstoneEntityListener.java b/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/ODataJPATombstoneEntityListener.java
index 148fa38..ff85653 100644
--- a/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/ODataJPATombstoneEntityListener.java
+++ b/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/ODataJPATombstoneEntityListener.java
@@ -57,4 +57,11 @@ public abstract class ODataJPATombstoneEntityListener {
    */
   public abstract String generateDeltaToken(List<Object> deltas, Query query);
 
+  /**
+   * Implement this method to indicate whether the extended class can handle OData Tombstone feature as well
+   * @return true by default
+   */
+  public boolean isTombstoneSupported() {
+    return true;
+  }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/cb29fa48/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/jpql/JPQLContext.java
----------------------------------------------------------------------
diff --git a/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/jpql/JPQLContext.java b/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/jpql/JPQLContext.java
index a6230ad..672f808 100644
--- a/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/jpql/JPQLContext.java
+++ b/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/jpql/JPQLContext.java
@@ -159,6 +159,8 @@ public abstract class JPQLContext implements JPQLContextView {
    * 
    */
   public static abstract class JPQLContextBuilder {
+    private static final String ALIAS = "E";
+
     /**
      * alias counter is an integer counter that is incremented by "1" for
      * every new alias name generation. The value of counter is used in the
@@ -228,7 +230,7 @@ public abstract class JPQLContext implements JPQLContextView {
      * @return a String representing JPA entity alias name
      */
     protected String generateJPAEntityAlias() {
-      return new String("E" + ++aliasCounter);
+      return new String(ALIAS + ++aliasCounter);
     }
   }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/cb29fa48/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAProcessorImpl.java
----------------------------------------------------------------------
diff --git a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAProcessorImpl.java b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAProcessorImpl.java
index da5a1e1..ad8810c 100644
--- a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAProcessorImpl.java
+++ b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAProcessorImpl.java
@@ -35,6 +35,7 @@ import org.apache.olingo.odata2.api.edm.EdmException;
 import org.apache.olingo.odata2.api.edm.EdmMapping;
 import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
 import org.apache.olingo.odata2.api.ep.entry.ODataEntry;
+import org.apache.olingo.odata2.api.exception.ODataBadRequestException;
 import org.apache.olingo.odata2.api.uri.UriInfo;
 import org.apache.olingo.odata2.api.uri.info.DeleteUriInfo;
 import org.apache.olingo.odata2.api.uri.info.GetEntityCountUriInfo;
@@ -55,15 +56,15 @@ import org.apache.olingo.odata2.jpa.processor.api.access.JPAMethodContext;
 import org.apache.olingo.odata2.jpa.processor.api.access.JPAProcessor;
 import org.apache.olingo.odata2.jpa.processor.api.exception.ODataJPAModelException;
 import org.apache.olingo.odata2.jpa.processor.api.exception.ODataJPARuntimeException;
-import org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLContext;
 import org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLContextType;
-import org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLStatement;
 import org.apache.olingo.odata2.jpa.processor.api.model.JPAEdmMapping;
 import org.apache.olingo.odata2.jpa.processor.core.ODataEntityParser;
 import org.apache.olingo.odata2.jpa.processor.core.access.data.JPAPage.JPAPageBuilder;
+import org.apache.olingo.odata2.jpa.processor.core.access.data.JPAQueryBuilder.JPAQueryInfo;
 
 public class JPAProcessorImpl implements JPAProcessor {
 
+  private static final String DELTATOKEN = "!deltatoken";
   ODataJPAContext oDataJPAContext;
   EntityManager em;
 
@@ -128,78 +129,52 @@ public class JPAProcessorImpl implements JPAProcessor {
   public List<Object> process(final GetEntitySetUriInfo uriParserResultView)
       throws ODataJPAModelException, ODataJPARuntimeException {
 
+    List<Object> result = null;
     if (uriParserResultView.getFunctionImport() != null) {
       return (List<Object>) process((GetFunctionImportUriInfo) uriParserResultView);
     }
+
     InlineCount inlineCount = uriParserResultView.getInlineCount();
     Integer top = uriParserResultView.getTop() == null ? 1 : uriParserResultView.getTop().intValue();
     boolean hasNoAllPages = inlineCount == null ? true : !inlineCount.equals(InlineCount.ALLPAGES);
     if (top.intValue() == 0 && hasNoAllPages) {
       return new ArrayList<Object>();
     }
-    JPQLContextType contextType = null;
-    try {
-      if (uriParserResultView.getNavigationSegments().size() > 0) {
-        contextType = JPQLContextType.JOIN;
-      } else {
-        contextType = JPQLContextType.SELECT;
-      }
-
-      JPQLContext jpqlContext = null;
-
-      if (oDataJPAContext.getPageSize() > 0) {
-        jpqlContext = JPQLContext.createBuilder(contextType,
-            uriParserResultView, true).build();
-      } else {
-        jpqlContext = JPQLContext.createBuilder(contextType,
-            uriParserResultView).build();
-      }
 
-      JPQLStatement jpqlStatement = JPQLStatement.createBuilder(jpqlContext)
-          .build();
+    try {
+      JPAEdmMapping mapping = (JPAEdmMapping) uriParserResultView.getTargetEntitySet().getEntityType().getMapping();
+      JPAQueryBuilder queryBuilder = new JPAQueryBuilder(oDataJPAContext);
+      JPAQueryInfo queryInfo = queryBuilder.build(uriParserResultView);
+      Query query = queryInfo.getQuery();
+      ODataJPATombstoneEntityListener listener =
+          queryBuilder.getODataJPATombstoneEntityListener((UriInfo) uriParserResultView);
       Map<String, String> customQueryOptions = uriParserResultView.getCustomQueryOptions();
       String deltaToken = null;
       if (customQueryOptions != null) {
-        deltaToken = uriParserResultView.getCustomQueryOptions().get("!deltatoken");
+        deltaToken = uriParserResultView.getCustomQueryOptions().get(DELTATOKEN);
       }
       if (deltaToken != null) {
         ODataJPATombstoneContext.setDeltaToken(deltaToken);
       }
-
-      Query query = null;
-      List<Object> result = null;
-
-      JPAEdmMapping mapping = (JPAEdmMapping) uriParserResultView.getTargetEntitySet().getEntityType().getMapping();
-      ODataJPATombstoneEntityListener listener = null;
-      if (mapping.getODataJPATombstoneEntityListener() != null) {
-        listener = (ODataJPATombstoneEntityListener) mapping.getODataJPATombstoneEntityListener().newInstance();
-        query = listener.getQuery(uriParserResultView, em);
-      }
-      if (query == null) {
-        query = em.createQuery(jpqlStatement.toString());
-        if (listener != null) {
-          query.getResultList();
-          List<Object> deltaResult =
-              (List<Object>) ODataJPATombstoneContext.getDeltaResult(((EdmMapping) mapping).getInternalName());
-          result = handlePaging(deltaResult, uriParserResultView);
-        } else {
-          result = handlePaging(query, uriParserResultView);
-        }
+      if (listener != null && (!queryInfo.isTombstoneQuery() && listener.isTombstoneSupported())) {
+        query.getResultList();
+        List<Object> deltaResult =
+            (List<Object>) ODataJPATombstoneContext.getDeltaResult(((EdmMapping) mapping).getInternalName());
+        result = handlePaging(deltaResult, uriParserResultView);
+        ODataJPATombstoneContext.setDeltaToken(listener.generateDeltaToken((List<Object>) result, query));
       } else {
         result = handlePaging(query, uriParserResultView);
       }
-
-      // Set New Token
-      if (listener != null) {
-        ODataJPATombstoneContext.setDeltaToken(listener.generateDeltaToken((List<Object>) result, query));
-      }
-
       return result == null ? new ArrayList<Object>() : result;
-
-    } catch (Exception e) {
+    } catch (EdmException e) {
+      throw ODataJPARuntimeException.throwException(
+          ODataJPARuntimeException.ERROR_JPQL_QUERY_CREATE, e);
+    } catch (InstantiationException e) {
+      throw ODataJPARuntimeException.throwException(
+          ODataJPARuntimeException.ERROR_JPQL_QUERY_CREATE, e);
+    } catch (IllegalAccessException e) {
       throw ODataJPARuntimeException.throwException(
           ODataJPARuntimeException.ERROR_JPQL_QUERY_CREATE, e);
-
     }
   }
 
@@ -207,18 +182,7 @@ public class JPAProcessorImpl implements JPAProcessor {
   @Override
   public <T> Object process(GetEntityUriInfo uriParserResultView)
       throws ODataJPAModelException, ODataJPARuntimeException {
-
-    JPQLContextType contextType = null;
-    if (uriParserResultView instanceof GetEntityUriInfo) {
-      uriParserResultView = ((GetEntityUriInfo) uriParserResultView);
-      if (uriParserResultView.getNavigationSegments().size() > 0) {
-        contextType = JPQLContextType.JOIN_SINGLE;
-      } else {
-        contextType = JPQLContextType.SELECT_SINGLE;
-      }
-    }
-
-    return readEntity(uriParserResultView, contextType);
+    return readEntity(new JPAQueryBuilder(oDataJPAContext).build(uriParserResultView));
   }
 
   /* Process $count for Get Entity Set Request */
@@ -226,36 +190,13 @@ public class JPAProcessorImpl implements JPAProcessor {
   public long process(final GetEntitySetCountUriInfo resultsView)
       throws ODataJPAModelException, ODataJPARuntimeException {
 
-    JPQLContextType contextType = null;
-    try {
-      if (!resultsView.getStartEntitySet().getName()
-          .equals(resultsView.getTargetEntitySet().getName())) {
-        contextType = JPQLContextType.JOIN_COUNT;
-      } else {
-        contextType = JPQLContextType.SELECT_COUNT;
-      }
-    } catch (EdmException e) {
-      ODataJPARuntimeException.throwException(
-          ODataJPARuntimeException.GENERAL, e);
+    JPAQueryBuilder queryBuilder = new JPAQueryBuilder(oDataJPAContext);
+    Query query = queryBuilder.build(resultsView);
+    List<?> resultList = query.getResultList();
+    if (resultList != null && resultList.size() == 1) {
+      return Long.valueOf(resultList.get(0).toString());
     }
 
-    JPQLContext jpqlContext = JPQLContext.createBuilder(contextType,
-        resultsView).build();
-
-    JPQLStatement jpqlStatement = JPQLStatement.createBuilder(jpqlContext)
-        .build();
-    Query query = null;
-    try {
-
-      query = em.createQuery(jpqlStatement.toString());
-      List<?> resultList = query.getResultList();
-      if (resultList != null && resultList.size() == 1) {
-        return Long.valueOf(resultList.get(0).toString());
-      }
-    } catch (IllegalArgumentException e) {
-      throw ODataJPARuntimeException.throwException(
-          ODataJPARuntimeException.ERROR_JPQL_QUERY_CREATE, e);
-    }
     return 0;
   }
 
@@ -263,37 +204,12 @@ public class JPAProcessorImpl implements JPAProcessor {
   @Override
   public long process(final GetEntityCountUriInfo resultsView) throws ODataJPAModelException, ODataJPARuntimeException {
 
-    JPQLContextType contextType = null;
-    try {
-      if (!resultsView.getStartEntitySet().getName()
-          .equals(resultsView.getTargetEntitySet().getName())) {
-        contextType = JPQLContextType.JOIN_COUNT;
-      } else {
-        contextType = JPQLContextType.SELECT_COUNT;
-      }
-    } catch (EdmException e) {
-      ODataJPARuntimeException.throwException(
-          ODataJPARuntimeException.GENERAL, e);
-    }
-
-    JPQLContext jpqlContext = JPQLContext.createBuilder(contextType,
-        resultsView).build();
-
-    JPQLStatement jpqlStatement = JPQLStatement.createBuilder(jpqlContext)
-        .build();
-    Query query = null;
-    try {
-
-      query = em.createQuery(jpqlStatement.toString());
-      List<?> resultList = query.getResultList();
-      if (resultList != null && resultList.size() == 1) {
-        return Long.valueOf(resultList.get(0).toString());
-      }
-    } catch (IllegalArgumentException e) {
-      throw ODataJPARuntimeException.throwException(
-          ODataJPARuntimeException.ERROR_JPQL_QUERY_CREATE, e);
+    JPAQueryBuilder queryBuilder = new JPAQueryBuilder(oDataJPAContext);
+    Query query = queryBuilder.build(resultsView);
+    List<?> resultList = query.getResultList();
+    if (resultList != null && resultList.size() == 1) {
+      return Long.valueOf(resultList.get(0).toString());
     }
-
     return 0;
   }
 
@@ -329,38 +245,19 @@ public class JPAProcessorImpl implements JPAProcessor {
   @Override
   public Object process(DeleteUriInfo uriParserResultView, final String contentType)
       throws ODataJPAModelException, ODataJPARuntimeException {
-    JPQLContextType contextType = null;
-    try {
-      if (uriParserResultView instanceof DeleteUriInfo) {
-        if (((UriInfo) uriParserResultView).isLinks()) {
-          return deleteLink(uriParserResultView);
-        }
-        uriParserResultView = ((DeleteUriInfo) uriParserResultView);
-        if (!((DeleteUriInfo) uriParserResultView).getStartEntitySet().getName()
-            .equals(((DeleteUriInfo) uriParserResultView).getTargetEntitySet().getName())) {
-          contextType = JPQLContextType.JOIN_SINGLE;
-        } else {
-          contextType = JPQLContextType.SELECT_SINGLE;
-        }
+    if (uriParserResultView instanceof DeleteUriInfo) {
+      if (((UriInfo) uriParserResultView).isLinks()) {
+        return deleteLink(uriParserResultView);
       }
-    } catch (EdmException e) {
-      ODataJPARuntimeException.throwException(
-          ODataJPARuntimeException.GENERAL, e);
     }
-
-    Object selectedObject = readEntity(uriParserResultView, contextType);
+    Object selectedObject = readEntity(new JPAQueryBuilder(oDataJPAContext).build(uriParserResultView));
     if (selectedObject != null) {
-      try {
-        boolean isLocalTransaction = setTransaction();
-        em.remove(selectedObject);
-        em.flush();
-        if (isLocalTransaction) {
-          oDataJPAContext.getODataJPATransaction().commit();
-        }
 
-      } catch (Exception e) {
-        throw ODataJPARuntimeException.throwException(
-            ODataJPARuntimeException.ERROR_JPQL_DELETE_REQUEST, e);
+      boolean isLocalTransaction = setTransaction();
+      em.remove(selectedObject);
+      em.flush();
+      if (isLocalTransaction) {
+        oDataJPAContext.getODataJPATransaction().commit();
       }
     }
     return selectedObject;
@@ -402,31 +299,12 @@ public class JPAProcessorImpl implements JPAProcessor {
   }
 
   /* Common method for Read and Delete */
-  private Object readEntity(final Object uriParserResultView, final JPQLContextType contextType)
-      throws ODataJPAModelException, ODataJPARuntimeException {
-
+  private Object readEntity(final Query query) throws ODataJPARuntimeException {
     Object selectedObject = null;
-
-    if (uriParserResultView instanceof DeleteUriInfo || uriParserResultView instanceof GetEntityUriInfo
-        || uriParserResultView instanceof PutMergePatchUriInfo) {
-
-      JPQLContext selectJPQLContext = JPQLContext.createBuilder(
-          contextType, uriParserResultView).build();
-
-      JPQLStatement selectJPQLStatement = JPQLStatement.createBuilder(
-          selectJPQLContext).build();
-      Query query = null;
-      try {
-        query = em.createQuery(selectJPQLStatement.toString());
-        @SuppressWarnings("rawtypes")
-        final List resultList = query.getResultList();
-        if (!resultList.isEmpty()) {
-          selectedObject = resultList.get(0);
-        }
-      } catch (IllegalArgumentException e) {
-        throw ODataJPARuntimeException.throwException(
-            ODataJPARuntimeException.ERROR_JPQL_QUERY_CREATE, e);
-      }
+    @SuppressWarnings("rawtypes")
+    final List resultList = query.getResultList();
+    if (!resultList.isEmpty()) {
+      selectedObject = resultList.get(0);
     }
     return selectedObject;
   }
@@ -462,9 +340,12 @@ public class JPAProcessorImpl implements JPAProcessor {
         }
         return jpaEntity;
       }
-    } catch (Exception e) {
+    } catch (ODataBadRequestException e) {
+      throw ODataJPARuntimeException.throwException(
+          ODataJPARuntimeException.ERROR_JPQL_QUERY_CREATE, e);
+    } catch (EdmException e) {
       throw ODataJPARuntimeException.throwException(
-          ODataJPARuntimeException.ERROR_JPQL_CREATE_REQUEST, e);
+          ODataJPARuntimeException.ERROR_JPQL_QUERY_CREATE, e);
     }
     return null;
   }
@@ -472,21 +353,10 @@ public class JPAProcessorImpl implements JPAProcessor {
   private <T> Object processUpdate(PutMergePatchUriInfo updateView,
       final InputStream content, final Map<String, Object> properties, final String requestContentType)
       throws ODataJPAModelException, ODataJPARuntimeException {
-    JPQLContextType contextType = null;
     Object jpaEntity = null;
     try {
       boolean isLocalTransaction = setTransaction();
-      if (updateView instanceof PutMergePatchUriInfo) {
-        updateView = ((PutMergePatchUriInfo) updateView);
-        if (!((PutMergePatchUriInfo) updateView).getStartEntitySet().getName()
-            .equals(((PutMergePatchUriInfo) updateView).getTargetEntitySet().getName())) {
-          contextType = JPQLContextType.JOIN_SINGLE;
-        } else {
-          contextType = JPQLContextType.SELECT_SINGLE;
-        }
-      }
-
-      jpaEntity = readEntity(updateView, contextType);
+      jpaEntity = readEntity(new JPAQueryBuilder(oDataJPAContext).build(updateView));
 
       if (jpaEntity == null) {
         throw ODataJPARuntimeException
@@ -497,10 +367,10 @@ public class JPAProcessorImpl implements JPAProcessor {
       final EdmEntityType oDataEntityType = oDataEntitySet.getEntityType();
       final JPAEntity virtualJPAEntity = new JPAEntity(oDataEntityType, oDataEntitySet, oDataJPAContext);
       virtualJPAEntity.setJPAEntity(jpaEntity);
-
       if (content != null) {
         final ODataEntityParser oDataEntityParser = new ODataEntityParser(oDataJPAContext);
-        final ODataEntry oDataEntry = oDataEntityParser.parseEntry(oDataEntitySet, content, requestContentType, false);
+        ODataEntry oDataEntry;
+        oDataEntry = oDataEntityParser.parseEntry(oDataEntitySet, content, requestContentType, false);
         virtualJPAEntity.update(oDataEntry);
       } else if (properties != null) {
         virtualJPAEntity.update(properties);
@@ -511,11 +381,13 @@ public class JPAProcessorImpl implements JPAProcessor {
       if (isLocalTransaction) {
         oDataJPAContext.getODataJPATransaction().commit();
       }
-    } catch (Exception e) {
+    } catch (ODataBadRequestException e) {
       throw ODataJPARuntimeException.throwException(
-          ODataJPARuntimeException.ERROR_JPQL_UPDATE_REQUEST, e);
+          ODataJPARuntimeException.ERROR_JPQL_QUERY_CREATE, e);
+    } catch (EdmException e) {
+      throw ODataJPARuntimeException.throwException(
+          ODataJPARuntimeException.ERROR_JPQL_QUERY_CREATE, e);
     }
-
     return jpaEntity;
   }
 

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/cb29fa48/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAQueryBuilder.java
----------------------------------------------------------------------
diff --git a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAQueryBuilder.java b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAQueryBuilder.java
new file mode 100644
index 0000000..c5e61a8
--- /dev/null
+++ b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAQueryBuilder.java
@@ -0,0 +1,259 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+package org.apache.olingo.odata2.jpa.processor.core.access.data;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.uri.UriInfo;
+import org.apache.olingo.odata2.api.uri.info.DeleteUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntityCountUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntitySetCountUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntitySetUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntityUriInfo;
+import org.apache.olingo.odata2.api.uri.info.PutMergePatchUriInfo;
+import org.apache.olingo.odata2.jpa.processor.api.ODataJPAContext;
+import org.apache.olingo.odata2.jpa.processor.api.ODataJPAQueryExtensionEntityListener;
+import org.apache.olingo.odata2.jpa.processor.api.ODataJPATombstoneEntityListener;
+import org.apache.olingo.odata2.jpa.processor.api.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.jpa.processor.api.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLContext;
+import org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLContextType;
+import org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLStatement;
+import org.apache.olingo.odata2.jpa.processor.api.model.JPAEdmMapping;
+
+public class JPAQueryBuilder {
+
+  public enum UriInfoType {
+    GetEntitySet,
+    GetEntity,
+    GetEntitySetCount,
+    GetEntityCount,
+    PutMergePatch,
+    Delete
+  };
+
+  private EntityManager em = null;
+  private int pageSize = 0;
+
+  public JPAQueryBuilder(ODataJPAContext odataJPAContext) {
+    this.em = odataJPAContext.getEntityManager();
+    this.pageSize = odataJPAContext.getPageSize();
+  }
+
+  public JPAQueryInfo build(GetEntitySetUriInfo uriInfo) throws ODataJPARuntimeException {
+    JPAQueryInfo queryInfo = new JPAQueryInfo();
+    Query query = null;
+    try {
+      ODataJPATombstoneEntityListener listener = getODataJPATombstoneEntityListener((UriInfo) uriInfo);
+      if (listener != null) {
+        query = listener.getQuery(uriInfo, em);
+      }
+      if (query == null) {
+        query = buildQuery((UriInfo) uriInfo, UriInfoType.GetEntitySet);
+      } else {
+        queryInfo.setTombstoneQuery(true);
+      }
+    } catch (Exception e) {
+      throw ODataJPARuntimeException.throwException(
+          ODataJPARuntimeException.ERROR_JPQL_QUERY_CREATE, e);
+    }
+    queryInfo.setQuery(query);
+    return queryInfo;
+  }
+
+  public Query build(GetEntityUriInfo uriInfo) throws ODataJPARuntimeException {
+    Query query = null;
+    try {
+      ODataJPAQueryExtensionEntityListener listener = getODataJPAQuertEntityListener((UriInfo) uriInfo);
+      if (listener != null) {
+        query = listener.getQuery(uriInfo, em);
+      }
+      if (query == null) {
+        query = buildQuery((UriInfo) uriInfo, UriInfoType.GetEntity);
+      }
+    } catch (Exception e) {
+      throw ODataJPARuntimeException.throwException(
+          ODataJPARuntimeException.ERROR_JPQL_QUERY_CREATE, e);
+    }
+    return query;
+  }
+
+  public Query build(GetEntitySetCountUriInfo uriInfo) throws ODataJPARuntimeException {
+    Query query = null;
+    try {
+      ODataJPAQueryExtensionEntityListener listener = getODataJPAQuertEntityListener((UriInfo) uriInfo);
+      if (listener != null) {
+        query = listener.getQuery(uriInfo, em);
+      }
+      if (query == null) {
+        query = buildQuery((UriInfo) uriInfo, UriInfoType.GetEntitySetCount);
+      }
+    } catch (Exception e) {
+      throw ODataJPARuntimeException.throwException(
+          ODataJPARuntimeException.ERROR_JPQL_QUERY_CREATE, e);
+    }
+    return query;
+  }
+
+  public Query build(GetEntityCountUriInfo uriInfo) throws ODataJPARuntimeException {
+    Query query = null;
+    try {
+      ODataJPAQueryExtensionEntityListener listener = getODataJPAQuertEntityListener((UriInfo) uriInfo);
+      if (listener != null) {
+        query = listener.getQuery(uriInfo, em);
+      }
+      if (query == null) {
+        query = buildQuery((UriInfo) uriInfo, UriInfoType.GetEntityCount);
+      }
+    } catch (Exception e) {
+      throw ODataJPARuntimeException.throwException(
+          ODataJPARuntimeException.ERROR_JPQL_QUERY_CREATE, e);
+    }
+    return query;
+  }
+
+  public Query build(DeleteUriInfo uriInfo) throws ODataJPARuntimeException {
+    Query query = null;
+    try {
+      ODataJPAQueryExtensionEntityListener listener = getODataJPAQuertEntityListener((UriInfo) uriInfo);
+      if (listener != null) {
+        query = listener.getQuery(uriInfo, em);
+      }
+      if (query == null) {
+        query = buildQuery((UriInfo) uriInfo, UriInfoType.Delete);
+      }
+    } catch (Exception e) {
+      throw ODataJPARuntimeException.throwException(
+          ODataJPARuntimeException.ERROR_JPQL_QUERY_CREATE, e);
+    }
+    return query;
+  }
+
+  public Query build(PutMergePatchUriInfo uriInfo) throws ODataJPARuntimeException {
+    Query query = null;
+    try {
+      ODataJPAQueryExtensionEntityListener listener = getODataJPAQuertEntityListener((UriInfo) uriInfo);
+      if (listener != null) {
+        query = listener.getQuery(uriInfo, em);
+      }
+      if (query == null) {
+        query = buildQuery((UriInfo) uriInfo, UriInfoType.PutMergePatch);
+      }
+    } catch (Exception e) {
+      throw ODataJPARuntimeException.throwException(
+          ODataJPARuntimeException.ERROR_JPQL_QUERY_CREATE, e);
+    }
+    return query;
+  }
+
+  private Query buildQuery(UriInfo uriParserResultView, UriInfoType type)
+      throws EdmException,
+      ODataJPAModelException, ODataJPARuntimeException {
+
+    Query query = null;
+    JPQLContextType contextType = determineJPQLContextType(uriParserResultView, type);
+    JPQLContext jpqlContext = buildJPQLContext(contextType, uriParserResultView);
+    JPQLStatement jpqlStatement = JPQLStatement.createBuilder(jpqlContext)
+        .build();
+    query = em.createQuery(jpqlStatement.toString());
+
+    return query;
+  }
+
+  public ODataJPAQueryExtensionEntityListener getODataJPAQuertEntityListener(UriInfo uriInfo) throws EdmException,
+      InstantiationException, IllegalAccessException {
+    ODataJPAQueryExtensionEntityListener queryListener = null;
+    ODataJPATombstoneEntityListener listener = getODataJPATombstoneEntityListener(uriInfo);
+    if (listener instanceof ODataJPAQueryExtensionEntityListener) {
+      queryListener = (ODataJPAQueryExtensionEntityListener) listener;
+    }
+    return queryListener;
+  }
+
+  public ODataJPATombstoneEntityListener getODataJPATombstoneEntityListener(UriInfo uriParserResultView)
+      throws InstantiationException, IllegalAccessException, EdmException {
+    JPAEdmMapping mapping = (JPAEdmMapping) uriParserResultView.getTargetEntitySet().getEntityType().getMapping();
+    ODataJPATombstoneEntityListener listener = null;
+    if (mapping.getODataJPATombstoneEntityListener() != null) {
+      listener = (ODataJPATombstoneEntityListener) mapping.getODataJPATombstoneEntityListener().newInstance();
+    }
+    return listener;
+  }
+
+  public JPQLContext buildJPQLContext(JPQLContextType contextType, UriInfo uriParserResultView)
+      throws ODataJPAModelException, ODataJPARuntimeException {
+    JPQLContext jpqlContext = null;
+    if (pageSize > 0 && (contextType == JPQLContextType.SELECT || contextType == JPQLContextType.JOIN)) {
+      jpqlContext = JPQLContext.createBuilder(contextType,
+          uriParserResultView, true).build();
+    } else {
+      jpqlContext = JPQLContext.createBuilder(contextType,
+          uriParserResultView).build();
+    }
+    return jpqlContext;
+  }
+
+  public JPQLContextType determineJPQLContextType(UriInfo uriParserResultView, UriInfoType type) {
+    JPQLContextType contextType = null;
+
+    if (uriParserResultView.getNavigationSegments().size() > 0) {
+      if (type == UriInfoType.GetEntitySet) {
+        contextType = JPQLContextType.JOIN;
+      } else if (type == UriInfoType.Delete || type == UriInfoType.Delete || type == UriInfoType.GetEntity
+          || type == UriInfoType.PutMergePatch) {
+        contextType = JPQLContextType.JOIN_SINGLE;
+      } else if (type == UriInfoType.GetEntitySetCount || type == UriInfoType.GetEntityCount) {
+        contextType = JPQLContextType.JOIN_COUNT;
+      }
+    } else {
+      if (type == UriInfoType.GetEntitySet) {
+        contextType = JPQLContextType.SELECT;
+      } else if (type == UriInfoType.Delete || type == UriInfoType.GetEntity
+          || type == UriInfoType.PutMergePatch) {
+        contextType = JPQLContextType.SELECT_SINGLE;
+      } else if (type == UriInfoType.GetEntitySetCount || type == UriInfoType.GetEntityCount) {
+        contextType = JPQLContextType.SELECT_COUNT;
+      }
+    }
+    return contextType;
+  }
+
+  public final class JPAQueryInfo {
+    private Query query = null;
+    private boolean isTombstoneQuery = false;
+
+    public Query getQuery() {
+      return query;
+    }
+
+    public void setQuery(Query query) {
+      this.query = query;
+    }
+
+    public boolean isTombstoneQuery() {
+      return isTombstoneQuery;
+    }
+
+    public void setTombstoneQuery(boolean isTombstoneQuery) {
+      this.isTombstoneQuery = isTombstoneQuery;
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/cb29fa48/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/ODataJPAProcessorDefaultTest.java
----------------------------------------------------------------------
diff --git a/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/ODataJPAProcessorDefaultTest.java b/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/ODataJPAProcessorDefaultTest.java
index 8f7a413..9e4ced5 100644
--- a/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/ODataJPAProcessorDefaultTest.java
+++ b/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/ODataJPAProcessorDefaultTest.java
@@ -70,7 +70,12 @@ import org.apache.olingo.odata2.jpa.processor.api.ODataJPAContext;
 import org.apache.olingo.odata2.jpa.processor.api.ODataJPATransaction;
 import org.apache.olingo.odata2.jpa.processor.api.exception.ODataJPAModelException;
 import org.apache.olingo.odata2.jpa.processor.api.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.jpa.processor.api.model.JPAEdmMapping;
 import org.apache.olingo.odata2.jpa.processor.core.common.ODataJPATestConstants;
+import org.apache.olingo.odata2.jpa.processor.core.mock.ODataContextMock;
+import org.apache.olingo.odata2.jpa.processor.core.mock.ODataServiceMock;
+import org.apache.olingo.odata2.jpa.processor.core.mock.data.SalesOrderHeader;
+import org.apache.olingo.odata2.jpa.processor.core.model.JPAEdmMappingImpl;
 import org.apache.olingo.odata2.jpa.processor.core.model.JPAEdmTestModelView;
 import org.easymock.EasyMock;
 import org.junit.Assert;
@@ -130,10 +135,10 @@ public class ODataJPAProcessorDefaultTest extends JPAEdmTestModelView {
   @Test
   public void testExistsEntity() {
     try {
-      Assert.assertNotNull(objODataJPAProcessorDefault.existsEntity(getEntityCountCountUriInfo(),
+      Assert.assertNotNull(objODataJPAProcessorDefault.existsEntity(getEntityCountUriInfo(),
           HttpContentType.APPLICATION_XML));
       Assert.assertNull("ContentType MUST NOT set by entity provider", objODataJPAProcessorDefault.existsEntity(
-          getEntityCountCountUriInfo(), HttpContentType.APPLICATION_XML).getHeader(STR_CONTENT_TYPE));
+          getEntityCountUriInfo(), HttpContentType.APPLICATION_XML).getHeader(STR_CONTENT_TYPE));
     } catch (ODataException e) {
       fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
     } catch (Exception e) {
@@ -210,13 +215,15 @@ public class ODataJPAProcessorDefaultTest extends JPAEdmTestModelView {
     return getLocalUriInfo();
   }
 
-  private GetEntityCountUriInfo getEntityCountCountUriInfo() {
+  private GetEntityCountUriInfo getEntityCountUriInfo() {
     return getLocalUriInfo();
   }
 
   private DeleteUriInfo getDeletetUriInfo() {
     UriInfo objUriInfo = EasyMock.createMock(UriInfo.class);
     EasyMock.expect(objUriInfo.getStartEntitySet()).andStubReturn(getLocalEdmEntitySet());
+    List<NavigationSegment> navSegments = new ArrayList<NavigationSegment>();
+    EasyMock.expect(objUriInfo.getNavigationSegments()).andReturn(navSegments).anyTimes();
     EasyMock.expect(objUriInfo.getTargetEntitySet()).andStubReturn(getLocalEdmEntitySet());
     EasyMock.expect(objUriInfo.getSelect()).andStubReturn(null);
     EasyMock.expect(objUriInfo.getOrderBy()).andStubReturn(getOrderByExpression());
@@ -241,6 +248,8 @@ public class ODataJPAProcessorDefaultTest extends JPAEdmTestModelView {
   private UriInfo getLocalUriInfo() {
     UriInfo objUriInfo = EasyMock.createMock(UriInfo.class);
     EasyMock.expect(objUriInfo.getStartEntitySet()).andStubReturn(getLocalEdmEntitySet());
+    List<NavigationSegment> navSegments = new ArrayList<NavigationSegment>();
+    EasyMock.expect(objUriInfo.getNavigationSegments()).andReturn(navSegments).anyTimes();
     EasyMock.expect(objUriInfo.getTargetEntitySet()).andStubReturn(getLocalEdmEntitySet());
     EasyMock.expect(objUriInfo.getSelect()).andStubReturn(null);
     EasyMock.expect(objUriInfo.getOrderBy()).andStubReturn(getOrderByExpression());
@@ -286,8 +295,7 @@ public class ODataJPAProcessorDefaultTest extends JPAEdmTestModelView {
       EasyMock.expect(edmEntityType.hasStream()).andStubReturn(false);
       EasyMock.expect(edmEntityType.getNavigationPropertyNames()).andStubReturn(new ArrayList<String>());
       EasyMock.expect(edmEntityType.getKeyPropertyNames()).andStubReturn(new ArrayList<String>());
-      EasyMock.expect(edmEntityType.getMapping()).andStubReturn(getEdmMappingMockedObj(SALES_ORDER));// ID vs Salesorder
-                                                                                                     // ID
+      EasyMock.expect(edmEntityType.getMapping()).andStubReturn((EdmMapping) getEdmMappingMockedObj(SALES_ORDER));
       EasyMock.replay(edmEntityType);
     } catch (EdmException e) {
       fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
@@ -317,6 +325,7 @@ public class ODataJPAProcessorDefaultTest extends JPAEdmTestModelView {
 
   private ODataJPAContext getLocalmockODataJPAContext() {
     ODataJPAContext odataJPAContext = EasyMock.createMock(ODataJPAContext.class);
+    EasyMock.expect(odataJPAContext.getPageSize()).andReturn(0).anyTimes();
     EasyMock.expect(odataJPAContext.getPersistenceUnitName()).andStubReturn("salesorderprocessing");
     EasyMock.expect(odataJPAContext.getEntityManagerFactory()).andStubReturn(mockEntityManagerFactory());
     EasyMock.expect(odataJPAContext.getODataJPATransaction()).andStubReturn(getLocalJpaTransaction());
@@ -460,7 +469,7 @@ public class ODataJPAProcessorDefaultTest extends JPAEdmTestModelView {
       EasyMock.expect(edmEntityType.getPropertyNames()).andStubReturn(getLocalPropertyNames());
       EasyMock.expect(edmEntityType.getProperty(SO_ID)).andStubReturn(getEdmTypedMockedObj(SO_ID));
 
-      EasyMock.expect(edmEntityType.getMapping()).andStubReturn(getEdmMappingMockedObj(SALES_ORDER));
+      EasyMock.expect(edmEntityType.getMapping()).andStubReturn((EdmMapping) getEdmMappingMockedObj(SALES_ORDER));
 
       EasyMock.expect(edmEntityType.getKind()).andStubReturn(EdmTypeKind.SIMPLE);
       EasyMock.expect(edmEntityType.getNamespace()).andStubReturn(SALES_ORDER_HEADERS);
@@ -500,7 +509,7 @@ public class ODataJPAProcessorDefaultTest extends JPAEdmTestModelView {
   private EdmTyped getEdmTypedMockedObj(final String propertyName) {
     EdmProperty mockedEdmProperty = EasyMock.createMock(EdmProperty.class);
     try {
-      EasyMock.expect(mockedEdmProperty.getMapping()).andStubReturn(getEdmMappingMockedObj(propertyName));
+      EasyMock.expect(mockedEdmProperty.getMapping()).andStubReturn((EdmMapping) getEdmMappingMockedObj(propertyName));
       EdmType edmType = EasyMock.createMock(EdmType.class);
       EasyMock.expect(edmType.getKind()).andStubReturn(EdmTypeKind.SIMPLE);
       EasyMock.replay(edmType);
@@ -523,13 +532,15 @@ public class ODataJPAProcessorDefaultTest extends JPAEdmTestModelView {
     return facets;
   }
 
-  private EdmMapping getEdmMappingMockedObj(final String propertyName) {
-    EdmMapping mockedEdmMapping = EasyMock.createMock(EdmMapping.class);
+  private JPAEdmMapping getEdmMappingMockedObj(final String propertyName) {
+    JPAEdmMappingImpl mockedEdmMapping = EasyMock.createMock(JPAEdmMappingImpl.class);
     if (propertyName.equalsIgnoreCase(SALES_ORDER)) {
-      EasyMock.expect(mockedEdmMapping.getInternalName()).andStubReturn(SALES_ORDER_HEADERS);
+      EasyMock.expect(((EdmMapping) mockedEdmMapping).getInternalName()).andStubReturn(SALES_ORDER_HEADERS);
     } else {
-      EasyMock.expect(mockedEdmMapping.getInternalName()).andStubReturn(propertyName);
+      EasyMock.expect(((EdmMapping) mockedEdmMapping).getInternalName()).andStubReturn(propertyName);
     }
+    EasyMock.expect(mockedEdmMapping.getODataJPATombstoneEntityListener()).andReturn(null);
+    EasyMock.<Class<?>> expect(mockedEdmMapping.getJPAType()).andReturn(SalesOrderHeader.class);
     EasyMock.replay(mockedEdmMapping);
     return mockedEdmMapping;
   }
@@ -541,14 +552,16 @@ public class ODataJPAProcessorDefaultTest extends JPAEdmTestModelView {
   }
 
   private ODataContext getLocalODataContext() {
-    ODataContext objODataContext = EasyMock.createMock(ODataContext.class);
+    ODataContext objODataContext = null;
     try {
-      EasyMock.expect(objODataContext.getPathInfo()).andStubReturn(getLocalPathInfo());
-      EasyMock.expect(objODataContext.isInBatchMode()).andReturn(false).anyTimes();
+      ODataContextMock contextMock = new ODataContextMock();
+      contextMock.setODataService(new ODataServiceMock().mock());
+      contextMock.setPathInfo(getLocalPathInfo());
+      objODataContext = contextMock.mock();
+
     } catch (ODataException e) {
       fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
     }
-    EasyMock.replay(objODataContext);
     return objODataContext;
   }
 

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/cb29fa48/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAProcessorImplTest.java
----------------------------------------------------------------------
diff --git a/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAProcessorImplTest.java b/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAProcessorImplTest.java
index a62096b..4a00340 100644
--- a/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAProcessorImplTest.java
+++ b/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAProcessorImplTest.java
@@ -167,6 +167,7 @@ public class JPAProcessorImplTest {
     EasyMock.expect(objUriInfo.getFilter()).andStubReturn(getFilter());
     EasyMock.expect(objUriInfo.getKeyPredicates()).andStubReturn(getKeyPredicates());
     EasyMock.expect(objUriInfo.isLinks()).andStubReturn(false);
+    EasyMock.expect(objUriInfo.getNavigationSegments()).andReturn(new ArrayList<NavigationSegment>());
     EasyMock.replay(objUriInfo);
     return objUriInfo;
   }
@@ -209,6 +210,7 @@ public class JPAProcessorImplTest {
   private UriInfo getLocalUriInfo() {
     UriInfo objUriInfo = EasyMock.createMock(UriInfo.class);
     EasyMock.expect(objUriInfo.getStartEntitySet()).andStubReturn(getLocalEdmEntitySet());
+    EasyMock.expect(objUriInfo.getNavigationSegments()).andStubReturn(new ArrayList<NavigationSegment>());
     EasyMock.expect(objUriInfo.getTargetEntitySet()).andStubReturn(getLocalEdmEntitySet());
     EasyMock.expect(objUriInfo.getSelect()).andStubReturn(null);
     EasyMock.expect(objUriInfo.getOrderBy()).andStubReturn(getOrderByExpression());

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/cb29fa48/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAQueryBuilderTest.java
----------------------------------------------------------------------
diff --git a/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAQueryBuilderTest.java b/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAQueryBuilderTest.java
new file mode 100644
index 0000000..4c9fbaa
--- /dev/null
+++ b/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAQueryBuilderTest.java
@@ -0,0 +1,254 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+package org.apache.olingo.odata2.jpa.processor.core.access.data;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmEntityType;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmMapping;
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.processor.ODataContext;
+import org.apache.olingo.odata2.api.uri.NavigationSegment;
+import org.apache.olingo.odata2.api.uri.UriInfo;
+import org.apache.olingo.odata2.api.uri.info.DeleteUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntityCountUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntitySetCountUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntitySetUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntityUriInfo;
+import org.apache.olingo.odata2.api.uri.info.PutMergePatchUriInfo;
+import org.apache.olingo.odata2.jpa.processor.api.ODataJPAContext;
+import org.apache.olingo.odata2.jpa.processor.api.ODataJPAQueryExtensionEntityListener;
+import org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLContextType;
+import org.apache.olingo.odata2.jpa.processor.api.model.JPAEdmMapping;
+import org.apache.olingo.odata2.jpa.processor.core.access.data.JPAQueryBuilder.JPAQueryInfo;
+import org.apache.olingo.odata2.jpa.processor.core.access.data.JPAQueryBuilder.UriInfoType;
+import org.apache.olingo.odata2.jpa.processor.core.common.ODataJPATestConstants;
+import org.apache.olingo.odata2.jpa.processor.core.mock.ODataContextMock;
+import org.apache.olingo.odata2.jpa.processor.core.mock.ODataJPAContextMock;
+import org.apache.olingo.odata2.jpa.processor.core.model.JPAEdmMappingImpl;
+import org.easymock.EasyMock;
+import org.junit.Before;
+import org.junit.Test;
+
+public class JPAQueryBuilderTest {
+  JPAQueryBuilder builder = null;
+
+  @Before
+  public void setup() {
+    ODataContextMock odataContextMock = new ODataContextMock();
+    ODataContext context;
+    try {
+      context = odataContextMock.mock();
+      ODataJPAContext odataJPAContext = ODataJPAContextMock.mockODataJPAContext(context);
+      builder = new JPAQueryBuilder(odataJPAContext);
+    } catch (ODataException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+  }
+
+  @Test
+  public void buildGetEntityTest() {
+    try {
+      assertNotNull(builder.build((GetEntityUriInfo) mockURIInfoWithListener(false)));
+    } catch (ODataException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+  }
+
+  @Test
+  public void buildGetEntitySetTest() {
+    try {
+      JPAQueryInfo info = builder.build((GetEntitySetUriInfo) mockURIInfoWithListener(false));
+      assertNotNull(info.getQuery());
+      assertEquals(true, info.isTombstoneQuery());
+    } catch (ODataException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+  }
+
+  @Test
+  public void buildDeleteEntityTest() {
+    try {
+      assertNotNull(builder.build((DeleteUriInfo) mockURIInfoWithListener(false)));
+    } catch (ODataException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+  }
+
+  @Test
+  public void buildGetEntitySetCountTest() {
+    try {
+      assertNotNull(builder.build((GetEntitySetCountUriInfo) mockURIInfoWithListener(false)));
+    } catch (ODataException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+  }
+
+  @Test
+  public void buildGetEntityCountTest() {
+    try {
+      assertNotNull(builder.build((GetEntityCountUriInfo) mockURIInfoWithListener(false)));
+    } catch (ODataException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+  }
+
+  @Test
+  public void buildPutMergePatchTest() {
+    try {
+      assertNotNull(builder.build((PutMergePatchUriInfo) mockURIInfoWithListener(false)));
+    } catch (ODataException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+  }
+
+  @Test
+  public void determineGetEntityTest() {
+    try {
+      assertEquals(JPQLContextType.JOIN_SINGLE, builder.determineJPQLContextType(mockURIInfoWithListener(true),
+          UriInfoType.GetEntity));
+    } catch (ODataException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+  }
+
+  @Test
+  public void determineGetEntityCountTest() {
+    try {
+      assertEquals(JPQLContextType.JOIN_COUNT, builder.determineJPQLContextType(mockURIInfoWithListener(true),
+          UriInfoType.GetEntityCount));
+    } catch (ODataException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+  }
+
+  @Test
+  public void determineGetEntitySetTest() {
+    try {
+      assertEquals(JPQLContextType.JOIN, builder.determineJPQLContextType(mockURIInfoWithListener(true),
+          UriInfoType.GetEntitySet));
+    } catch (ODataException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+  }
+
+  @Test
+  public void determineGetEntitySetCountTest() {
+    try {
+      assertEquals(JPQLContextType.JOIN_COUNT, builder.determineJPQLContextType(mockURIInfoWithListener(true),
+          UriInfoType.GetEntitySetCount));
+    } catch (ODataException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+  }
+
+  @Test
+  public void determinePutMergePatchTest() {
+    try {
+      assertEquals(JPQLContextType.JOIN_SINGLE, builder.determineJPQLContextType(mockURIInfoWithListener(true),
+          UriInfoType.PutMergePatch));
+    } catch (ODataException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+  }
+
+  @Test
+  public void determineDeleteTest() {
+    try {
+      assertEquals(JPQLContextType.JOIN_SINGLE, builder.determineJPQLContextType(mockURIInfoWithListener(true),
+          UriInfoType.Delete));
+    } catch (ODataException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+  }
+
+  private UriInfo mockURIInfoWithListener(boolean isNavigationEnabled) throws EdmException {
+    UriInfo uriInfo = EasyMock.createMock(UriInfo.class);
+    if (isNavigationEnabled) {
+      List<NavigationSegment> navSegments = new ArrayList<NavigationSegment>();
+      navSegments.add(null);
+      EasyMock.expect(uriInfo.getNavigationSegments()).andReturn(navSegments);
+      EasyMock.replay(uriInfo);
+      return uriInfo;
+    }
+    EdmEntityType edmEntityType = EasyMock.createMock(EdmEntityType.class);
+    EasyMock.expect(edmEntityType.getMapping()).andReturn((EdmMapping) mockEdmMapping());
+    EdmEntitySet edmEntitySet = EasyMock.createMock(EdmEntitySet.class);
+    EasyMock.expect(edmEntitySet.getEntityType()).andReturn(edmEntityType);
+    EasyMock.expect(uriInfo.getTargetEntitySet()).andReturn(edmEntitySet);
+    EasyMock.replay(edmEntityType, edmEntitySet, uriInfo);
+    return uriInfo;
+
+  }
+
+  private JPAEdmMapping mockEdmMapping() {
+    JPAEdmMappingImpl mockedEdmMapping = new JPAEdmMappingImpl();
+    mockedEdmMapping.setODataJPATombstoneEntityListener(JPAQueryExtensionMock.class);
+    return mockedEdmMapping;
+  }
+
+  public static final class JPAQueryExtensionMock extends ODataJPAQueryExtensionEntityListener {
+    Query query = EasyMock.createMock(Query.class);
+
+    @Override
+    public Query getQuery(GetEntityUriInfo uriInfo, EntityManager em) {
+      return query;
+    }
+
+    @Override
+    public Query getQuery(GetEntitySetUriInfo uriInfo, EntityManager em) {
+      return query;
+    }
+
+    @Override
+    public Query getQuery(GetEntitySetCountUriInfo uriInfo, EntityManager em) {
+      return query;
+    }
+
+    @Override
+    public Query getQuery(DeleteUriInfo uriInfo, EntityManager em) {
+      return query;
+    }
+
+    @Override
+    public Query getQuery(GetEntityCountUriInfo uriInfo, EntityManager em) {
+      return query;
+    }
+
+    @Override
+    public Query getQuery(PutMergePatchUriInfo uriInfo, EntityManager em) {
+      return query;
+    }
+
+    @Override
+    public boolean isTombstoneSupported() {
+      return false;
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/cb29fa48/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/mock/ODataContextMock.java
----------------------------------------------------------------------
diff --git a/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/mock/ODataContextMock.java b/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/mock/ODataContextMock.java
index e39d3af..8d4fab1 100644
--- a/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/mock/ODataContextMock.java
+++ b/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/mock/ODataContextMock.java
@@ -28,6 +28,7 @@ public class ODataContextMock {
 
   private ODataService odataService;
   private PathInfo pathInfo;
+  private boolean isInBatchMode;
 
   public void setODataService(final ODataService service) {
     odataService = service;
@@ -37,6 +38,10 @@ public class ODataContextMock {
     this.pathInfo = pathInfo;
   }
 
+  public void isInBatchMode(final boolean isInBatchMode) {
+    this.isInBatchMode = isInBatchMode;
+  }
+
   public ODataContext mock() throws ODataException {
     ODataContext context = EasyMock.createMock(ODataContext.class);
     EasyMock.expect(context.getService()).andReturn(odataService).anyTimes();
@@ -44,6 +49,7 @@ public class ODataContextMock {
     ODataJPAServiceFactoryMock mockServiceFactory = new ODataJPAServiceFactoryMock(context);
     mockServiceFactory.initializeODataJPAContext();
     EasyMock.expect(context.getServiceFactory()).andReturn(mockServiceFactory).anyTimes();
+    EasyMock.expect(context.isInBatchMode()).andReturn(this.isInBatchMode).anyTimes();
     EasyMock.replay(context);
     return context;
   }
@@ -52,6 +58,7 @@ public class ODataContextMock {
     ODataContext context = EasyMock.createMock(ODataContext.class);
     EasyMock.expect(context.getService()).andReturn(odataService).anyTimes();
     EasyMock.expect(context.getPathInfo()).andReturn(pathInfo).anyTimes();
+    EasyMock.expect(context.isInBatchMode()).andReturn(this.isInBatchMode).anyTimes();
     ODataJPAServiceFactoryMock mockServiceFactory = new ODataJPAServiceFactoryMock(context);
     mockServiceFactory.initializeODataJPAContextX();
     EasyMock.expect(context.getServiceFactory()).andReturn(mockServiceFactory).anyTimes();

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/cb29fa48/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/mock/ODataJPAContextMock.java
----------------------------------------------------------------------
diff --git a/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/mock/ODataJPAContextMock.java b/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/mock/ODataJPAContextMock.java
index 433f784..9e03c86 100644
--- a/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/mock/ODataJPAContextMock.java
+++ b/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/mock/ODataJPAContextMock.java
@@ -54,6 +54,7 @@ public abstract class ODataJPAContextMock {
     EasyMock.expect(odataJPAContext.getJPAEdmExtension()).andReturn(null);
     EasyMock.expect(odataJPAContext.getDefaultNaming()).andReturn(true);
     EasyMock.expect(odataJPAContext.getODataContext()).andReturn(context).anyTimes();
+    EasyMock.expect(odataJPAContext.getPageSize()).andReturn(0);
 
     EasyMock.replay(odataJPAContext);
     return odataJPAContext;

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/cb29fa48/odata2-jpa-processor/jpa-ref/src/main/java/org/apache/olingo/odata2/jpa/processor/ref/model/Customer.java
----------------------------------------------------------------------
diff --git a/odata2-jpa-processor/jpa-ref/src/main/java/org/apache/olingo/odata2/jpa/processor/ref/model/Customer.java b/odata2-jpa-processor/jpa-ref/src/main/java/org/apache/olingo/odata2/jpa/processor/ref/model/Customer.java
index bf5010b..0605956 100644
--- a/odata2-jpa-processor/jpa-ref/src/main/java/org/apache/olingo/odata2/jpa/processor/ref/model/Customer.java
+++ b/odata2-jpa-processor/jpa-ref/src/main/java/org/apache/olingo/odata2/jpa/processor/ref/model/Customer.java
@@ -26,6 +26,7 @@ import javax.persistence.CascadeType;
 import javax.persistence.Column;
 import javax.persistence.Embedded;
 import javax.persistence.Entity;
+import javax.persistence.EntityListeners;
 import javax.persistence.EnumType;
 import javax.persistence.Enumerated;
 import javax.persistence.Id;
@@ -34,6 +35,7 @@ import javax.persistence.Table;
 
 @Entity
 @Table(name = "T_CUSTOMER")
+@EntityListeners(org.apache.olingo.odata2.jpa.processor.ref.listeners.CustomerQueryExtension.class)
 public class Customer extends CustomerBase {
 
   @Id

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/cb29fa48/odata2-jpa-processor/jpa-web/src/main/java/org/apache/olingo/odata2/jpa/processor/ref/web/JPAReferenceServiceFactory.java
----------------------------------------------------------------------
diff --git a/odata2-jpa-processor/jpa-web/src/main/java/org/apache/olingo/odata2/jpa/processor/ref/web/JPAReferenceServiceFactory.java b/odata2-jpa-processor/jpa-web/src/main/java/org/apache/olingo/odata2/jpa/processor/ref/web/JPAReferenceServiceFactory.java
index c264f70..fa499c8 100644
--- a/odata2-jpa-processor/jpa-web/src/main/java/org/apache/olingo/odata2/jpa/processor/ref/web/JPAReferenceServiceFactory.java
+++ b/odata2-jpa-processor/jpa-web/src/main/java/org/apache/olingo/odata2/jpa/processor/ref/web/JPAReferenceServiceFactory.java
@@ -46,6 +46,7 @@ public class JPAReferenceServiceFactory extends ODataJPAServiceFactory {
     oDataJPAContext.setJPAEdmExtension(new SalesOrderProcessingExtension());
     oDataJPAContext.setPageSize(PAGE_SIZE);
     oDataJPAContext.setDefaultNaming(false);
+    oDataJPAContext.getODataContext().setDebugMode(true);
     setErrorLevel();
     setOnWriteJPAContent(onDBWriteContent);
     return oDataJPAContext;