Message Boards

Liferay 7.2 - How to dynamicQuery with expandoBridge?

Fabio Carvalho, modified 4 Years ago.

Liferay 7.2 - How to dynamicQuery with expandoBridge?

Junior Member Posts: 81 Join Date: 6/25/19 Recent Posts
Hi,
I have set a custom field to my JournalArticle. Now, I want to query my JournalArticles based on this custom field. I am doing something like this:
DynamicQuery expandoTableDynamicQuery = DynamicQueryFactoryUtil.forClass(ExpandoTable.class, ExpandoTable.class.getClassLoader());
expandoTableDynamicQuery.add(PropertyFactoryUtil.forName("name").eq(ExpandoTableConstants.DEFAULT_TABLE_NAME));
expandoTableDynamicQuery.setProjection(ProjectionFactoryUtil.property("tableId"));
        
DynamicQuery expandoColumnDynamicQuery = DynamicQueryFactoryUtil.forClass(ExpandoColumn.class, ExpandoColumn.class.getClassLoader());
expandoColumnDynamicQuery.add(PropertyFactoryUtil.forName("tableId").in(expandoTableDynamicQuery));
expandoColumnDynamicQuery.add(PropertyFactoryUtil.forName("name").eq("contentDate"));
expandoColumnDynamicQuery.setProjection(ProjectionFactoryUtil.property("columnId"));
        
DynamicQuery expandoValueDynamicQuery = DynamicQueryFactoryUtil.forClass(ExpandoValue.class, ExpandoValue.class.getClassLoader());
expandoValueDynamicQuery.add(PropertyFactoryUtil.forName("columnId").in(expandoColumnDynamicQuery));
expandoValueDynamicQuery.add(PropertyFactoryUtil.forName("data").gt(getFilterDate(pageDate)));
expandoValueDynamicQuery.setProjection(ProjectionFactoryUtil.property("classPK"));
        
DynamicQuery articleDynamicQuery = JournalArticleLocalServiceUtil.dynamicQuery();
articleDynamicQuery.add(PropertyFactoryUtil.forName("id").in(expandoValueDynamicQuery));
​​​​​​​
List<journalarticle> articles = JournalArticleLocalServiceUtil.dynamicQuery(articleDynamicQuery);</journalarticle>

But when I add the following line, I crash the query:
articleDynamicQuery.add(PropertyFactoryUtil.forName("id").in(expandoValueDynamicQuery));

org.hibernate.MappingException: Unknown entity: com.liferay.portlet.expando.model.impl.ExpandoValueImpl
&nbsp;&nbsp; &nbsp;at org.hibernate.impl.SessionFactoryImpl.getEntityPersister(SessionFactoryImpl.java:693)
&nbsp;&nbsp; &nbsp;at org.hibernate.criterion.SubqueryExpression.toSqlString(SubqueryExpression.java:66)
&nbsp;&nbsp; &nbsp;at org.hibernate.loader.criteria.CriteriaQueryTranslator.getWhereCondition(CriteriaQueryTranslator.java:380)
&nbsp;&nbsp; &nbsp;at org.hibernate.loader.criteria.CriteriaJoinWalker.<init>(CriteriaJoinWalker.java:113)
&nbsp;&nbsp; &nbsp;at org.hibernate.loader.criteria.CriteriaJoinWalker.<init>(CriteriaJoinWalker.java:82)
&nbsp;&nbsp; &nbsp;at org.hibernate.loader.criteria.CriteriaLoader.<init>(CriteriaLoader.java:92)
&nbsp;&nbsp; &nbsp;at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1697)
&nbsp;&nbsp; &nbsp;at org.hibernate.impl.CriteriaImpl.list(CriteriaImpl.java:347)
&nbsp;&nbsp; &nbsp;at com.liferay.portal.dao.orm.hibernate.DynamicQueryImpl.list(DynamicQueryImpl.java:140)
&nbsp;&nbsp; &nbsp;at com.liferay.portal.dao.orm.hibernate.DynamicQueryImpl.list(DynamicQueryImpl.java:126)
&nbsp;&nbsp; &nbsp;at com.liferay.portal.kernel.service.persistence.impl.BasePersistenceImpl.findWithDynamicQuery(BasePersistenceImpl.java:328)
&nbsp;&nbsp; &nbsp;at com.liferay.journal.service.base.JournalArticleLocalServiceBaseImpl.dynamicQuery(JournalArticleLocalServiceBaseImpl.java:162)
&nbsp;&nbsp; &nbsp;at com.liferay.portal.kernel.bean.ClassLoaderBeanHandler.invoke(ClassLoaderBeanHandler.java:66)
&nbsp;&nbsp; &nbsp;at com.liferay.journal.service.JournalArticleLocalServiceWrapper.dynamicQuery(JournalArticleLocalServiceWrapper.java:781)
&nbsp;&nbsp; &nbsp;at com.liferay.portal.kernel.bean.ClassLoaderBeanHandler.invoke(ClassLoaderBeanHandler.java:66)
&nbsp;&nbsp; &nbsp;at com.liferay.portal.spring.aop.AopMethodInvocationImpl.proceed(AopMethodInvocationImpl.java:50)
&nbsp;&nbsp; &nbsp;at com.liferay.portal.spring.transaction.TransactionInterceptor.lambda$invoke$0(TransactionInterceptor.java:64)
&nbsp;&nbsp; &nbsp;at com.liferay.portal.spring.transaction.DefaultTransactionExecutor._execute(DefaultTransactionExecutor.java:128)
&nbsp;&nbsp; &nbsp;at com.liferay.portal.spring.transaction.DefaultTransactionExecutor.execute(DefaultTransactionExecutor.java:51)
&nbsp;&nbsp; &nbsp;at com.liferay.portal.spring.transaction.TransactionInterceptor.invoke(TransactionInterceptor.java:62)</init></init></init>

Am I doing something wrong? What would be the correct way to do this?
thumbnail
Mohammed Yasin, modified 4 Years ago.

RE: Liferay 7.2 - How to dynamicQuery with expandoBridge?

Liferay Master Posts: 591 Join Date: 8/8/14 Recent Posts
Hi,
Try using ExpandoValueLocalServiceUtil.dynamicQuery() or expandoValueLocalService.dynamicQuery()   Instead of DynamicQueryFactoryUtil
DynamicQuery expandoValueDynamicQuery =&nbsp;&nbsp;ExpandoValueLocalServiceUtil.dynamicQuery() ;
In the same way you can change for ExpandoColumn and ExpandoTable
Fabio Carvalho, modified 4 Years ago.

RE: Liferay 7.2 - How to dynamicQuery with expandoBridge?

Junior Member Posts: 81 Join Date: 6/25/19 Recent Posts
Hi Mohammed,

I have tried that. It isn't working either. Same error.
Julien Feyen, modified 4 Years ago.

RE: Liferay 7.2 - How to dynamicQuery with expandoBridge?

New Member Posts: 2 Join Date: 1/31/20 Recent Posts
Hi Fabio,

I was experiencing the same problem, running from your example provided but for another purpose. You first need to query the ExpandoValues in order to locate the Journal Articles' primary keys. You then pass in this list of keys to the final query to get your desired results.

In order to get your example working, try the following:

DynamicQuery expandoTableDynamicQuery = DynamicQueryFactoryUtil.forClass(ExpandoTable.class, ExpandoTable.class.getClassLoader());
expandoTableDynamicQuery.add(PropertyFactoryUtil.forName("name").eq(ExpandoTableConstants.DEFAULT_TABLE_NAME));
expandoTableDynamicQuery.setProjection(ProjectionFactoryUtil.property("tableId"));

DynamicQuery expandoColumnDynamicQuery = DynamicQueryFactoryUtil.forClass(ExpandoColumn.class, ExpandoColumn.class.getClassLoader());
expandoColumnDynamicQuery.add(PropertyFactoryUtil.forName("tableId").in(expandoTableDynamicQuery));
expandoColumnDynamicQuery.add(PropertyFactoryUtil.forName("name").eq("contentDate"));
expandoColumnDynamicQuery.setProjection(ProjectionFactoryUtil.property("columnId"));

DynamicQuery expandoValueDynamicQuery = DynamicQueryFactoryUtil.forClass(ExpandoValue.class, ExpandoValue.class.getClassLoader());
expandoValueDynamicQuery.add(PropertyFactoryUtil.forName("columnId").in(expandoColumnDynamicQuery));
expandoValueDynamicQuery.add(PropertyFactoryUtil.forName("data").gt(getFilterDate(pageDate)));
expandoValueDynamicQuery.setProjection(ProjectionFactoryUtil.property("classPK"));
List<long> expandoValueDynamicQueryValues = ExpandoValueLocalServiceUtil.dynamicQuery(expandoValueDynamicQuery);

DynamicQuery articleDynamicQuery = JournalArticleLocalServiceUtil.dynamicQuery();
articleDynamicQuery.add(PropertyFactoryUtil.forName("id").in(expandoValueDynamicQueryValues));

List<journalarticle> articles = JournalArticleLocalServiceUtil.dynamicQuery(articleDynamicQuery);</journalarticle></long>
thumbnail
David H Nebinger, modified 4 Years ago.

RE: Liferay 7.2 - How to dynamicQuery with expandoBridge?

Liferay Legend Posts: 14915 Join Date: 9/2/06 Recent Posts
A couple of things...

First, Mohammed is right in that you shouldn't use DynamicQueryFactoryUtil.forClass(). It is often to get the classloaders right.

Second, Julien has the answer but doesn't explain it, but it comes down to class loader again. You're trying to use the class loader from the journal article bundle and pass in a DQ instance built from a different class loader (the ExpandoValue's loader).

So you're trying to effectively do this across a bunch of different class loaders and, of course, one doesn't know about the other so you get the unknown entity exception.

Julien's solution works because he's getting the list of values and passes that list to the journal article's DQ, effectively removing the need to have some kind of mixed class loader.
Julien Feyen, modified 4 Years ago.

RE: Liferay 7.2 - How to dynamicQuery with expandoBridge?

New Member Posts: 2 Join Date: 1/31/20 Recent Posts
Thanks for your reply and for explaining why we are getting the 'Unknown entity' mapping exception for the ExpandoValue.
I am new to the OSGi world much like many that are upgrading from Liferay 6.2, so please correct me if I am wrong. From my experience, the example provided by Fabio would have originally worked in 6.2, correct? It's simply because of the class loaders required in the OSGi realm to make the associated connections.
David, do you have an example as to how we may be able to get a mixed class loader to work so that we could pass one DQ to the other effectively creating a join which would have the potential of being better for performance especially when dealing with large data sets and further filtering articles?
thumbnail
David H Nebinger, modified 4 Years ago.

RE: Liferay 7.2 - How to dynamicQuery with expandoBridge?

Liferay Legend Posts: 14915 Join Date: 9/2/06 Recent Posts
Mixed class loaders is not going to work. After all, they are mixed class loaders...

I wouldn't be trying to solve this kind of thing with DQ as things get either prohibitively hard or impossible.

For something like this I'd be using a custom SQL statement to handle the table joins and get results, followed by a normal entity retrieve to get the entities.