Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » EclipseLink » Problem mongodb query/find by id
Problem mongodb query/find by id [message #1031352] Mon, 01 April 2013 16:07 Go to next message
Jason Saint is currently offline Jason SaintFriend
Messages: 4
Registered: April 2013
Junior Member
Using Eclipselink version 2.4.2-RC1 because of Bug 392174. Mongodb version is 2.4.0.

I am having a problem searching for a document by the mongo generated OID.

I have a simple mongo entity, Exercise, mapped to a collection called 'exercises. The id is mapped to _id as @GeneratedValue.

The document already exists in the collection.

 db.exercises.findOne()
{
        "_id" : ObjectId("5155ccb4f4b5a31e95000334"),
        "name" : "Unicycling",
        "description" : "unicycling"
}


Searching by id using:
    String exerciseId = "5155ccb4f4b5a31e95000334";
    Exercise testExercise = em.find(Exercise.class,exerciseId);


returns no results:

[EL Fine]: sql: 2013-04-01 10:25:20.203--ServerSession(529858968)--Connection(102824579)--Thread(Thread[main,5,main])--Executing MappedInteraction()
	spec => null
	properties => {mongo.collection=exercises, mongo.operation=FIND}
	input => [5155ccb4f4b5a31e95000334]
[EL Finest]: query: 2013-04-01 10:25:20.394--ServerSession(529858968)--Thread(Thread[main,5,main])--Adapter result: null
[EL Finest]: query: 2013-04-01 10:25:20.394--ServerSession(529858968)--Thread(Thread[main,5,main])--Data access result: null


I have also tried JPQL:

[code]
String id = "5155ccb4f4b5a31e95000334";
Query query = getEntityManager().createQuery("SELECT e FROM Exercise e WHERE e.id = :id");
query.setParameter("id", id);
List<Exercise> exercises = query.getResultList();
[\code]

Also with no results.

I am however able to query by one of the other fields:

    String description = "unicycling";
    Query query = getEntityManager().createQuery("SELECT e FROM Exercise e WHERE e.description = :description");
    query.setParameter("description", description);
    List<Exercise> exercises = query.getResultList();


[EL Fine]: sql: 2013-04-01 10:52:20.868--ServerSession(305297482)--Connection(70630159)--Thread(Thread[main,5,main])--Executing MappedInteraction()
	spec => null
	properties => {mongo.collection=exercises, mongo.operation=FIND}
	input => [DatabaseRecord(
	exercises.description => unicycling)]
[EL Finest]: query: 2013-04-01 10:52:21.772--ServerSession(305297482)--Thread(Thread[main,5,main])--Adapter result: [{_id=5155ccb4f4b5a31e95000334, description=unicycling, name=Unicycling}]


Once the record has been found by another search (or by a findAll()), the JPQL method of finding by id will return a record (I am assuming from the EntityManager cache). The EntityManager.find() method however still does not return results.

Has anyone else seen this behavior or have a workaround?

Thanks,
Jason
Re: Problem mongodb query/find by id [message #1032061 is a reply to message #1031352] Tue, 02 April 2013 14:20 Go to previous messageGo to next message
James Sutherland is currently offline James SutherlandFriend
Messages: 1939
Registered: July 2009
Location: Ottawa, Canada
Senior Member

That is odd. We have similar tests that work.

Did EclipseLink insert the data, or did you manually insert it?
How did you map the Id?

Try using a byte[] or and ObjectId as the parameter instead of the hex string.


James : Wiki : Book : Blog : Twitter
Re: Problem mongodb query/find by id [message #1032888 is a reply to message #1032061] Wed, 03 April 2013 15:14 Go to previous messageGo to next message
Jason Saint is currently offline Jason SaintFriend
Messages: 4
Registered: April 2013
Junior Member
The data was inserted manually.

The id is mapped as:
    @Id
    @GeneratedValue
    @Field(name="_id")
    public String getId() {
        return this.id;
    }


Changing the id from String to byte[] produces the same null result.

When I try to use ObjectId as the id type I get a conversion exception.


Exception [EclipseLink-3001] (Eclipse Persistence Services - 2.4.2.v20130315-93567e3): org.eclipse.persistence.exceptions.ConversionException
Exception Description: The object [5155ccb4f4b5a31e95000334], of class [class org.bson.types.ObjectId], could not be converted to [class [B].
	at org.eclipse.persistence.exceptions.ConversionException.couldNotBeConverted(ConversionException.java:71)
	at org.eclipse.persistence.internal.helper.ConversionManager.convertObjectToByteArray(ConversionManager.java:344)
	at org.eclipse.persistence.internal.helper.ConversionManager.convertObject(ConversionManager.java:134)
	at org.eclipse.persistence.internal.oxm.XMLConversionManager.convertObject(XMLConversionManager.java:186)
	at org.eclipse.persistence.internal.databaseaccess.DatasourcePlatform.convertObject(DatasourcePlatform.java:162)
	at org.eclipse.persistence.internal.descriptors.ObjectBuilder.extractPrimaryKeyFromRow(ObjectBuilder.java:2545)
	at org.eclipse.persistence.internal.descriptors.ObjectBuilder.extractPrimaryKeyFromExpression(ObjectBuilder.java:2392)
	at org.eclipse.persistence.internal.queries.ExpressionQueryMechanism.checkCacheForObject(ExpressionQueryMechanism.java:866)
	at org.eclipse.persistence.queries.ReadObjectQuery.checkEarlyReturnLocal(ReadObjectQuery.java:243)
	at org.eclipse.persistence.queries.ObjectLevelReadQuery.checkEarlyReturn(ObjectLevelReadQuery.java:838)
	at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:789)
	at org.eclipse.persistence.queries.ObjectLevelReadQuery.execute(ObjectLevelReadQuery.java:1109)
	at org.eclipse.persistence.queries.ReadObjectQuery.execute(ReadObjectQuery.java:421)
	at org.eclipse.persistence.queries.ObjectLevelReadQuery.executeInUnitOfWork(ObjectLevelReadQuery.java:1197)
	at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2879)
	at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1607)
	at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1589)
	at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1554)
	at org.eclipse.persistence.internal.jpa.QueryImpl.executeReadQuery(QueryImpl.java:231)
	at org.eclipse.persistence.internal.jpa.QueryImpl.getResultList(QueryImpl.java:403)


I can retrieve by the object Id using a native query, but I can't get native queries to work with Auth turned on.

Thanks for your help.
Re: Problem mongodb query/find by id [message #1037404 is a reply to message #1032888] Tue, 09 April 2013 14:12 Go to previous messageGo to next message
James Sutherland is currently offline James SutherlandFriend
Messages: 1939
Registered: July 2009
Location: Ottawa, Canada
Senior Member

Can you try having EclipseLink insert the data.

James : Wiki : Book : Blog : Twitter
Re: Problem mongodb query/find by id [message #1039139 is a reply to message #1037404] Thu, 11 April 2013 20:10 Go to previous messageGo to next message
Jason Saint is currently offline Jason SaintFriend
Messages: 4
Registered: April 2013
Junior Member
When I try to use the EntityManager.persist method, it appears to work from the Java side. I can query the created object by id. However, it only appears to be written to the entity manager cache. It never gets persisted to mongo.


EDIT

I had the persist method wrapped in a Facade class. I had not yet added the transaction or flush. I added that and now get an exception that my class is not a known entity type.

It is included in the persistence.xml but I still see the exception.

[Updated on: Thu, 11 April 2013 20:20]

Report message to a moderator

Re: Problem mongodb query/find by id [message #1039172 is a reply to message #1039139] Thu, 11 April 2013 21:24 Go to previous messageGo to next message
Jason Saint is currently offline Jason SaintFriend
Messages: 4
Registered: April 2013
Junior Member
The exception turned out to be Glassfish related. A restart of the app server and a redeploy of the application fixed it. The object still was not written to the collection however.

I had the entity declared as:

@Entity
@NoSql(dataType="exercises",dataFormat=DataFormatType.MAPPED)
public class Exercise extends BaseEntity {
...
}


When I remove the dataType and let JPA insert to the default collection name EXERCISE, everything works as expected.

Is overriding the default collection name supported?

Re: Problem mongodb query/find by id [message #1042464 is a reply to message #1039172] Tue, 16 April 2013 13:17 Go to previous messageGo to next message
James Sutherland is currently offline James SutherlandFriend
Messages: 1939
Registered: July 2009
Location: Ottawa, Canada
Senior Member

What error do you get? Enable logging on finest and include the log.


James : Wiki : Book : Blog : Twitter
Re: Problem mongodb query/find by id [message #1052646 is a reply to message #1042464] Tue, 30 April 2013 10:49 Go to previous messageGo to next message
David Courtin is currently offline David CourtinFriend
Messages: 4
Registered: April 2013
Junior Member
I've got the same problem. My eclipselink version : 2.4.1.

My class :

@Entity
@NoSql(dataFormat=DataFormatType.MAPPED, dataType="collecte")
public class Collecte {

@Id
@GeneratedValue
//@Field(name="_id")
private String id;
....

I've tried with or without @Field annotation, same results.


The test :
EntityManagerFactory emf = Persistence
.createEntityManagerFactory("mongoPU");
EntityManager em = emf.createEntityManager();
Collecte c = em.find(Collecte.class, "517f9d50559a541e63011fe0");
//Query q = em.createQuery("select c from Collecte c where c.id =:id");
// Query q = em.createNativeQuery("db.collecte.findOne({\"_id\": ObjectId(" +"517f9d50559a541e63011fe0"+ ") \"})", Collecte.class);
//q.setParameter("id", "517f9d50559a541e63011fe0");
// Collecte c = (Collecte) q.getSingleResult();
assertThat(c.getEan()).isEqualTo("3251248033108");

None of the methods find(), createQuery, createNativeQuery() works.

The logs :
[EL Finest]: jpa: End deploying Persistence Unit mongoPU; session file:/home/david/git/servicescrowdsourcing/target/scala-2.10/classes/_mongoPU; state Deployed; factoryCount 1
[EL Finer]: connection: client acquired: 148643588
[EL Finer]: transaction: acquire unit of work: 1188706162
[EL Finest]: query: Execute query ReadObjectQuery(name="readObject" referenceClass=Collecte )
[EL Finest]: connection: Connection(1634151355)--Connection acquired from connection pool [default].
[EL Fine]: sql: Connection(1634151355)--Executing MappedInteraction()
spec => null
properties => {mongo.collection=collecte, mongo.operation=FIND}
input => [517f9d50559a541e63011fe0]
[EL Finest]: query: Adapter result: null
[EL Finest]: query: Data access result: null
[EL Finest]: connection: Connection(1634151355)--Connection released to connection pool [default].

The data have been inserted in MongoDB also with EclipseLink.

Any advice ?

Thanks,

David
Re: Problem mongodb query/find by id [message #1052720 is a reply to message #1052646] Tue, 30 April 2013 12:56 Go to previous messageGo to next message
James Sutherland is currently offline James SutherlandFriend
Messages: 1939
Registered: July 2009
Location: Ottawa, Canada
Senior Member

Is your insert now working, or not? Please include the log from your insert if it is not working.

So, both the insert and the find work when you do not set the dataType, but neither work when you do?


James : Wiki : Book : Blog : Twitter
Re: Problem mongodb query/find by id [message #1052803 is a reply to message #1052720] Tue, 30 April 2013 14:50 Go to previous messageGo to next message
David Courtin is currently offline David CourtinFriend
Messages: 4
Registered: April 2013
Junior Member
Yes insertion in database work find but I think find the cause :
1/ if you add the annotation @Field(name="_id"), the id java field is record as a capitalise string in the _id database field, not as an ObjectId.
2/ if you suppress this annotation, you hava two UUID record in the database, first in ID column and the UUID string is capitalise, and second UUID in _id column, not capitalized and it's type is ObjectId !

In first case, you can find the produit with the ID, but tools like MonjaDb and Genghis can't be used to maintain database.
In second case, you can find the product with the capitalize id, but record twice an UUID is strange...

Re: Problem mongodb query/find by id [message #1053070 is a reply to message #1052803] Thu, 02 May 2013 10:32 Go to previous messageGo to next message
David Courtin is currently offline David CourtinFriend
Messages: 4
Registered: April 2013
Junior Member
To finally have somethings that work as I except, I've used the Converter annotation like this :

@Entity
@NoSql(dataFormat=DataFormatType.MAPPED, dataType="personne")
public class Person {
	@Id
	@GeneratedValue
	@Field(name="_id")
	@Converter(name="convertisseurObjectId", converterClass=model.utils.ObjectIdConverter.class)
	@Convert("convertisseurObjectId")
	private String personId;

	@Column(name = "PERSON_NAME")
	private String personName;

and here is the converter class :
package model.utils;

import org.bson.types.ObjectId;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.mappings.converters.Converter;
import org.eclipse.persistence.sessions.Session;

/**
 * Converter of the ObjectId type, used by MongoDB
 * @author david
 *
 */
public class ObjectIdConverter implements Converter {

	@Override
	public Object convertObjectValueToDataValue(Object objectValue,
			Session session) {
		ObjectId objId;
		if (objectValue instanceof ObjectId)
			objId = (ObjectId)objectValue;
		else
			objId = new ObjectId((String)objectValue);
		return objId;
	}

	@Override
	public Object convertDataValueToObjectValue(Object dataValue,
			Session session) {
		ObjectId objId;
		if (dataValue instanceof ObjectId)
			objId = (ObjectId)dataValue;
		else
			objId = new ObjectId((byte[])dataValue);
		return objId.toString();
	}

	@Override
	public boolean isMutable() {
		// Yes 
		return false;
	}

	@Override
	public void initialize(DatabaseMapping mapping, Session session) {
		// Nothing to DO
	}

}


Usefull are not ?

David
Re: Problem mongodb query/find by id [message #1053771 is a reply to message #1053070] Tue, 07 May 2013 14:28 Go to previous message
James Sutherland is currently offline James SutherlandFriend
Messages: 1939
Registered: July 2009
Location: Ottawa, Canada
Senior Member

MongoDB requires an "_id" key field. If your data does not contain one, Mongo will generate one as an ObjectId.

The application is free to use whatever value it wants for "_id", it is odd your tools are requiring this to be an ObjectId.

In EclipseLink, you can use whatever type you want for the "_id", but this will be the value passed to Mongo. So if you map it as String, then it will be a String.
@GeneratedValue will initialize this field with a new ObjectId converted to your field's type (in your case String).

Your converter is probably the best way to ensure the type is an ObjectId in the database.

You might also be able to declare the type as ObjectId to avoid the String conversion. If this does not work, please log a bug to have ObjectId support corrected.


James : Wiki : Book : Blog : Twitter
Previous Topic:When will Eclipselink 2.4.2 be released?
Next Topic:Convert .NET DateTimeOffset <--> Jodatime DateTime (utc)
Goto Forum:
  


Current Time: Thu Nov 27 18:44:46 GMT 2014

Powered by FUDForum. Page generated in 0.03890 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software