Search code examples
sqlserviceliferayliferay-6builder

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


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


Solution

  • 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.