【发布时间】:2017-01-19 00:35:36
【问题描述】:
我在使用 EclipseLink 在 JavaEE Web 应用程序中实现分页时遇到问题。
目标实体:
@Entity
@JsonIdentityInfo(generator=JSOGGenerator.class)
@NamedQueries({
@NamedQuery(
name = Project.QUERY_FIND_FOR_ADMIN,
query = "SELECT DISTINCT p " +
"FROM Project p " +
"LEFT JOIN FETCH p.documents " +
"LEFT JOIN FETCH p.projectManager " +
"LEFT JOIN FETCH p.watchingUsers " +
"LEFT JOIN FETCH p.users " +
"LEFT JOIN FETCH p.scheme " +
"ORDER BY p.id",
hints = {
@QueryHint(name = QueryHints.LEFT_FETCH, value = "p.documents.states")
// ,@QueryHint(name = QueryHints.JDBC_FETCH_SIZE, value = Project.ITEMS_PER_PAGE) // does not change anything
// ,@QueryHint(name = QueryHints.JDBC_MAX_ROWS, value = Project.ITEMS_PER_PAGE) // results in a LIMIT statement
}
)
})
public class Project extends BaseEntity {
public static final String ITEMS_PER_PAGE = "" + 2;
...
}
一个BaseDAO
public abstract class BaseEntityDAO<Entity> extends AbstractDAO {
...
protected List<Entity> executeQuery(String queryName, Map<String, ?> parameters, final int firstResult) {
TypedQuery<Entity> query = prepareQuery(queryName, parameters);
query.setFirstResult(firstResult);
query.setMaxResults(Integer.parseInt(Project.ITEMS_PER_PAGE));
return query.getResultList();
}
}
这会导致以下查询:
// Logging
[2016-09-11T13:16:26.141+0200] [glassfish 4.1] [INFO] [] [] [tid: _ThreadID=28 _ThreadName=Thread-8] [timeMillis: 1473592586141] [levelValue: 800] [[
page: 1]]
// Logging
[2016-09-11T13:16:26.141+0200] [glassfish 4.1] [INFO] [] [] [tid: _ThreadID=28 _ThreadName=Thread-8] [timeMillis: 1473592586141] [levelValue: 800] [[
first row: 0]]
[2016-09-11T13:16:26.143+0200] [glassfish 4.1] [FINE] [] [org.eclipse.persistence.session./file:/Users/timtoheus/NetBeansProjects/discanno/target/swan-2.0/WEB-INF/classes/_SwanPU.sql] [tid: _ThreadID=32 _ThreadName=http-listener-1(5)] [timeMillis: 1473592586143] [levelValue: 500] [[
SELECT DISTINCT t1.ID, t1.Name, t1.CREATOR_ID, t1.COLORSCHEME_ID, t0.ID, t0.Name, t0.TOKENIZATIONLANG, t0.Scheme FROM SCHEME t1 LEFT OUTER JOIN PROJECT t0 ON (t0.Scheme = t1.ID)]]
[2016-09-11T13:16:26.144+0200] [glassfish 4.1] [FINE] [] [org.eclipse.persistence.session./file:/Users/timtoheus/NetBeansProjects/discanno/target/swan-2.0/WEB-INF/classes/_SwanPU.sql] [tid: _ThreadID=28 _ThreadName=http-listener-1(1)] [timeMillis: 1473592586144] [levelValue: 500] [[
SELECT DISTINCT t1.ID AS a1, t1.Name AS a2, t1.TOKENIZATIONLANG AS a3, t1.Scheme AS a4, t0.ID AS a5, t0.Name AS a6, t0.Text AS a7,
t0.project_fk AS a8, t2.ID AS a9, t2.Completed AS a10, t2.LastEdit AS a11, t2.document_fk AS a12, t2.user_fk AS a13,
t3.ID AS a14, t3.CreateDate AS a15, t3.EMail AS a16, t3.Lastname AS a17, t3.Password AS a18, t3.Prename AS a19, t3.Role AS a20,
t3.session AS a21, t4.ID AS a22, t4.CreateDate AS a23, t4.EMail AS a24, t4.Lastname AS a25, t4.Password AS a26, t4.Prename AS a27,
t4.Role AS a28, t4.session AS a29, t5.ID AS a30, t5.CreateDate AS a31, t5.EMail AS a32, t5.Lastname AS a33, t5.Password AS a34,
t5.Prename AS a35, t5.Role AS a36, t5.session AS a37, t6.ID AS a38, t6.Name AS a39, t6.CREATOR_ID AS a40, t6.COLORSCHEME_ID AS a41 F
ROM PROJECT t1 LEFT OUTER JOIN DOCUMENT t0 ON (t0.project_fk = t1.ID)
LEFT OUTER JOIN STATE t2 ON (t2.document_fk = t0.ID)
LEFT OUTER JOIN (PROJECTS_MANAGER t7 JOIN Users t3 ON (t3.ID = t7.MANAGER_ID)) ON (t7.PROJECT_ID = t1.ID)
LEFT OUTER JOIN (PROJECTS_WATCHINGUSERS t8 JOIN Users t4 ON (t4.ID = t8.WATCHINGUSER_ID)) ON (t8.PROJECT_ID = t1.ID)
LEFT OUTER JOIN (USERS_PROJECTS t9 JOIN Users t5 ON (t5.ID = t9.USERS_ID)) ON (t9.PROJECT_ID = t1.ID)
LEFT OUTER JOIN SCHEME t6 ON (t6.ID = t1.Scheme)
ORDER BY t1.ID
LIMIT ? OFFSET ?
bind => [2, 0]]]
// Logging
[2016-09-11T13:16:28.885+0200] [glassfish 4.1] [INFO] [] [] [tid: _ThreadID=28 _ThreadName=Thread-8] [timeMillis: 1473592588885] [levelValue: 800] [[
number of results: 1]]
如您所见,该查询使用 LIMIT 和 OFFSET 并正确绑定所需的参数,但无论 page/OFFSET 参数是什么,始终返回相同的结果。它总是返回“Project1”,但数据库中总共有 6 个项目(pgAdmin 和 IntelliJ 可以证明这一点)。将 ORDER BY 更改为 name/id 或增加“Project.ITEMS_PER_PAGE”也不会改变任何内容。所需的行为应该返回声明为“Project.ITEMS_PER_PAGE”的行数,而不是总是一个。我想避免编写原生 SQL 查询。
EclipseLink 应支持此处列出的 PostgreSQL: https://www.eclipse.org/eclipselink/documentation/2.6/concepts/app_tl_ext001.htm
JPQL 不支持表达式“LIMIT”、“FETCH FIRST ROWS”和“OFFSET”。如上所述,我还尝试了一些 QueryHints。奇怪的是,如果我在 Postgres 中手动执行查询,它会正确返回所需数量的结果。
希望有人能给我一个提示。
环境:GlassFish 4.1、PostgreSQL ~9.3、EclipseLink 2.6.2
【问题讨论】:
标签: postgresql jakarta-ee pagination eclipselink jpql