Liferay自定义原生态SQL查询

原文:http://www.chinasb.org/archives/2010/12/1313.shtml

首先,Liferay内置的ServiceBuilder工具十分强大,基本上的数据库操作都可以通过自动生成的方法去实现。但是某些复杂的方法就需要使用到自定义SQL查询了,本文以一个例子向大家介绍如何在Liferay的开发中使用原生态SQL执行数据库操作。(以下操作基于ext开发环境)

1.在portal-ext.properties添加

custom.sql.configs=custom-sql/default.xml,custom-sql/default-ext.xml

2.新建ext-impl/src/custom-sql/default-ext.xml与ext-impl/src/custom-sql/book.xml(例子自定义SQL文件)

default-ext.xml:

<?xml version="1.0"?>

<custom-sql>
	<sql file="custom-sql/book.xml" />
</custom-sql>

book.xml:

<?xml version="1.0"?>

<custom-sql>
  <sql id="com.xxx.xxx.portlet.book.service.persistence.BookFinder.countByUserId">
    <![CDATA[
		SELECT
			*
		FROM
			BOOK
		WHERE
			USERID = ?
	]]>
  </sql>
</custom-sql>

解析一下:sql id="com.xxx.xxx.portlet.book.service.persistence.BookFinder.countByUserId",这里指定BookFinder接口的countByUserId方法去执行自定义的SQL语句:SELECT * FORM BOOK WHERE USERID = ?(这里就不用说了吧,?代表一个参数)

好了,接下来我们利用Liferay的强大的ServiceBuilder工具为我们生成BookFinder的接口和相应的Util类。

3.新建com.xxx.xxx.portlet.book.service.persistence.BookFinderImpl.java(即是BookFinder接口的实现类,这里一定要注意命名规范:实体名加FinderImpl)

BookFinderImpl.java:

public class BookFinderImpl extends BasePersistenceImpl implements BookFinder {

	public static String COUNT_BY_USER_ID = BookFinder.class.getName()
			+ ".countByUserId";

	public int countByUserId(long userId) throws SystemException {

		Session session = null;

		try {
			session = openSession();

			return countByUserId(session, userId);
		} catch (Exception e) {
			throw new SystemException(e);
		} finally {
			closeSession(session);
		}
	}

	protected int countByUserId(Session session, long userId) {

		String sql = CustomSQLUtil.get(COUNT_BY_USER_ID);

		_log.info("SQL:" + sql);

		SQLQuery q = session.createSQLQuery(sql);

		QueryPos qPos = QueryPos.getInstance(q);

		qPos.add(userId);

		return q.list().size();
	}

	public List<Book> findByUserId(long userId, int start, int end) throws SystemException {

		Session session = null;

		try {
			session = openSession();

			return findByUserId(session, userId, start, end);
		} catch (Exception e) {
			throw new SystemException(e);
		} finally {
			closeSession(session);
		}
	}

	protected List<Book> findByUserId(Session session, long userId, int start, int end) {

		String sql = CustomSQLUtil.get(COUNT_BY_USER_ID);

		_log.info("SQL:" + sql);

		SQLQuery q = session.createSQLQuery(sql);

		q.addEntity("Book", BookImpl.class);

		QueryPos qPos = QueryPos.getInstance(q);

		qPos.add(userId);

		return (List<Book>)QueryUtil.list(q, getDialect(), start, end);
	}

	private static Log _log = LogFactory.getLog(BookFinderImpl.class);
}

解析一下:BookFinderImpl记得继承自BasePersistenceImpl并且实现BookFinder接口(放心,一会让service build去帮我们生成这个接口),这里有两个方法,一个是实现查询总数,一个是实现分页查询实体数据。细心你的发现没有,其实Liferay用的也就是自已封装过的SQLQuery去执行原生态SQL,把SQL定义在XML完全是为了达到解耦的一种效果,如果你懒点,完全可以直接:

SQLQuery q = session.createSQLQuery("SELECT * FROM BOOK WHERE USERID = ?");

QueryPos qPos = QueryPos.getInstance(q);

qPos.add(userId);

q.list()执行后返回的是一个对象数组List,如果要转换成实体对象的List,必须用以下方法:

q.addEntity("Book", BookImpl.class);

List<Book> books = (List<Book>)QueryUtil.list(q, getDialect(), start, end);

好了,马上ant service build一下,将会生成你需要的接口与Util类了。这样还不够,要在视图层调用ServiceBuilder给你生成了专用的BookLocalServiceUtil工具类,所以还要再麻烦一下。

4.修改com.xxx.xxx.portlet.book.service.impl.BookLocalServiceImpl.java,加入要供外部调用的两个方法

public int getCountByUserId(long userId) throws SystemException {
		return BookFinderUtil.countByUserId(userId);
	}

	public List<Book> getBooksByUserId(long userId, int start, int end) throws SystemException {
		return BookFinderUtil.findByUserId(userId, start, end);
	}

5.最后再次ant build service,让ServiceBuilder工具帮你生成相应的接口就可以在你的action里进行调用了。

相关推荐