原创

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 方法的接口。按照以下步骤很容易做到:

  1. 指定您的自定义 SQL。

  2. 实现你的 finder 方法。

  3. 从您的服务访问您的 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在服务持久包中创建一个类。事件列表项目EventFinderImplcom.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

正文到此结束
该篇文章的评论功能已被站长关闭
本文目录