Issue with Casting / Joins

#1

Hi

I can't seem to find my way out of this. Basically what I have is something like:

@Embeddable
public class EmbeddedBase
{
...
}

@Embeddable
public class EmbeddedA extends EmbeddedBase
{
private String name;

getName()...
}

@Entity
public class MyEntity
{
private Map<String, EmbeddedBase> embeddeds = new ..;

getEmbeddeds()..
}

// Populate
MyEntity entity = new MyEntity();
entity.getEmbeddeds().put("test", new EmbeddedA);
...

// Try to query using join
From<MyEntity> from = criteria.from(MyEntity.class);
MapJoin<?,?,?> join = from.joinMap("embeddeds");
Path<?> pathToEmbeddedAName = join.value().get("name") <-- fails with attribute "name" not found

This somewhat makes sense because the underlying type of the join.value() here is "EmbeddedBase" and not "EmbeddedA". However, I do actually know and can make sure that the underlying type in my case is "EmbeddedA" (or any other descendant but I know the type for sure), so I'd need somelike join.value().castUnderylingJavaTypeTo(EmbeddedA.class)? Because odb correctly saves and retrieves the fields, I simply cannot access it using criteria api.. I can also not use metamodel because it is not available for me at that point.. so what am I doing wrong? I can't seem to figure any simple way out of here??

thanks so much

Alex

#2

You may try using a string based (JPQL) query instead of a criteria query for this purpose, since ObjectDB supports casting in a string based query (as an extension to JPQL).

ObjectDB Support
#3

Hi,

Actually I need to stick with the Criteria API as a lot of code is involved in building an exact query so I'd need an appropriate solution for this.. I cannot imagine that there's no standard JPA-Way of such a common (inheritance??) feature?

 

Alex

#4

This is an interesting question. Maybe if you ask on stackoverflow or on forums of other JPA implementations someone can suggest a standard JPA solution.

If there is no standard solution, maybe this can be solved by adding a new ObjectDB specific hint.

ObjectDB Support
#5

hi,

okay, asked on three different places without success.. can't u help me out here? I'd guess you should be a JPA Expert at least no ? ;-) I really need to get that fixed // working..

thanks

Alex

#6

Probably JPA doesn't support this level of polymorphism but since you wrote "I cannot imagine that there's no standard JPA-Way of such a common (inheritance??) feature?" - it made sense to check it with other experts.

But looking closer at your query reveals another problem. You are trying to define a variable for iteration over map values and currently this is not supported (issue #13). This is the same issue as this forum thread that you have started.

ObjectDB Support
#7

Hi,

Yes it doesn't seem that there's a solution in JPA for this however we have no other way of defining our Model (imagine i.e. a simple Order with Order Items which might be of different type etc.) so can you provide any idea / solution?

About the variable for iterating map values.. Yes I am aware that this isn't supported in JPQL though I was under the impression that it is supported within the Criteria API or isn't it?? Because it seems to work..??

Alex

#8

any idea?

#9

You should be able to solve this by using casting in a string based query (casting is a JDOQL feature that is available by ObjectDB also in JPQL queries).

If you prefer criteria queries:

  1. Build the query using the criteria API.
  2. Use toString to generate the equivalent JPQL from the criteria query.
  3. Fix the query string by wrapping the variable with casting (replace).
  4. Run the query as a JPQL query.

Regarding the map limitation, on a second thought this is probably not a problem since you iterate over the values and not over the keys.

ObjectDB Support
#10

hi,

Wow, sounds complicated but anyway.. :) Now if you can just tell me:

3. How to do this? I mean, how does such a cast look like and how do I know what the substitution looks like from the generated query?

Alex

#11

The following code demonstrates using casting in your case:

import java.util.*;

import javax.persistence.*;
import javax.persistence.criteria.*;


public final class T623 {

    public static void main(String[] args) {
        EntityManagerFactory emf =
            Persistence.createEntityManagerFactory(
                "objectdb:$objectdb/db/test.tmp;drop");
        EntityManager em = emf.createEntityManager();
       
        em.getTransaction().begin();
        MyEntity entity = new MyEntity();
        entity.embeddeds.put("test", new EmbeddedA());
        em.persist(entity);
        em.getTransaction().commit();

        String query =
            "SELECT ((EmbeddedA)e.embeddeds.get('test')).name FROM MyEntity e";
        List resultList = em.createQuery(query).getResultList();
        System.out.println(resultList);

        em.close();
        emf.close();
    }
   
    @Entity
    public static final class MyEntity {
        Map<String,EmbeddedBase> embeddeds  = new HashMap<String,EmbeddedBase>();
    }

    @Embeddable
    public static class EmbeddedBase {
    }

    @Embeddable
    public static class EmbeddedA extends EmbeddedBase {
        String name = "Alex";
    }  
}
ObjectDB Support
#12

hi,

Okay I think I've got the idea, however this

SELECT ((EmbeddedA)e.embeddeds.get('test')).name FROM MyEntity e

wouldn't work in our case because we always do a

SELECT FROM MyEntity e

to get a collection of MyEntity returned. Any idea? Or would it be something like

SELECT FROM MyEntity e LEFT JOIN e.embeddeds em WHERE ((EmbeddedA)em.get('test')).name = 'TEST'

Also, am I supposed to use the ClassName in (EmbeddedA) or the Entity Name? Furthermore, I need to use full qualified names of either class or entity name, will that work, i.e. (com.test.EmbeddedA) ?

Alex

#13

Your last query looks valid. Eventually, this is the Java syntax for casting.

You have to do the casting to EmbeddedA, since this is an EmbeddedA instance and you want to use a field that is defined in EmbeddedA.

Both fully qualified names and non qualified names should work, but please check it.

ObjectDB Support
#14

Hi,

Sorry to get it back, I know that it is an old post.

I am facing the same polymorphism/casting problem with Criteria API, I don't want to use JPQL strings,  and can't find any information in other forums.

Do you know if nowadays there is a way to do that in Criteria API?

Thanks!
Pablo.

#15

No news on this subject and apparently the old posts already cover this situation well. 

ObjectDB Support

Reply