How to fetch liferay entity through custom-finder in custom plugin portlet?
Asked Answered
D

1

7

How can we fetch liferay entities through custom-finder using custom SQL?

  1. Following is my sql query written in default.xml (I have trimmed down the query to the bare minimum so that the logic remains simple. Since it included a few functions and joins we couldn't use DynamicQuery API ):

    SELECT
        grp.*
    FROM
        Group_
    WHERE
        site = 1
        AND active_ = 1
        AND type_ <> 3
    
  2. Relevant code in MyCustomGroupFinderImpl.java:

    Session session = null;
    
    try {
        session = openSession();
    
        // fetches the query string from the default.xml
        String sql = CustomSQLUtil.get(FIND_ONLY_ACTIVE_SITES);
    
        SQLQuery sqlQuery = session.createSQLQuery(sql);
    
        sqlQuery.addEntity("Group_", GroupImpl.class);
        // sqlQuery.addEntity("Group_", PortalClassLoaderUtil.getClassLoader().loadClass("com.liferay.portal.model.impl.GroupImpl"));
    
        return (List<Group>) QueryUtil.list(sqlQuery, getDialect(), 0, QueryUtil.ALL_POS);
    }
    catch (Exception e) {
        throw new SystemException(e);
    }
    finally {
        closeSession(session);
    }
    

This above code won't work as the GroupImpl class is present in portal-impl.jar and this jar cannot be used in custom portlet.

I also tried using sqlQuery.addEntity("Group_", PortalClassLoaderUtil.getClassLoader().loadClass("com.liferay.portal.model.impl.GroupImpl"))
But this above code throws exception:

com.liferay.portal.kernel.exception.SystemException:
    com.liferay.portal.kernel.dao.orm.ORMException:
        org.hibernate.MappingException:
            Unknown entity: com.liferay.portal.model.impl.GroupImpl

But the same code works for our custom-entity, if we write sqlQuery.addEntity("MyCustomGroup", MyCustomGroupImpl.class);.

Thanks

Downswing answered 9/4, 2013 at 7:8 Comment(0)
D
8

I found out from the liferay forum thread that instead of session = openSession(); we would need to fetch the session from liferaySessionFactory as follows to make it work:

// fetch liferay's session factory
SessionFactory sessionFactory = (SessionFactory) PortalBeanLocatorUtil.locate("liferaySessionFactory");

Session session = null;

try {
    // open session using liferay's session factory
    session = sessionFactory.openSession();

    // fetches the query string from the default.xml
    String sql = CustomSQLUtil.get(FIND_ONLY_ACTIVE_SITES);

    SQLQuery sqlQuery = session.createSQLQuery(sql);

    // use portal class loader, since this is portal entity
    sqlQuery.addEntity("Group_", PortalClassLoaderUtil.getClassLoader().loadClass("com.liferay.portal.model.impl.GroupImpl"));

    return (List<Group>) QueryUtil.list(sqlQuery, getDialect(), 0, QueryUtil.ALL_POS);
}
catch (Exception e) {
    throw new SystemException(e);
}
finally {
    sessionFactory.closeSession(session); // edited as per the comment on this answer
    // closeSession(session);
}

Hope this helps somebody on stackoverflow, also I found a nice tutorial regarding custom-sql which also uses the same approach.

Downswing answered 9/4, 2013 at 7:8 Comment(2)
would that closeSession call on the finally block close that session? I looked at liferay's code and found it uses the sessionFactory of the finder to close the session hence my question.Conclave
@Conclave I think it should be sessionFactory.closeSession(session) in this case. Thanks for pointing that out.Downswing

© 2022 - 2024 — McMap. All rights reserved.