1

I am recenttly working on a JAVA project with a mongoDB database. Being so i decided to use eclipselink 2.4. Regarding queries, it allows the usual "SQL like" queries but also (supposedly) allows native mongoDB queries. I followed this tutorial and put everything working. I am able to run a findOne() native mongoDB query (queryOne) but i am not able to run find() queries (queryAll does no work)...

  1. Query queryOne = em.createNativeQuery("db.ORDER.findOne()", Order.class);

  2. Query queryAll = em.createNativeQuery("db.ORDER.find()", Order.class);

I get the error when executing the query:

Exception in thread "main" Local Exception Stack: 
Exception [EclipseLink-6044] (Eclipse Persistence Services - 2.4.0.v20120608-r11652): org.eclipse.persistence.exceptions.QueryException
Exception Description: The primary key read from the row [EISMappedRecord(
    value => DBQuery: myTest.ORDER -> undefined)] during the execution of the query was detected to be null.  Primary keys must not contain null.
Query: ReadAllQuery(referenceClass=Order )
    at org.eclipse.persistence.exceptions.QueryException.nullPrimaryKeyInBuildingObject(QueryException.java:912)
    at org.eclipse.persistence.internal.descriptors.ObjectBuilder.buildObject(ObjectBuilder.java:586)
    at org.eclipse.persistence.internal.descriptors.ObjectBuilder.buildObject(ObjectBuilder.java:562)
    at org.eclipse.persistence.queries.ObjectLevelReadQuery.buildObject(ObjectLevelReadQuery.java:776)
    at org.eclipse.persistence.queries.ReadAllQuery.registerResultInUnitOfWork(ReadAllQuery.java:781)
    at org.eclipse.persistence.queries.ReadAllQuery.executeObjectLevelReadQuery(ReadAllQuery.java:433)
    at org.eclipse.persistence.queries.ObjectLevelReadQuery.executeDatabaseQuery(ObjectLevelReadQuery.java:1149)
    at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:852)
    at org.eclipse.persistence.queries.ObjectLevelReadQuery.execute(ObjectLevelReadQuery.java:1108)
    at org.eclipse.persistence.queries.ReadAllQuery.execute(ReadAllQuery.java:392)
    at org.eclipse.persistence.queries.ObjectLevelReadQuery.executeInUnitOfWork(ObjectLevelReadQuery.java:1196)
    at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2875)
    at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1602)
    at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1584)
    at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1549)
    at org.eclipse.persistence.internal.jpa.QueryImpl.executeReadQuery(QueryImpl.java:231)
    at org.eclipse.persistence.internal.jpa.QueryImpl.getResultList(QueryImpl.java:411)
    at example.Test.testQuery(Test.java:171)
    at example.Test.main(Test.java:54)

The execution of the query with resorting to the MongoDB shell:

{ "_id" : "5061DC17E4B0881F592675A5", "TOTALCOST" : 3187, "SHIPPINGADDRESS" : [     {   "POSTALCODE" : "L5J1H7",    "COUNTRY" : "Canada",   "PROVINCE" : "ON",  "CITY" : "Ottawa",  "STREET" : "17 Jane St." } ], "ORDERLINES" : [  {   "DESCRIPTION" : "machine",  "COST" : 2999,  "LINENUMBER" : 1 },     {   "DESCRIPTION" : "shipping",     "COST" : 129,   "LINENUMBER" : 2 },     {   "DESCRIPTION" : "installation",     "COST" : 59,    "LINENUMBER" : 3 } ], "VERSION" : NumberLong(1), "DESCRIPTION" : "Pinball machine", "CUSTOMER__id" : "5061DC17E4B0881F592675A4", "BILLINGADDRESS" : [   {   "POSTALCODE" : "L5J1H7",    "COUNTRY" : "Canada",   "PROVINCE" : "ON",  "CITY" : "Ottawa",  "STREET" : "17 Jane St." } ] }
{ "_id" : "5061DC17E4B0881F592675A6", "TOTALCOST" : 565, "SHIPPINGADDRESS" : [  {   "POSTALCODE" : "L5J1H7",    "COUNTRY" : "Canada",   "PROVINCE" : "ON",  "CITY" : "Ottawa",  "STREET" : "17 Jane St." } ], "ORDERLINES" : [  {   "DESCRIPTION" : "machine",  "COST" : 500,   "LINENUMBER" : 1 },     {   "DESCRIPTION" : "balls",    "COST" : 5,     "LINENUMBER" : 2 },     {   "DESCRIPTION" : "shipping",     "COST" : 60,    "LINENUMBER" : 3 } ], "VERSION" : NumberLong(1), "DESCRIPTION" : "Foosball", "CUSTOMER__id" : "5061DC17E4B0881F592675A4", "BILLINGADDRESS" : [  {   "POSTALCODE" : "L5J1H8",    "COUNTRY" : "Canada",   "PROVINCE" : "ON",  "CITY" : "Ottawa",  "STREET" : "7 Bank St." } ] }
{ "_id" : "5061DC17E4B0881F592675A8", "TOTALCOST" : 402, "SHIPPINGADDRESS" : [  {   "POSTALCODE" : "L5J1H7",    "COUNTRY" : "Canada",   "PROVINCE" : "ON",  "CITY" : "Ottawa",  "STREET" : "17 Jane St." } ], "ORDERLINES" : [  {   "DESCRIPTION" : "table",    "COST" : 300,   "LINENUMBER" : 1 },     {   "DESCRIPTION" : "balls",    "COST" : 5,     "LINENUMBER" : 2 },     {   "DESCRIPTION" : "rackets",  "COST" : 15,    "LINENUMBER" : 3 },     {   "DESCRIPTION" : "net",  "COST" : 2,     "LINENUMBER" : 4 },     {   "DESCRIPTION" : "shipping",     "COST" : 80,    "LINENUMBER" : 5 } ], "VERSION" : NumberLong(1), "DESCRIPTION" : "Pingpong table", "CUSTOMER__id" : "5061DC17E4B0881F592675A7", "BILLINGADDRESS" : [    {   "POSTALCODE" : "L5J1H8",    "COUNTRY" : "Canada", "PROVINCE" : "ON",    "CITY" : "Ottawa",  "STREET" : "7 Bank St." } ] }

If you could tell me how to fix this or a little workaround i would appreciate it.

EDIT: JPQL queries can be useful, i am using some as a workaround, however, i am not currently able to query for references ids. For example, if i have an Order with a Customer reference (the order saves only the id of the customer) with mongoDB queries i would search like taht:

db.ORDER.find({"CUSTOMER__id": "ID"})

The JPQL similar query i believe that would be like:

query = em.createQuery("Select o from Order o where o.customer.id = \"ID\"");

However, once again... not working!! Error:

Exception in thread "main" Local Exception Stack: 
Exception [EclipseLink-6168] (Eclipse Persistence Services - 2.4.0.v20120608-r11652): org.eclipse.persistence.exceptions.QueryException
Exception Description: Query failed to prepare, unexpected error occurred: [java.lang.ClassCastException: org.eclipse.persistence.eis.mappings.EISOneToOneMapping cannot be cast to org.eclipse.persistence.mappings.OneToOneMapping].
Internal Exception: java.lang.ClassCastException: org.eclipse.persistence.eis.mappings.EISOneToOneMapping cannot be cast to org.eclipse.persistence.mappings.OneToOneMapping
Query: ReadAllQuery(referenceClass=Order jpql="Select o from Order o where o.customer.id = "ID"")
    at org.eclipse.persistence.exceptions.QueryException.prepareFailed(QueryException.java:1572)
    at org.eclipse.persistence.queries.DatabaseQuery.checkPrepare(DatabaseQuery.java:633)
    at org.eclipse.persistence.queries.ObjectLevelReadQuery.checkPrepare(ObjectLevelReadQuery.java:882)
    at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:838)
    at org.eclipse.persistence.queries.ObjectLevelReadQuery.execute(ObjectLevelReadQuery.java:1108)
    at org.eclipse.persistence.queries.ReadAllQuery.execute(ReadAllQuery.java:392)
    at org.eclipse.persistence.queries.ObjectLevelReadQuery.executeInUnitOfWork(ObjectLevelReadQuery.java:1196)
    at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2875)
    at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1602)
    at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1584)
    at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1549)
    at org.eclipse.persistence.internal.jpa.QueryImpl.executeReadQuery(QueryImpl.java:231)
    at org.eclipse.persistence.internal.jpa.QueryImpl.getResultList(QueryImpl.java:411)
    at example.Test.testQuery(Test.java:175)
    at example.Test.main(Test.java:55)
Caused by: java.lang.ClassCastException: org.eclipse.persistence.eis.mappings.EISOneToOneMapping cannot be cast to org.eclipse.persistence.mappings.OneToOneMapping
    at org.eclipse.persistence.internal.expressions.RelationExpression.checkForeignKeyJoinOptimization(RelationExpression.java:512)
    at org.eclipse.persistence.internal.expressions.RelationExpression.normalize(RelationExpression.java:535)
    at org.eclipse.persistence.internal.expressions.SQLSelectStatement.normalize(SQLSelectStatement.java:1365)
    at org.eclipse.persistence.internal.queries.ExpressionQueryMechanism.buildNormalSelectStatement(ExpressionQueryMechanism.java:543)
    at org.eclipse.persistence.internal.queries.ExpressionQueryMechanism.prepareSelectAllRows(ExpressionQueryMechanism.java:1675)
    at org.eclipse.persistence.queries.ReadAllQuery.prepareSelectAllRows(ReadAllQuery.java:719)
    at org.eclipse.persistence.queries.ReadAllQuery.prepare(ReadAllQuery.java:656)
    at org.eclipse.persistence.queries.DatabaseQuery.checkPrepare(DatabaseQuery.java:614)
    ... 13 more

Thanks

lage
  • 589
  • 2
  • 5
  • 18

2 Answers2

0

It appears its trying to fetch an object which has primary key as null. Moreover the records are A5, A6 and A8. Looks like A7 is messed up if they were created in sequence?

Would it be possible to drop the ORDER document and again run the tests (insert and get)?

Anshu
  • 7,783
  • 5
  • 31
  • 41
  • The ids are okay, the A7 would be a Customer, considering the order of the persists in the code. Everytime i run the tests i drop the entire DB and create it from scratch... – lage Sep 25 '12 at 17:03
  • I see.. doesn't look like a bug in your code. We must be missing something – Anshu Sep 25 '12 at 17:45
  • Yap... I'm afraid that the find() query may not be supported, however there isn't any documentation stating that... Thanks for your help... – lage Sep 25 '12 at 18:50
0

I don't think find() works the same as findOne() through the native MongoDB API.

What happen when you execute the native query without the class?

i.e. Query queryAll = em.createNativeQuery("db.ORDER.find()"); queryAll.getResultList();

What do you get back?

I don't think the native find() is directly supported (but you can use JPQL for most queries). Please log a bug for this, there should be some way to get it to work.

James
  • 17,965
  • 11
  • 91
  • 146
  • Hi, thanks for responding. When i run without the class i get a classCast excpetion (org.eclipse.persistence.nosql.adapters.mongo.MongoPlatform cannot be cast to org.eclipse.persistence.platform.database.DatabasePlatform) so i assume that this method is not supported for nosql. Regarding JPQL queries, i updated the question with my problems with JPQL, if you could have a look ;) Thanks – lage Sep 26 '12 at 13:48
  • Please log a bug for both issues. – James Sep 27 '12 at 13:54
  • For the second issue, try using o.customer = :customer and pass an instance as the argument, you could also map the customerId, or define a query key. – James Sep 27 '12 at 13:55
  • Hi, I had to give up on JPA for this project due to these limitations... Anyway I logged a bug, just hope the next version will be better, since JPA for NoSQL would be a great help. Thanks – lage Oct 04 '12 at 13:12
  • I ended up doing something very nasty, I think. I created a function in mongodb that would take the cursor from find and return the concatenated ids as a csv formatted string. Then I would run a second query for the Ids. I hated it, but I had to get it out. – Ernesto Sep 29 '14 at 13:59