Wednesday, June 4, 2014

Liferay Service Builder Finder Methods

Introduction:

Liferay Service Builder finder methods are use to fetch the data based on columns.

Liferay Service Builder will generate finder methods simply by configure the finder tag in service.xml file.

We have finder tag so that we can configure the columns on which base we need to fetch the data from the table.

Go through the following articles before continue.



We need to defined finder tag in service.xml file and this tag should be enclosed by entity tag.

Example:


<entity name="Student" local-service="true" remote-service="true">
<!-- PK fields -->
<column name="studentId" type="long" primary="true" />
<column name="firstName" type="String" />
<column name="lastName" type="String" />
<column name="studentAge" type="int" />
<column name="studentGender" type="int" />
<column name="studentAddress" type="String" />
<!-- Finder methods -->
<finder name="Gender" return-type="Collection">
<finder-column name="studentGender"/>
</finder>
</entity>


Inside finder tag we need defined columns names so that SQL query will fetch the data based on defined columns.

Example Finder


<finder name="Gender" return-type="Collection">
<finder-column name="studentGender"/>
</finder>

Respective SQL Query

Select * from Student where studentGender=?


Finder on multiple Columns


<finder name="Gender_Age" return-type="Collection">
<finder-column name="studentGender"/>
<finder-column name="studentAge"/>
</finder>

Respective SQL Query

Select * from Student where studentGender=? AND student Age=?


Here all columns will be in Where clause and here AND operator will be applies if the columns are more than one.

Finder Tag and Its Attributes:


<finder
       name CDATA #REQUIRED
       return-type CDATA #REQUIRED
       unique CDATA #IMPLIED
       where CDATA #IMPLIED
       db-index CDATA #IMPLIED
> 

 name:

Name attribute specify the name of the attribute and after run the service builder respective service method will be created in XXXUtil.java class and the methods use this attribute.

Method Syntax in XXXUtil.java

findBy[finder Name Attribute Value](--)

Example:


<finder name="Gender">
<finder-column name="studentGender"/>
</finder>

 public List findByGender(----){

 }


return-type:

This attribute specify the data which is return by the finder method.
It may be Collection or Entity Model Object

If the finder returns more objects then it will be collection and in java method return type is java.util.List

If the finder is return only one value that is Entity object Model Type.

Example:

Collection:


<finder name="Gender_Age" return-type="Collection">
</finder>

 public List findByGender_Age(--){
}


Single Object


<finder name="StudentId" return-type="Student">
<finder-column name="studentId"/>
</finder>

 public Student findByStudentId(--){
}


unique:

If the unique value is true, then the finder must return a unique entity and that is Entity mode object type.

Example


<finder name="StudentId" return-type="Student" unique="true">
<finder-column name="studentId"/>
</finder>

 public Student findByStudentId(--){
}


where:

If any constant or static condition you want use in where clause then we have to use where attribute

Example:

Assume in the student data we don’t want consider the male gender. This is our specific condition.


<finder name="femaleStudents" return-type="Collection" where="studentGender!=1">
<finder-column name="studentAge"/>
</finder>


In the above scenario it won’t consider male gender.

We can use all operators in where attribute bases on data type (=, !=, <, <=, >, >=, or LIKE)

 db-index:

If the db-index value is true, then the service will automatically generate a
SQL index for this finder. The default value is true.

finder-column Tag

Finder column should be placed within finder tag and it will specify the on which column base the data should be fetched.

Example:


<finder name="Gender" return-type="Collection">
<finder-column name="studentGender"/>
</finder>

public List findByGender_Age(int studentGender){
}



These finder column is become method parameter in XXXUtil.java for respective finder method.

Finder Colum Attributes:

<!ATTLIST finder-column
       name CDATA #REQUIRED
       case-sensitive CDATA #IMPLIED
       comparator CDATA #IMPLIED
       arrayable-operator CDATA #IMPLIED
> 

name:

Name specifies the column name for entity. Name should match the any one of the available columns in entity. This name will be used in method parameter name in the java method.

 case-sensitive:

The attribute case-sensitive is a Boolean value and is only used if the column is a String value

comparator

The attribute comparator takes in the values =, !=, <, <=, >, >=, or LIKE and is used to compare this column.


<finder name="firstName" return-type="Collection">
<finder-column name="firstName" comparator="LIKE"/>
</finder>


In the above it will use like operator when it find the records based on first name.


Greater Than

<finder name="majorStudent" return-type="Collection">
<finder-column name="studentAge" comparator="&gt;"/>
</finder>

Less Than

<finder name="minorStudent" return-type="Collection">
<finder-column name="studentAge" comparator="&lt;"/>
</finder>


arrayable-operator

The attribute arrayable-operator takes in the values AND or OR and will generate an additional finder where this column's parameter takes an array instead of a single value. Every value in this array will be compared with the column using the comparator, and the conditions will be combined with either an AND or OR operator.

Example:

A finder column with the = comparator and an arrayable-operator of OR will act like an IN clause


<finder name="Age" return-type="Collection">
<finder-column name="studentAge" arrayable-operator="OR" />
</finder>

Respective Java Method

public findByAge(int[] studentAges){

}

Select * from Student where studentAge=value1 OR  studentAge=value2


The complete Example Snippet


<entity name="Student" local-service="true" remote-service="true">
<!-- PK fields -->
<column name="studentId" type="long" primary="true" />
<column name="firstName" type="String" />
<column name="lastName" type="String" />
<column name="studentAge" type="int" />
<column name="studentGender" type="int" />
<column name="studentAddress" type="String" />
<!-- Order -->
<order by="asc">
<order-column name="studentId" />
</order>
<!-- Finder methods -->
<finder name="Gender" return-type="Collection">
<finder-column name="studentGender"/>
</finder>
<!-- Finder methods -->
<finder name="Gender_Age" return-type="Collection">
<finder-column name="studentGender"/>
<finder-column name="studentAge"/>
</finder>
<finder name="byStudentId" return-type="Student" unique="true" db-index="true">
<finder-column name="studentId"/>
</finder>
<finder name="femaleStudents" return-type="Collection" where="studentGender!=1">
<finder-column name="studentAge"/>
</finder>
<finder name="firstNameLike" return-type="Collection">
<finder-column name="firstName" comparator="LIKE"/>
</finder>
<finder name="majorStudentGreaterThan" return-type="Collection">
<finder-column name="studentAge" comparator="&gt;"/>
</finder>
<finder name="minorStudentLessThan" return-type="Collection">
<finder-column name="studentAge" comparator="&lt;"/>
</finder>
<finder name="multipleAge" return-type="Collection">
<finder-column name="studentAge" arrayable-operator="OR" comparator="="/>
</finder>
</entity>


Return Uniqu Object


<finder name="byStudentId" return-type="Student" unique="true" db-index="true">
<finder-column name="studentId"/>
</finder>


public static com.meera.dbservice.model.Student findBybyStudentId(
long studentId)
throws com.liferay.portal.kernel.exception.SystemException,
com.meera.dbservice.NoSuchStudentException {
return getPersistence().findBybyStudentId(studentId);
}


Using Where Attribute

<finder name="femaleStudents" return-type="Collection" where="studentGender!=1">
<finder-column name="studentAge"/>
</finder>

public static java.util.List<com.meera.dbservice.model.Student> findByfemaleStudents(
int studentAge)
throws com.liferay.portal.kernel.exception.SystemException {
return getPersistence().findByfemaleStudents(studentAge);
}

Like Operator


<finder name="firstNameLike" return-type="Collection">
<finder-column name="firstName" comparator="LIKE"/>
</finder>

public static java.util.List<com.meera.dbservice.model.Student> findByfirstNameLike(
java.lang.String firstName)
throws com.liferay.portal.kernel.exception.SystemException {
return getPersistence().findByfirstNameLike(firstName);
}


Arrayble Operator


<finder name="multipleAge" return-type="Collection">
<finder-column name="studentAge" arrayable-operator="OR" comparator="="/>
</finder>

public static java.util.List<com.meera.dbservice.model.Student> findBymulipleAges(
int[] studentAges)
throws com.liferay.portal.kernel.exception.SystemException {
return getPersistence().findBymulipleAges(studentAges);
}


Note:

All the finder methods will be created in XXXUtil.jav (StudentUtil.java)  apart from these methods there are many similar methods will be created and which will be useful in pagination

Finder on Multiple Columns

If we want find the records based on multiple columns


<finder name="Gender_Age" return-type="Collection">
<finder-column name="studentGender"/>
<finder-column name="studentAge"/>
</finder>


For above Configuration respective SQL query as follows


Select * from LS_Student Where studentGender=? AND StudentAge=?


For Above Finder Configuration respective Java Method in XXXUtil(StudentUtil) as follows


public class StudentUtil{

public static java.util.List<com.meera.dbservice.model.Student>
findByGender_Age(int studentGender, int studentAge)
throws com.liferay.portal.kernel.exception.SystemException {
return getPersistence().findByGender_Age(studentGender,
studentAge);
}
}

Note:

When we use finder on multiple columns it will apply the AND operator in SQL query.

When we call XXXUtil methods in JSP or Portlet action class then we will get Exception

Example:


java.util.List<com.meera.dbservice.model.Student>  studentsList=
StudentUtil. findByGender_Age(1,20)


When we use above code in anywhere then we will get Hibernate Exception


org.hibernate.HibernateException: No Hibernate Session bound to thread


Solution:

We need to use these methods in XXXLocalServiceImpl then we will call these methods using XXXLocalServiceUtil

Liferay Service Builder finder Implementation

Steps:
  1. Define finder tag and finder columns in Entity Tag
  2. Run service Builder
  3. Implement Custom method in XXXLocalServiceImpl class
  4. Run service Builder
  5. Call Implemented method using XXXLocalServiceUtil

Define finder tag and finder columns in Entity Tag

We need to define the finder tag and finder columns with appropriate attributes that we desired and these tags should be available within entity tag. We already know all this configuration should be defined in service.xml file.

Example:


<entity name="Student" local-service="true" remote-service="true">
<!-- PK fields -->
<column name="studentId" type="long" primary="true" />
<column name="firstName" type="String" />
<column name="lastName" type="String" />
<column name="studentAge" type="int" />
<column name="studentGender" type="int" />
<column name="studentAddress" type="String" />
<!-- Finder methods -->
<finder name="Gender_Age" return-type="Collection">
<finder-column name="studentGender"/>
<finder-column name="studentAge"/>
</finder>
</entity>


Run service Builder

Once we define the finder tag and its column we need to run service builder then all finder java methods will be create in respective entity XXXUtil java class.

Implement Custom method in XXXLocalServiceImpl class

Whenever we get the requirement to write our custom methods then we need to implement in respective entity local service implementation class


XXXLocalServiceImpl

StudentLocalServiceImpl


Assume scenario we are not able to call finder methods form StudentUtil so we will implement custom method in StudentLocalServiceImpl.java


public  java.util.List<com.meera.dbservice.model.Student>
 findByGenderAndAge(int studentGender, int studentAge)

throws com.liferay.portal.kernel.exception.SystemException {

return StudentUtil.findByGender_Age(studentGender, studentAge);

}


Here we have implemented our custom method in XXXLocalServiceImpl (StudentLocalServiceImpl.java) and inside the custom method we have used XXXUtil methods.

Like this we can use XXXServiceUtil and XXXUtil methods in XXXLolcalServiceImpl custom method implementation.

Note:

XXXLocalServiceImpl class available in basepackage.service.impl path

Run service Builder

Once we implement the custom method in XXXServiceImpl then we need to run service builder using ant build-service target from ant view in eclipse.

After run service builder respective method signature will be created in XXXLocalServiceUtil class.

Note:

For every change in XXXLocalServiceImpl class we need re run the service builder.
Call Implemented method using XXXLocalServiceUtil

Now the method is available in XXXLocalSeriviceUtil class so that we can call method anywhere.

Example:

Method in StudentUtil.java

public class StudentUtil{

public static java.util.List<com.meera.dbservice.model.Student>
 findByGender_Age(
int studentGender, int studentAge)
throws com.liferay.portal.kernel.exception.SystemException {
return getPersistence().findByGender_Age(studentGender,
 studentAge);
}
}


Note:

We can’t call above method directly

Implement the Custom method in StudentLocalServiceImpl.java


public class StudentLocalServiceImpl extends
StudentLocalServiceBaseImpl {
public  java.util.List<com.meera.dbservice.model.Student>
 findByGenderAndAge(
int studentGender, int studentAge)
throws com.liferay.portal.kernel.exception.SystemException {
return StudentUtil.findByGender_Age(studentGender, studentAge);
}
}

Respective method Signature in StudentLocalServieUtil.java


public static java.util.List<com.meera.dbservice.model.Student>
findByGenderAndAge(
int studentGender, int studentAge)
throws com.liferay.portal.kernel.exception.SystemException {
return getService().findByGenderAndAge(studentGender, studentAge);
}


Note:

Method signature available after run the service builder

Using custom method in JSP page or Portlet Action Class


java.util.List<Student>  studentsList=
StudentLocalServiceUtil. findByGenderAndAge(1,20)



Complete code for Example

Cutome Method Implemetation(StudentLocalServiceImpl.java)


public class StudentLocalServiceImpl extends StudentLocalServiceBaseImpl {

public java.util.List<com.meera.dbservice.model.Student> findByGenderAndAge(
int studentGender, int studentAge)
throws com.liferay.portal.kernel.exception.SystemException {
return StudentUtil.findByGender_Age(studentGender, studentAge);
}

public java.util.List<com.meera.dbservice.model.Student> usingArrableOperatorOnFindeCoumn(
int[] studentAges)
throws com.liferay.portal.kernel.exception.SystemException {
return StudentUtil.findBymulipleAges(studentAges);
}

public com.meera.dbservice.model.Student usingUniqueAttributeforFindertag(
long studentId)
throws com.liferay.portal.kernel.exception.SystemException,
com.meera.dbservice.NoSuchStudentException {
return StudentUtil.findBybyStudentId(studentId);
}

public java.util.List<com.meera.dbservice.model.Student> usingWhereAttrobuteInFinderTag(
int studentAge)
throws com.liferay.portal.kernel.exception.SystemException {
return StudentUtil.findByfemaleStudents(studentAge);
}

public java.util.List<com.meera.dbservice.model.Student> usingLikeOperatorOnFinderColumn(
java.lang.String firstName)
throws com.liferay.portal.kernel.exception.SystemException {
return StudentUtil.findByfirstNameLike(firstName);
}

public java.util.List<com.meera.dbservice.model.Student> usingGreaterThanOnFinderCoulumn(
int studentAge)
throws com.liferay.portal.kernel.exception.SystemException {
return StudentUtil.findBymajorStudentGreaterThan(studentAge);
}

public java.util.List<com.meera.dbservice.model.Student> usingLessThanOnFinderCoulumn(
int studentAge)
throws com.liferay.portal.kernel.exception.SystemException {
return StudentUtil.findByminorStudentLessThan(studentAge);
}
}

Calling method in JSP page (/html/jsps/finder_methods_usage.jsp)


<%@page import="com.liferay.portal.kernel.util.ListUtil"%>
<%@page import="com.meera.dbservice.model.Student"%>
<%@page import="java.util.List"%>
<%@page import=
"com.meera.dbservice.service.StudentLocalServiceUtil"%>
<%@ include file="init.jsp"%>
<a href="<portlet:renderURL />">&laquo;Home</a>
<div class="separator"></div>

<h2>The following method return only one Student Object
</h2><br/>
<b>StudentLocalServiceUtil.usingUniqueAttributeforFindertag(1)</b><br/>

<h2>The following method is example for
 Arrayble Operator and method take array of values</h2><br/><br/>
<%
int[] ageArray = {29,34,23};
%>
<b>int[] ageArray = {29,34,23};</b><br/>
<b>StudentLocalServiceUtil.usingArrableOperatorOnFindeCoumn(ageArray)</b><br/>
<%="Number studenr"+StudentLocalServiceUtil.usingArrableOperatorOnFindeCoumn(ageArray) +"<br/>"%><br/>
<h2>The following method is example for Like  Operator</h2><br/><br/>
<b>StudentLocalServiceUtil.usingLikeOperatorOnFinderColumn("meera")</b><br/>
<%="Number of Students using Like Operator:"+StudentLocalServiceUtil.
usingLikeOperatorOnFinderColumn("meera")+"<br/>"%>
<h2>The following method is example for Greater then Operator</h2><br/>
<b>StudentLocalServiceUtil.usingGreaterThanOnFinderCoulumn(23)</b><br/>
<%="Number of Students greater then Age 23:"+StudentLocalServiceUtil.
usingGreaterThanOnFinderCoulumn(23)+"<br/>"%><br/>

<h2>The following method is example for Less then Operator</h2><br/>
<b>StudentLocalServiceUtil.usingLessThanOnFinderCoulumn(30)</b><br/>
<%="Number of Students Less then Age 23:"+StudentLocalServiceUtil.usingLessThanOnFinderCoulumn(30)+"<br/>"%>
<h2>The following method is example for
using Where attribute in Finder tag and it always fetch Female Students</h2><br/><br/>
<b>StudentLocalServiceUtil.usingWhereAttrobuteInFinderTag(27)</b><br/>
<%="Number of Female:"+StudentLocalServiceUtil.usingWhereAttrobuteInFinderTag(27)+
"<br/>"%><br/>


Download Liferay Service Builder Finder Methods Portlet



Environment:

Liferay IDE 2.x+Eclipse (Kepler) +Liferay Plugins SDK 6.2+Tomcat 7.x Liferay Portal Bundle

Deployment and its Working.

Download portlet you can source or war file to deploy into liferay portal as your convenient.

Once portlet successfully deployed drag the portlet in any desired page. Portlet is available in sample category.

In the portlet page you can click on Service Builder Finder Examples link then you can see the search container with search inputs.

Note:

The portlet does not have any real functionality but I just showed calling of finder methods in portlet page.

Portlet Screens:

Default Page


Service Builder Finder Method Examples



Reference Links





Author

Popular Posts

Recent Posts

Recent Posts Widget