目标:掌握Query接口的使用
主要内容包括:
u 查询所有信息
u 使用Query完成分页
u 根据条件查询
u 相关接口方法介绍
1、查询所有信息
在第一讲中查询所有信息的代码如下:
List<Userinfo> list = em.createQuery("select u from Userinfo u").getResultList();
相当于下面的两行代码:
Query q = em.createQuery("select u from Userinfo u");
List<Userinfo> list =q.getResultList();
查询语句“select u from Userinfo u”不是标准的SQL语句,其中Userinfo是实体类的名字,u相当于对象。查询的结果是封装后的对象。这与以前的JDBC是不同的,SQL语句查询的结果是ResultSet。如果查询结果是多个,应该使用Query接口的getResultList方法,如果查询结果只有一个,可以使用Query接口的getSingleResult方法。
这种方式的查询直接在参数中写查询语句,还可以把查询语句单独写出来,然后调用。这种方式称为命名查询,例如使用命名查询上面的语句可以写成下面的样子:
@NamedQuery(name = "findAllUser", query = "SELECT u FROM Userinfo u")
name表示该查询的名字,query是查询语句本身。命名查询可以写在实体类中,第一次课生成的实体类中就有多个命名查询。
对于命名查询可以使用EntityManager的createNamedQuery方法,要访问上面的查询可以使用下面的代码:
Query q = em.createNamedQuery("findAllUser");
List<Userinfo> list =q.getResultList();
createNamedQuery方法的参数命名查询的名字。
实验:把第一次课中的查询修改成命名查询。
参考过程:
1)修改Userinfo实体类中的如下代码(红色部分是新添加的):
@NamedQueries( {
@NamedQuery(name = "Userinfo.findByUserid",
query = "SELECT u FROM Userinfo u WHERE u.userid = :userid"),
@NamedQuery(name = "Userinfo.findByUsername",
query = "SELECT u FROM Userinfo u WHERE u.username = :username"),
@NamedQuery(name = "Userinfo.findByUserpass",
query = "SELECT u FROM Userinfo u WHERE u.userpass = :userpass"),
@NamedQuery(name = "Userinfo.findByUsertype",
query = "SELECT u FROM Userinfo u WHERE u.usertype = :usertype"),
@NamedQuery(name = "findAllUser", query = "SELECT u FROM Userinfo u")
})
2)修改UserManagerBean中的findAllUser方法,修改后的代码如下:
public List<Userinfo> findAllUser(){
// return em.createQuery("select u from Userinfo u").getResultList();
Query q = em.createNamedQuery("findAllUser");
List<Userinfo> list =q.getResultList();
return list;
}
3)从新部署、测试。
2、使用Query完成分页
分页显示就是每次只显示部分对象的信息。要显示哪一部分信息取决于从什么地方开始显示,显示到什么地方。Query接口可以控制要获取的记录,有两个方法来设置要获取的第一条记录和最后一条记录。两个方法的定义分别如下:
setMaxResults(int maxResult),参数是要查询的最大记录数。
setFirstResult(int startposition),参数是第一个要查询的记录的位置。
通过这两个属性完成分页显示。
实验:自己完成用户信息列表的分页显示,每页显示5
条记录。
提示:在会话Bean
中添加一个根据页码查询的方法,参数是要显示的页码。
3、根据条件查询
根据条件查询包括查询语句的构造和查询条件处理。
3.1 构造查询语句
根据条件查询,需要在查询语句中使用变量,可以有两种方式:位置参数和名字参数。
位置参数
在位置参数中,使用“?”号加上参数的序号的方式表示参数。
例,根据用户名username查询用户。
SELECT u FROM Userinfo u where u.username = ?1
1表示第一个参数。
在位置参数中,可以使用多个参数,可以用不同的数字表示。同一个参数可以在查询中出现多次。
名字参数
在名字参数种,使用“:”号加上参数的名字的方式表示参数。
例,根据用户类型查询用户。
SELECT u FROM Userinfo u WHERE u.usertype = :usertype
“:”号后面的usertype就是参数的名字。
不管是位置参数还是名字参数都可以在命名查询中使用。
3.2 处理查询条件
在执行查询语句的时候需要为条件赋值,可以通过Query接口的相应方法完成。位置参数和名字参数使用的赋值方法是不同的,并且参数可以是各种类型。用于位置参数的主要方法如下:
public Query setParameter(int position,Object value)
public Query setParameter(int position,Date value,TemporalType temporalType)
public Query setParameter(int position,Calendar value,TemporalType temporalType)
用于名字参数的赋值方法基本相同,只是第一个参数用于指定参数的名字。主要方法如下:
public Query setParameter(String name,Object value)
public Query setParameter(String name,Date value,TemporalType temporalType)
public Query setParameter(String name,Calendar value,TemporalType temporalType)
例1:使用前面介绍的根据用户名进行查询的语句。
Query q = em.createQuery("SELECT u FROM Userinfo u where u.username = ?1");
q = q.setParameter(1,username);
List<Userinfo> list =q.getResultList();
例2:使用前面介绍的根据用户类型进行查询的语句。
Query q = em.createQuery("SELECT u FROM Userinfo u WHERE u.usertype = :usertype");
q = q.setParameter("usertype",usertype);
List<Userinfo> list =q.getResultList();
实验:在前面的功能中添加根据用户名和用户类型进行查询的功能。
参考实验过程及代码。
1)在UserManagerBean中添加根据用户名和根据用户类型查询用户的方法,方法如下:
// 根据用户名查询
public List<Userinfo> findUserByName(String username){
// 使用位置参数
Query q = em.createQuery("SELECT u FROM Userinfo u where u.username = ?1");
// 为参数赋值
q = q.setParameter(1,username);
// 得到查询结果
List<Userinfo> list =q.getResultList();
// 返回查询结果
return list;
}
// 根据用户类型查询
public List<Userinfo> findUserByType(char usertype){
// 使用命名参数
Query q = em.createQuery("SELECT u FROM Userinfo u WHERE u.usertype = :usertype");
// 为参数赋值
q = q.setParameter("usertype",usertype);
// 得到查询结果
List<Userinfo> list =q.getResultList();
// 返回查询结果
return list;
}
2)在UserManagerRemote中声明上面的两个方法,参考代码如下:
public List<Userinfo> findUserByName(String username);
public List<Userinfo> findUserByType(char usertype);
3)修改FindAllUserServlet,让该控制器可以完成3种查询的控制,参考代码(红色部分为核心代码)如下:
/*
* FindAllUserServlet.java
*
* Created on 2007
年5月21日, 上午6:27
*/
package jpa.web;
import java.io.*;
import java.net.*;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.ejb.EJB;
import jpa.UserManagerRemote;
import jpa.Userinfo;
import java.util.List;
import java.util.Iterator;
/**
*
* @author Administrator
* @version
*/
public class FindAllUserServlet extends HttpServlet {
@EJB
UserManagerRemote user;
/** Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods.
* @param request servlet request
* @param response servlet response
*/
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String username = request.getParameter("username");
String usertype = request.getParameter("usertype");
//
调用业务方法
List<Userinfo> list;
//
根据参数确定查询类型,调用相应的方法
if(username != null)
list = user.findUserByName(username);
else if(usertype != null)
list = user.findUserByType(usertype.charAt(0));
else
list = user.findAllUser();
//
把查询的结果存储到
request
中,从而传递到页面
request.setAttribute("userlist",list);
//
专向
userlist.jsp
RequestDispatcher rd = request.getRequestDispatcher("userlist.jsp");
rd.forward(request,response);
}
// <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
/** Handles the HTTP <code>GET</code> method.
* @param request servlet request
* @param response servlet response
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
/** Handles the HTTP <code>POST</code> method.
* @param request servlet request
* @param response servlet response
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
/** Returns a short description of the servlet.
*/
public String getServletInfo() {
return "Short description";
}
// </editor-fold>
}
4)添加一个输入查询条件和显示查询结果的JSP文件userlist.jsp,参考代码如下:
<%@page contentType="text/html"%>
<%@page pageEncoding="gb2312"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>用户信息</title>
</head>
<body>
<h1>用户信息</h1>
<br>
<form action="FindAllUserServlet" method="POST">
根据用户名查询:<input type="text" name="username"/>
<input type="submit" value="确定" />
</form>
<br>
<form action="FindAllUserServlet" method="POST">
根据类型查询:<select name="usertype">
<option value="0" selected>普通用户</option>
<option value="1">管理员</option>
</select><input type="submit" value="确定" />
</form>
<br>
<form action="FindAllUserServlet" method="POST">
<input type="submit" value="显示所有" />
</form>
<table border="1">
<thead>
<tr>
<th>序号</th>
<th>用户ID</th>
<th>用户名</th>
<th>权限</th>
</tr>
</thead>
<tbody>
<c:forEach varStatus="status" var="user" items="${userlist}">
<tr>
<td>${status.index+1}</td>
<td>${user.userid}</td>
<td>${user.username}</td>
<td>
<c:if test="${user.usertype==\"0\"}">
普通用户
</c:if>
<c:if test="${user.usertype==\"1\"}">
管理员
</c:if>
</td>
</tr>
</c:forEach>
</tbody>
</table>
</body>
</html>
5)部署、测试。
思考:如何在显示查询结果的时候把查询条件也显示出来?
4、相关接口方法
关于Query接口的方法参考书上370页Query接口部分。关于EntityManager接口的方法参考书上358页EntityManager接口部分。