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=">"/> </finder> Less Than <finder name="minorStudent" return-type="Collection"> <finder-column name="studentAge" comparator="<"/> </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=">"/> </finder> <finder name="minorStudentLessThan" return-type="Collection"> <finder-column name="studentAge" comparator="<"/> </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:
- Define finder tag and finder columns in Entity Tag
- Run service Builder
- Implement Custom method in XXXLocalServiceImpl class
- Run service Builder
- 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.implpath
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 />">«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
0 comments:
Post a Comment