Liferay6.2开发自定义 SQL 查询
Service Builder 的 finder 方法有助于通过实体的属性(它们的列值)搜索实体。将该列添加为service.xml
文件中查找程序的参数,运行服务构建器,它会在您的持久层中生成查找程序方法,并将调用查找程序的方法添加到您的服务层。但是,如果您想进行包含多个实体的属性的更复杂的搜索,该怎么办?
例如,考虑 事件列表 portlet。假设您想根据名称、描述和位置名称查找事件。在事件列表 portlet 中,事件实体通过位置的 ID 而不是它的名称来引用它的位置。也就是说,事件实体表 , Event_Event
通过表locationId
列中的长整数 ID 来引用事件的位置。但是您需要访问事件位置的名称。当然,您可以使用 SQL 连接事件和位置表以包含位置名称。但是您将如何将自定义 SQL 合并到您的 portlet 中呢?您将如何从您的服务中调用 SQL?Service Builder 允许您通过将 SQL 指定为Liferay 自定义 SQL并通过自定义查找器方法。
Liferay 自定义 SQL 是一种服务构建器支持的方法,用于对数据库执行复杂的自定义查询。从持久层中的 finder 方法调用自定义 SQL 很简单。Service Builder 可以帮助您生成 finder 方法的接口。按照以下步骤很容易做到:
指定您的自定义 SQL。
实现你的 finder 方法。
从您的服务访问您的 finder 方法。
接下来,以事件列表 portlet 为例,您将了解如何完成这些步骤。
步骤 1:指定您的自定义 SQL
在您测试完您的 SQL 之后,您必须在特定文件中指定它以便 Liferay 访问它。Liferay 的CustomSQLUtil
类从default.xml
在您的 portlet 项目 docroot/WEB-INF/src/custom-sql/
文件夹中调用的文件中查找自定义 SQL 。您必须创建custom-sql
文件夹并default.xml
在该custom-sql
文件夹中创建文件。该 default.xml
文件必须遵循以下格式:
<custom-sql>
<sql id="[fully-qualified class name + method]">
SQL query wrapped in <![CDATA[...]]>
No terminating semi-colon
</sql>
</custom-sql>
您可以custom-sql
为您希望用于 portlet 的每个自定义 SQL 查询添加一个元素,只要每个查询都有一个唯一的 ID。我们建议对 ID 值使用的约定是 finder 的完全限定类名,后跟一个点 ( .
) 字符和 finder 方法的名称。有关 finder 类和 finder 方法的更多详细信息,请参见步骤 2。
在 Event Listing 项目中,以下 ID 值用于查询:
com.liferay.docs.eventlisting.service.persistence.\
EventFinder.findByEventNameEventDescriptionLocationName
自定义 SQL 必须包含在元素的字符数据 ( CDATA
) 中sql
。重要的是,SQL不能以分号结尾。遵循这些规则,default.xml
事件列表项目的文件指定了一个连接事件和位置表的 SQL 查询:
<?xml version="1.0" encoding="UTF-8"?>
<custom-sql>
<sql id="com.liferay.docs.eventlisting.service.persistence.EventFinder.\
findByEventNameEventDescriptionLocationName">
<![CDATA[
SELECT Event_Event.*
FROM Event_Event
INNER JOIN
Event_Location ON Event_Event.locationId = Event_Location.locationId
WHERE
(Event_Event.name LIKE ?) AND
(Event_Event.description LIKE ?) AND
(Event_Location.name LIKE ?)
]]>
</sql>
</custom-sql>
如果复制上面的 XML 片段,请确保删除\
ID 末尾的反斜杠 ( ) 字符,以便 finder 方法名称 findByEventNameEventDescriptionLocationName
紧跟下面指定的包路径:
com.liferay.docs.eventlisting.service.persistence.
现在您已经指定了一些自定义 SQL,下一步是实现一个 finder 方法来调用它。finder 的方法名称应与您刚刚为sql
元素指定的 ID 相匹配。
第 2 步:实现您的 Finder 方法
指定自定义 SQL 查询后,您需要实现 finder 方法来调用它。这应该在服务的持久层中完成。Service Builder 为finder 生成接口,但您需要创建实现。
第一步是*FinderImpl
在服务持久包中创建一个类。事件列表项目EventFinderImpl
在com.liferay.docs.eventlisting.service.persistence.impl
包中包含该类 。你的类,比如EventFinderImpl
,应该扩展BasePersistenceImpl<Event>
。
运行 Service Builder为查找器生成*Finder
接口和*Util
类。Service Builder基于该类生成*Finder
接口和 *FinderUtil
实用程序*FinderImpl
类。修改你的 *FinderImpl
类,让它实现*Finder
你刚刚生成的接口:
public class *FinderImpl extends BasePersistenceImpl<Event>
implements EventFinder {
}
现在你可以在你的EventFinderImpl
类中创建我们的 finder 方法。将您的 finder 方法和静态字段添加到*FinderImpl
类中。这是 EventFinderImpl
课程:
public List<Event> findByEventNameEventDescriptionLocationName(
String eventName, String eventDescription, String locationName,
int begin, int end) {
Session session = null;
try {
session = openSession();
String sql = CustomSQLUtil.get(
FIND_BY_EVENTNAME_EVENTDESCRIPTON_LOCATIONNAME);
SQLQuery q = session.createSQLQuery(sql);
q.setCacheable(false);
q.addEntity("Event_Event", EventImpl.class);
QueryPos qPos = QueryPos.getInstance(q);
qPos.add(eventName);
qPos.add(eventDescription);
qPos.add(locationName);
return (List<Event>) QueryUtil.list(q, getDialect(), begin, end);
} catch (Exception e) {
try {
throw new SystemException(e);
} catch (SystemException se) {
se.printStackTrace();
}
} finally {
closeSession(session);
}
return null;
}
public static final String FIND_BY_EVENTNAME_EVENTDESCRIPTON_LOCATIONNAME =
EventFinder.class.getName() +
".findByEventNameEventDescriptionLocationName";
请记住导入所需的类。需要以下导入 EventFinderImpl
:
import java.util.List;
import com.liferay.docs.eventlisting.model.Event;
import com.liferay.docs.eventlisting.model.impl.EventImpl;
import com.liferay.portal.kernel.dao.orm.QueryPos;
import com.liferay.portal.kernel.dao.orm.QueryUtil;
import com.liferay.portal.kernel.dao.orm.SQLQuery;
import com.liferay.portal.kernel.dao.orm.Session;
import com.liferay.portal.kernel.exception.SystemException;
import com.liferay.portal.service.persistence.impl.BasePersistenceImpl;
import com.liferay.util.dao.orm.CustomSQLUtil;
自定义 finder 方法打开一个新的 Hibernate 会话并使用 Liferay 的 CustomSQLUtil.get(String id)
方法获取自定义 SQL 以用于数据库查询。该FIND_BY_EVENTNAME_EVENTDESCRIPTON_LOCATIONNAME
静态字段包含自定义SQL查询的ID。该 FIND_BY_EVENTNAME_EVENTDESCRIPTON_LOCATIONNAME
字符串基于*Finder
接口的完全限定类名( EventFinder
) 和 finder 方法的名称 ( findByEventNameEventDescriptionLocationName
)。
惊人的!您的自定义 SQL 已就位,您的 finder 方法已实施。接下来,您将从您的服务中调用 finder 方法。
第 3 步:从您的服务访问您的 Finder 方法
到目前为止,您创建了一个*FinderImpl
类并生成了一个*FinderUtil
实用程序类。但是,您的 portlet 类不应直接使用 finder 实用程序类;只有插件项目中的本地或远程服务实现(即, *LocalServiceImpl
或*ServiceImpl
)应该调用 *FinderUtil
该类。这鼓励了适当的关注点分离:portlet 类调用服务的业务逻辑,而服务又使用持久层的查找器类访问数据模型。因此,您将在*LocalServiceImpl
类中添加一个方法,该方法通过*FinderUtil
该类调用 finder 方法的实现。然后,您将通过重新构建服务来提供 portlet 和 JSP 对该服务方法的访问。
以下方法EventLocalServiceImpl
调用步骤 2 中讨论的 finder 方法:
public List<Event> findByEventNameEventDescriptionLocationName(String eventName,
String eventDescription, String locationName, int begin, int end)
throws SystemException {
return EventFinderUtil.findByEventNameEventDescriptionLocationName(
eventName, eventDescription, locationName, begin, end);
}
添加服务方法以调用 finder 方法后,运行 Service Builder 以生成接口并使您的 finder 服务方法在EventLocalServiceUtil
类中可用。
现在,您可以从 portlet 类或从 JSP 间接调用 finder 方法。要在 Event Listing 项目中调用 finder 方法,只需调用 EventLocalServiceUtil.findByEventNameEventDescriptionLocationName(...)
!
恭喜您为您的 portlet 开发了自定义 SQL 查询和自定义查找器!
https://help.liferay.com/hc/zh-cn/articles/360018179071-Developing-Custom-SQL-Queries