0

How can I read list of @Embeddable objects from MongoDB with Hibernate OGM after aggregation.

I have entity like this

@javax.persistence.Entity
public class MySession implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Type(type = "objectid") 
    private String id;
    private Date start;
    private Date end;
    @ElementCollection
    private List<MySessionEvent> events;
}

and @Embeddable object

@javax.persistence.Embeddable
public class MySessionEvent implements Serializable {
    private Long time;
    private String name;
}

I stuck with mapping Embeddable objects from native query

String queryString = "db.MySession.aggregate([" +
            "   { '$match': { 'events.name': { '$regex': 'Abrakadabra'} }}, " +
            "   { '$unwind': '$events' }, " +
            "   { '$replaceRoot': { 'newRoot': '$events'}} " +
            "])";

List<MySessionEvent> objects = em.createNativeQuery(queryString, MySessionEvent.class).getResultList();

I get an error Caused by: org.hibernate.MappingException: Unknown entity

user3714967
  • 1,575
  • 3
  • 14
  • 29
  • ensure that you are using @javax.persistence.Entity instead of org.hibernate.annotations.Entity – Alien Nov 30 '18 at 11:47
  • I am using it. I will add in code examples above – user3714967 Nov 30 '18 at 13:17
  • It is hard to answer without the whole stack trace. Does it happen at start up? Than the problem can be that the entity is not registered correctly. If it happens after the query execution, it's probably because the result of the query does not return what Hibernate OGM expects for an entity. Any reason for not using an HQL instead? What kind of query are you trying to run? – Davide D'Alto Dec 01 '18 at 18:20
  • I mean, are you just trying to return the entities with the embedded collection? Because OGM will create the entities for you if you use HQL queries. – Davide D'Alto Dec 01 '18 at 18:22
  • No, problem happens when query is executed. I have already created some documents in DB at startup so I think everything is just configured right. So yes I supposed the return value is incorrect but I don't know what is missing. I want to return flat array of events from sessions. Can this be done with HQL? – user3714967 Dec 02 '18 at 09:33
  • I have data like this [ {id:'s1', events: [{name: 'one'},{name: 'two'}]}, {id:'s2', events: [{name: 'three'},{name: 'four'}]} ] and I want result like this [{name: 'one'},{name: 'two'},{name: 'three'},{name: 'four'}] – user3714967 Dec 02 '18 at 09:35
  • @Davide any suggestion? – user3714967 Dec 03 '18 at 20:11
  • Checking if there is a better solution, but at the moment I can only think of two options: return the result as a List without conversion or avoid the unwind and let OGM rebuild the entity, – Davide D'Alto Dec 04 '18 at 10:44
  • Sorry, I realized that I didn't understand your original question. I think I've answered now. – Davide D'Alto Dec 04 '18 at 11:32

2 Answers2

1

Copying your comment here because it adds some details:

I have data like this [ {id:'s1', events: [{name: 'one'},{name: 'two'}]}, {id:'s2', events: [{name: 'three'},{name: 'four'}]} ] and I want result like this [{name: 'one'},{name: 'two'},{name: 'three'},{name: 'four'}]

The query you are running returns the following type of results if I run it on MongoDB natively (I populated it with some random data):

{ "name" : "Event 3", "time" : NumberLong(3) }
{ "name" : "Abrakadabra", "time" : NumberLong(5) }

This is not enough to rebuild an entity and that's the reason you are seeing the exception.

Considering that you only want the list of events, this should work:

List<Object[]> poems = em.createNativeQuery( queryString ).getResultList();

Hibernate OGM will convert the previous result in a list of arrays. Each element of the List is an array where the firs value of the array is the name of the event and the second one is the time.

For supported cases like this I think HQL queries are better. You could rewrite the same example with the following:

    String queryString = 
            "SELECT e.name " +
            "FROM MySession s JOIN s.events e " +
            "WHERE e.name LIKE 'Abrakadabra'";
    List<Object[]> events = em.createQuery( queryString ).getResultList();

Note that I decided not to return the time because in your comment you didn't request it, but this will work as well:

    String queryString = 
            "SELECT e.time, e.name " +
            "FROM MySession s JOIN s.events e " +
            "WHERE e.name LIKE 'Abrakadabra'";
    List<Object[]> events = em.createQuery( queryString ).getResultList();
Davide D'Alto
  • 7,421
  • 2
  • 16
  • 30
-1

It is not recognizing the entity, make sure all your entities are in persistence.xml Embeddable objects too

<class>org.example.package.MySessionEvent</class>
Jose
  • 124
  • 9
  • If this were the problem it would see a different error. Something like `Entity not mapped exception`. Hibernate OGM does autodiscovery of the entities unless configured otherwise. – Davide D'Alto Dec 04 '18 at 11:34