Re: How to run generic query for subclasses?

255 views
Skip to first unread message

Timo Westkämper

unread,
Jan 25, 2013, 2:21:29 PM1/25/13
to Querydsl on behalf of Strom L
Hi.

Some comments inline

On Fri, Jan 25, 2013 at 8:25 PM, Strom L via Querydsl <querydsl+noreply-APn2wQe4dy8r6EL...@googlegroups.com> wrote:
Hello, I have a JPA parent class that I use for all of my entities:

@MappedSuperclass
@Access(AccessType.FIELD)
public abstract class AbstractEntity<T> {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Column(nullable = false)
    private Boolean isDeleted;

Maybe deleted would be better as a field name, otherwise you have weird getters like isIsDeleted or getIsDeleted.
 
    ...
}

I am also making an AbstractDao which will have fetchById() and fetchAll() operations. All other operations specific to the child classes will be in their specific DAO class. How would you go about specifying the queries? This is what I have so far.

public abstract class AbstractDao<T extends AbstractEntity<T>> {
    @PersistenceContext
    private EntityManager entityManager;

    public T fetchById(Long id, boolean isDeletedEntitiesIncluded) {
        QAbstractEntity entity = QAbstractEntity.abstractEntity;
        JPAQuery query = new JPAQuery(getEntityManager());
        BooleanExpression whereClause = entity.id.eq(id);

Directly populate the query
 
    query.where(entity.id.eq(id));
        
 
        // Determine if we should filter out logically deleted entities.
        if (!isDeletedEntitiesIncluded) {
            whereClause = whereClause.and(entity.isDeleted.eq(false));

query.where(entity.deleted.eq(false));
 
        }
        // What do I return here?

return query.singleResult(entity);
 
    }

    public List<T> fetchAll(boolean isDeletedEntitiesIncluded) {
        QAbstractEntity entity = QAbstractEntity.abstractEntity;
        JPAQuery query = new JPAQuery(getEntityManager());
        query = query.from(entity);
        // Determine if we should filter out logically deleted entities.
        if (!isDeletedEntitiesIncluded) {
            query = query.where(entity.isDeleted.eq(false));

No need to reassign
 
        }
        // Run the query
        // What to return here?

return query.list(entity);
 
    }
}

Thanks!

--
 
 



--
Timo Westkämper
Mysema Oy
+358 (0)40 591 2172
www.mysema.com


Strom L

unread,
Jan 25, 2013, 2:33:42 PM1/25/13
to quer...@googlegroups.com
Thanks Timo,

I'll try it out. What do I do about the return value casting though? If I return the abstract entity, I'd have to cast the return value. If I return the abstract class, I'll have to cast it further down the hierarchy.

(T) query.singleResult(entity);


On Friday, January 25, 2013 10:25:16 AM UTC-8, Strom L wrote:
Hello, I have a JPA parent class that I use for all of my entities:

@MappedSuperclass
@Access(AccessType.FIELD)
public abstract class AbstractEntity<T> {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Column(nullable = false)
    private Boolean isDeleted;
    ...
}

I am also making an AbstractDao which will have fetchById() and fetchAll() operations. All other operations specific to the child classes will be in their specific DAO class. How would you go about specifying the queries? This is what I have so far.

public abstract class AbstractDao<T extends AbstractEntity<T>> {
    @PersistenceContext
    private EntityManager entityManager;

    public T fetchById(Long id, boolean isDeletedEntitiesIncluded) {
        QAbstractEntity entity = QAbstractEntity.abstractEntity;
        JPAQuery query = new JPAQuery(getEntityManager());
        BooleanExpression whereClause = entity.id.eq(id);
        // Determine if we should filter out logically deleted entities.
        if (!isDeletedEntitiesIncluded) {
            whereClause = whereClause.and(entity.isDeleted.eq(false));
        }
        // What do I return here?
    }

    public List<T> fetchAll(boolean isDeletedEntitiesIncluded) {
        QAbstractEntity entity = QAbstractEntity.abstractEntity;
        JPAQuery query = new JPAQuery(getEntityManager());
        query = query.from(entity);
        // Determine if we should filter out logically deleted entities.
        if (!isDeletedEntitiesIncluded) {
            query = query.where(entity.isDeleted.eq(false));
        }
        // Run the query
        // What to return here?
    }
}

Thanks!

Strom L

unread,
Jan 25, 2013, 3:07:29 PM1/25/13
to quer...@googlegroups.com
Thanks Timo,

I think I replied to myself previously on the message thread...oops. So, I tried it with just casting, and it crashed on me. Here are my methods.

public T fetchById(Long id, boolean isDeletedFetched) {
        QAbstractEntity entity = QAbstractEntity.abstractEntity;
        JPAQuery query = new JPAQuery(getEntityManager());
        query.from(entity);
        query.where(entity.id.eq(id));
        // Determine if we should filter out logically deleted entities.
        if (!isDeletedFetched) {
            query.where(entity.deleted.eq(false));
        }
        // Run the query
        T fetchedEntity = (T) query.uniqueResult(entity);

        return fetchedEntity;
    }

    public List<T> fetchAll(boolean isDeletedFetched) {
        QAbstractEntity entity = QAbstractEntity.abstractEntity;
        JPAQuery query = new JPAQuery(getEntityManager());
        query.from(entity);
        // Determine if we should filter out logically deleted entities.
        if (!isDeletedFetched) {
            query.where(entity.deleted.eq(false));
        }
        // Run the query
        return (List<T>) query.list(entity);
    }

Here's my stacktrace:
java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: AbstractEntity is not mapped [select abstractEntity
from AbstractEntity abstractEntity
where abstractEntity.id = ?1 and abstractEntity.deleted = ?2]
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1364)
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1300)
at org.hibernate.ejb.AbstractEntityManagerImpl.createQuery(AbstractEntityManagerImpl.java:294)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
        ...

Seems like casting the return result won't work, so where should I go from here? The from table should really be the concrete class, and I thought to use "entity.as(getConcreteEntityPath())", but I'm running into weird generics issues with Querydsl and it looked a bit hairy.

Strom


On Friday, January 25, 2013 11:21:29 AM UTC-8, Timo Westkämper wrote:
Hi.

Some comments inline

Timo Westkämper

unread,
Jan 25, 2013, 4:06:19 PM1/25/13
to Querydsl on behalf of Strom L
Hi.


On Fri, Jan 25, 2013 at 10:07 PM, Strom L via Querydsl <querydsl+noreply-APn2wQe4dy8r6EL...@googlegroups.com> wrote:
Thanks Timo,

I think I replied to myself previously on the message thread...oops. So, I tried it with just casting, and it crashed on me. Here are my methods.

public T fetchById(Long id, boolean isDeletedFetched) {
        QAbstractEntity entity = QAbstractEntity.abstractEntity;

You need to use one of the QAbstractEntity constructors here and supply the real entity class you are going to use.

 

Strom L

unread,
Jan 25, 2013, 6:29:06 PM1/25/13
to quer...@googlegroups.com
Thanks, that did the trick!


On Friday, January 25, 2013 1:06:19 PM UTC-8, Timo Westkämper wrote:
Hi.
Reply all
Reply to author
Forward
0 new messages