11第十二天DBUtils
一、前言:元数据介绍
准备工作:数据库day12(account)、mysql-connector-java-5.1.40-bin.jar和c3p0-0.9.1.2.jar,以及c3p0-config.xml:
<?xml version="1.0" encoding="utf-8"?>
<c3p0-config>
<default-config name="aaa">
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql:///day12</property>
<property name="user">root</property>
<property name="password">666666</property>
</default-config>
</c3p0-config>
select * from account;
+----+------+-------+
| id | name | money |
+----+------+-------+
| 1 | a | 1000 |
| 2 | b | 1000 |
| 3 | c | 1000 |
+----+------+-------+
(一)、元数据
1、DataBaseMetaData
(1)、元数据:数据库、表、列的定义信息。
(2)、 Connection.getMetaData()
(3)、DataBaseMetaData对象
String getURL()
:返回一个String类对象,代表数据库的URL。String getUserName()
:返回连接当前数据库管理系统的用户名。String getDriverName()
:返回驱动驱动程序的名称。ResultSet getPrimaryKeys(String catalog, String schema, String table)
:返回指定表主键的结果集catalog
- 类别名称;它必须与存储在数据库中的类别名称匹配;该参数为 "" 表示获取没有类别的那些描述;为 null 则表示该类别名称不应该用于缩小搜索范围。schema
- 模式名称;它必须与存储在数据库中的模式名称匹配;该参数为 "" 表示获取没有模式的那些描述;为 null 则表示该模式名称不应该用于缩小搜索范围。table
- 表名称;它必须与存储在数据库中的表名称匹配。
每个主键列描述都有以下列:
TABLE_CAT String => 表类别(可为 null)
TABLE_SCHEM String => 表模式(可为 null)
TABLE_NAME String => 表名称
COLUMN_NAME String => 列名称
KEY_SEQ short => 主键中的序列号(值 1 表示主键中的第一列,值 2 表示主键中的第二列)。
PK_NAME String => 主键的名称(可为 null)
```
* `getTables(String catalog, String schemaPattern,String tableNamePattern,String[] types)` - 获取可在给定类别中使用的表的描述。仅返回与类别、模式、表名称和类型标准匹配的表描述。它们根据 TABLE_TYPE、TABLE_CAT、TABLE_SCHEM 和 TABLE_NAME 进行排序。
```sql
每个表描述都有以下列:
TABLE_CAT String => 表类别(可为 null)
TABLE_SCHEM String => 表模式(可为 null)
TABLE_NAME String => 表名称
TABLE_TYPE String => 表类型。典型的类型是 "TABLE"、"VIEW"、"SYSTEM TABLE"、"GLOBAL TEMPORARY"、"LOCAL TEMPORARY"、"ALIAS" 和 "SYNONYM"。
REMARKS String => 表的解释性注释
TYPE_CAT String => 类型的类别(可为 null)
TYPE_SCHEM String => 类型模式(可为 null)
TYPE_NAME String => 类型名称(可为 null)
SELF_REFERENCING_COL_NAME String => 有类型表的指定 "identifier" 列的名称(可为 null)
REF_GENERATION String => 指定在 SELF_REFERENCING_COL_NAME 中创建值的方式。这些值为 "SYSTEM"、"USER" 和 "DERIVED"。(可能为 null)
注: 有些数据库可能不返回用于所有表的信息。
- 方法练习:
package com.lmd.metadata;
import java.sql.Connection/DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet/SQLException;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class DataBaseMetaDataDemo {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
ComboPooledDataSource source = new ComboPooledDataSource();
try {
conn = source.getConnection();
//--获取当前数据库的元数据
DatabaseMetaData metaData = conn.getMetaData();
//--获取数据库连接时使用的URL 框架设计者使用
String url = metaData.getURL();
System.out.println(url);//输出:jdbc:mysql:///day12
//--获取数据库的用户名 框架设计者使用
String name = metaData.getUserName();
System.out.println(name);//输出:root@localhost
//--返回驱动驱动程序的名称。 框架设计者使用
String driver = metaData.getDriverName();
System.out.println(driver);//输出:MySQL Connector Java
//--返回指定表主键的结果集 框架设计者使用
rs = metaData.getPrimaryKeys(null, null, "account");
while (rs.next()) {
//获取主键的序列号和名称
short cseq = rs.getShort("KEY_SEQ");
String cname = rs.getString("PK_NAME");
System.out.println(cseq+":"+cname);//1:PRIMARY
}
//-获取表, "acc%":以acc开头的表;"%":所有 表
rs = metaData.getTables(null, null, "%", new String[]{"TABLE"});
while (rs.next()) {
//获取表名称
String tname = rs.getString("TABLE_NAME");
System.out.println(tname);//输出:account
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//rs、ps和conn释放
}
}
}
2、ParameterMetaData
(1)、PreparedStatement . getParameterMetaData()
- 获得代表PreparedStatement元数据的ParameterMetaData对象。
- select * from user where name=? And password=?
(2)、ParameterMetaData对象
getParameterCount()
获得指定参数的个数getParameterTypeName(int param)
获得指定参数的sql类型
(3)、getParameterType异常处理
- Parameter metadata not available for the given statement
(4)、url后面拼接参数
- ?generateSimpleParameterMetadata=true
- 方法练习:
package com.lmd.metadata;
import java.sql.Connection;
import java.sql.DatabaseMetaData/ParameterMetaData;
import java.sql.PreparedStatement/ResultSet;
import java.sql.SQLException;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class PMMetaDataDemo {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
ComboPooledDataSource source = new ComboPooledDataSource();
try {
conn = source.getConnection();
ps = conn.prepareStatement("select * from account where name=? and money=?");
//---获取参数元数据
ParameterMetaData metaData = ps.getParameterMetaData();
//--获取参数个数
int count = metaData.getParameterCount();
System.out.println(count);//2
//--获取数据的类型
// 要修改c3p0-config.xml:<property name="jdbcUrl">jdbc:mysql:///day12
// ?generateSimpleParameterMetadata=true</property>
String type = metaData.getParameterTypeName(1);//mysql支持不好
System.out.println(type);//VARCHAR
String type2 = metaData.getParameterTypeName(2);
System.out.println(type2);//VARCHAR
} catch (Exception e) {
e.printStackTrace();
} finally {
//rs、ps和conn释放
}
}
}
3、ResultSetMetaData
(1)、ResultSet. getMetaData()
- 获得代表ResultSet对象元数据的ResultSetMetaData对象。
(2)、ResultSetMetaData对象
getColumnCount()
返回resultset对象的列数getColumnName(int column)
获得指定列的名称getColumnTypeName(int column)
获得指定列的类型- 方法练习:
package com.lmd.metadata;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class PMMetaDataDemo {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
ComboPooledDataSource source = new ComboPooledDataSource();
try {
conn = source.getConnection();
ps = conn.prepareStatement("select * from account");
rs = ps.executeQuery();
//框架设计者使用
//--获取结果集元数据
ResultSetMetaData metaData = rs.getMetaData();
//--获取结果集中列的个数
int ccount = metaData.getColumnCount();
System.out.println(ccount);//3
//--获取结果集中指定列的名称
String cname = metaData.getColumnName(2);
System.out.println(cname);//name
//--获取结果集中指定列的类型的名称
String tname = metaData.getColumnTypeName(3);
System.out.println(tname);//DOUBLE
} catch (Exception e) {
e.printStackTrace();
} finally {
//rs、ps和conn释放
}
}
}
- 总练习:
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
ComboPooledDataSource source = new ComboPooledDataSource();
try {
conn = source.getConnection();
ps = conn.prepareStatement("select * from account");
rs = ps.executeQuery();
//框架设计者使用
//--获取结果集元数据
ResultSetMetaData metaData = rs.getMetaData();
//--获取结果集中列的个数
int ccount = metaData.getColumnCount();
//System.out.println(ccount);//3
//--获取结果集中指定列的名称
//String cname = metaData.getColumnName(2);
//System.out.println(cname);//name
//--获取结果集中指定列的类型的名称
//String tname = metaData.getColumnTypeName(3);
//System.out.println(tname);//DOUBLE
System.out.println("----------------------------------------------------");
for (int i = 1; i <= ccount; i++) {
String cname = metaData.getColumnName(i);
String ctype = metaData.getColumnTypeName(i);
System.out.print(cname+":"+ctype+"\t\t");
}
System.out.println();
System.out.println("----------------------------------------------------");
while (rs.next()) {
for (int i = 1; i <= ccount; i++) {
Object obj = rs.getObject(i);
System.out.print(obj+"\t\t ");
}
System.out.println();
}
System.out.println("----------------------------------------------------");
} catch (Exception e) {
e.printStackTrace();
} finally {
//rs、ps和conn释放
}
<img src="029ca96e-e579-4d7d-b5d7-4eb88b1d88e1_files/084b64e4-5ad6-4e3f-ab13-8ab1ddeb1403.png" border="0" class="" style="font-size: 1rem;">
二、Apache—DBUtils框架
(一)、简介 commons-dbutils-1.4.jar
其方法都是静态的
1、commons-dbutils 是 Apache 组织提供的一个开源 JDBC工具类库,它是对JDBC的简单封装
,学习
成本极低
,并且使用dbutils能极大简化jdbc编码的工作量,同时也不会影响程序的性能。因此dbutils成为很
多不喜欢hibernate的公司的首选。
2、API介绍:
- org.apache.commons.dbutils.QueryRunner — 核心
- org.apache.commons.dbutils.ResultSetHandler
- 工具类
- org.apache.commons.dbutils.DbUtils、。
(二)、DbUtils类
1、提供如关闭连接、装载JDBC驱动程序等常规工作的工具类,里面的所有方法都是静态
的。主要方法如下:
- public static void close(…) throws java.sql.SQLException: DbUtils类提供了三个重载的关闭方法。这些方法检查所提供的参数是不是NULL,如果不是的话,它们就关闭Connection、Statement和ResultSet。
- public static void closeQuietly(…): 这一类方法不仅能在Connection、Statement和ResultSet为NULL情况下避免关闭,还能隐藏一些在程序中抛出的SQLException。
- public static void commitAndCloseQuietly(Connection conn): 用来提交连接,然后关闭连接,并且在关闭连接时不抛出SQL异常。
- public static boolean loadDriver(java.lang.String driverClassName):这一方装载并注册JDBC驱动程序,如果成功就返回true。使用该方法,你不需要捕捉这个异常ClassNotFoundException。
(三)、QueryRunner类 – 两行代码搞定增删改查
1、该类简单化了SQL查询,它与ResultSetHandler组合在一起使用可以完成大部分的数据库操作,能够
大大减少编码量。
2、QueryRunner类提供了两个构造方法:
- 默认的构造方法。
- 需要一个 javax.sql.DataSource 来作参数的构造方法。
3、QueryRunner() –需要控制事务时,使用这组方法
其中方法:Connection .setAutoCommit .commit .rollback
Connection conn = source.getConnection();
con.setAutoCommit(false);下面执行多条SQL语句,是基于一个连接,即一个事务
(1)、更新操作
- public int update(Connection conn, String sql)
- 执行 INSERT,UPDATE或DELETE SQL语句,不使用替换参数。
- public int update(Connection conn, String sql, Object… params)
- 执行 INSERT,UPDATE或DELETE SQL语句。
- public int update(Connection conn, String sql, Object param)
- 使用单个替换参数执行给定的INSERT,UPDATE或DELETE SQL语句。
(2)、查询操作
- public
T query(Connection conn, String sql, ResultSetHandler rsh, Object… params) - 执行 SELECT SQL语句,不使用替换参数。
- public
T query(Connection conn, String sql, ResultSetHandler rsh, Object… params) - 执行具有替换参数的SELECT SQL 语句。
- 执行具有替换参数的SELECT SQL 语句。
2、QueryRunner(DataSource ds) –不需要控制事务用这组方法
(1)、更新操作
- public int update(String sql)
- 执行给定的INSERT,UPDATE或DELETE SQL语句,不带任何替换参数。
- public int update(String sql, Object… params)
- 执行给定的INSERT,UPDATE或DELETE SQL语句。
- public int update(String sql, Object param)
- 使用单个替换参数执行给定的INSERT,UPDATE或DELETE SQL语句。
(2)、查询操作
- public
T query(String sql, ResultSetHandler rsh) - 执行给定的SELECT SQL语句,不带任何替换参数。
- public
T query(String sql, ResultSetHandler rsh, Object… params) - 执行给定的SELECT SQL查询语句并返回结果对象。
(四)、ResultSetHandler 实现类
该接口用于处理 java.sql.ResultSet,将数据按要求转换为另一种形式。
ResultSetHandler 接口提供了一个单独的方法:Object handle (java.sql.ResultSet .rs)
。
1、ResultSetHandler 接口的实现类
- ArrayHandler:把结果集中的第一行数据转成对象数组。
- ArrayListHandler:把结果集中的每一行数据都转成一个对象数组,再存放到List中。
- !!!!
BeanHandler
:将结果集中的第一行
数据封装到一个对应的JavaBean实例中。 - !!!!
BeanListHandler
:将结果集中的每一行数据都封装到一个对应的JavaBean实例中,存放到List里。 - MapHandler:将结果集中的第一行数据封装到一个Map里,key是列名,value就是对应的值。
- MapListHandler:将结果集中的每一行数据都封装到一个Map里,然后再存放到List
- ColumnListHandler:将结果集中某一列的数据存放到List中。
- KeyedHandler(name):将结果集中的每一行数据都封装到一个Map里(List
- !!!!!
ScalarHandler
:获取结果集中第一行数据指定列的值,常用来进行单值查询
2、练习:
package com.lmd.metadata;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.ArrayHandler;
import org.apache.commons.dbutils.handlers.ArrayListHandler;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ColumnListHandler;
import org.apache.commons.dbutils.handlers.KeyedHandler;
import org.apache.commons.dbutils.handlers.MapHandler;
import org.apache.commons.dbutils.handlers.MapListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import org.junit.Test;
import com.lmd.domain.Account;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class RSHandlerDemo {
//ArrayHandler:把结果集中的第一行数据转成对象数组
public void testArrayHandler() throws SQLException {
QueryRunner runner = new QueryRunner(new ComboPooledDataSource());
Object[] obj = runner.query("select * from account where money>?", new ArrayHandler(), 800);
for (int i = 0; i < obj.length; i++) {
System.out.print(i == obj.length-1 ? obj[i] : obj[i]+"--");
}
}//输出:1--a--999.0
//ArrayListHandler:把结果集中的每一行数据都转成一个对象数组,再存放到List中。
public void testArrayListHandler() throws SQLException {
QueryRunner runner = new QueryRunner(new ComboPooledDataSource());
List<Object[]> list = runner.query("select * from account where money>?", new ArrayListHandler(), 800);
for (int i = 0; i < list.size(); i++) {
Object[] obj = list.get(i);
for (int j = 0; j < obj.length; j++) {
System.out.print(j == obj.length-1 ? obj[j] : obj[j]+"--");
}
System.out.println();
}
}//输出:1--a--999.0 换行 2--b--888.0
//BeanHandler:将结果集中的第一行数据封装到一个对应的JavaBean实例中。
public void testBeanHandler() throws SQLException {
QueryRunner runner = new QueryRunner(new ComboPooledDataSource());
Account acc = runner.query("select * from account where money>?", new BeanHandler<Account>(Account.class), 800);
System.out.println(acc.getId()+"--"+acc.getName()+"--"+acc.getMoney());
}//输出:1--a--999.0
//BeanHandler:将结果集中的第一行数据封装到一个对应的JavaBean实例中。
public void testBeanListHandler() throws SQLException {
QueryRunner runner = new QueryRunner(new ComboPooledDataSource());
List<Account> list = runner.query("select * from account where money>?", new BeanListHandler<Account>(Account.class), 800);
for (int i = 0; i < list.size(); i++) {
Account acc = list.get(i);
System.out.println(acc.getId()+"--"+acc.getName()+"--"+acc.getMoney());
}
}//输出:1--a--999.0 换行 2--b--888.0
//MapHandler:将结果集中的第一行数据封装到一个Map里,key是列名,value就是对应的值。
public void testMapHandler() throws SQLException {
QueryRunner runner = new QueryRunner(new ComboPooledDataSource());
Map<String, Object> map = runner.query("select * from account where money>?", new MapHandler(), 800);
System.out.println(map );
}//输出:{money=999.0, name=a, id=1}
//MapListHandler:将结果集中的每一行数据都封装到一个Map里,然后再存放到List
public void testMapListHandler() throws SQLException {
QueryRunner runner = new QueryRunner(new ComboPooledDataSource());
List<Map<String, Object>> list = runner.query("select * from account where money>?", new MapListHandler(), 800);
for (Map<String, Object> map : list) {
System.out.println(map);
}
}//输出:{money=999.0, name=a, id=1}换行{money=888.0, name=b, id=2
//ColumnListHandler:将结果集中某一列的数据存放到List中。
public void testColumnListHandler() throws SQLException {
QueryRunner runner = new QueryRunner(new ComboPooledDataSource());
List<Object> list = runner.query("select * from account where money>?", new ColumnListHandler(2), 800);
for (Object obj : list) {
System.out.print(obj +" ");
}
}//输出:a b
//KeyedHandler(name):将结果集中的每一行数据都封装到一个Map里(List<Map>),
//再把这些map再存到一个map里,其key为指定的列。
public void testKeyedHandler() throws SQLException {
QueryRunner runner = new QueryRunner(new ComboPooledDataSource());
Map<Object, Map<String, Object>> map = runner.query("select * from account where money>?", new KeyedHandler("id"), 800);
System.out.println(map);
//输出:{1={money=999.0, name=a, id=1}, 2={money=888.0, name=b, id=2}}
System.out.println(map.get(2).get("name"));
}//输出: b
//ScalarHandler:获取结果集中第一行数据指定列的值,常用来进行单值查询
//默认第一行第一列
@Test
public void testScalarHandler() throws SQLException {
QueryRunner runner = new QueryRunner(new ComboPooledDataSource());
Long count = (Long) runner.query("select count(*) from account", new ScalarHandler());
System.out.println(count);
}//输出: 3
}
(五)、QueryRunner类更新和查询操作练习:
1、更新操作
//自己设计DbUtils框架
package com.lmd.dbutils;
import java.sql.Connection/ParameterMetaData;
import java.sql.PreparedStatement/SQLException;
import javax.sql.DataSource;
import org.apache.commons.dbutils.DbUtils;
public class MyQueryRunner {
private DataSource source = null;
public MyQueryRunner(){ }
public MyQueryRunner(DataSource source){
this.source = source;
}
public int update(String sql, Object... params)throws SQLException {
Connection conn = source.getConnection();
PreparedStatement ps = conn.prepareStatement(sql);
//--获取参数元数据
ParameterMetaData metaData = ps.getParameterMetaData();
int count = metaData.getParameterCount();
//--循环设置参数值
for (int i = 1; i <= count; i++) {
ps.setObject(i, params[i-1]);
}
//--执行update操作
int num = ps.executeUpdate();
DbUtils.closeQuietly(conn, ps, null);
return num;
}
}
- 实现更新操作:
package com.lmd.dbutils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.apache.commons.dbutils.DbUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.junit.Test;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class DbUtilsUpdate {
public void delete() throws SQLException {
MyQueryRunner runner = new MyQueryRunner(new ComboPooledDataSource());
runner.update("delete from account where id=?", 7);
}
public void add() throws SQLException {
MyQueryRunner runner = new MyQueryRunner(new ComboPooledDataSource());
runner.update("insert into account values(null,?,?)", "d", 1000);
}
/**
* MyDbUtils实现增删改功能
* @throws SQLException
*/
/@Test
public void update1() throws SQLException {
MyQueryRunner runner = new MyQueryRunner(new ComboPooledDataSource());
runner.update("update account set money=? where name=?", 777, "c");
}
/**
* DbUtils实现增删改功能
* @throws SQLException
*/
public void update2() throws SQLException {
QueryRunner runner = new QueryRunner(new ComboPooledDataSource());
runner.update("update account set money=? where name=?", 888, "b");
}
/**
* 古老方法实现增删改功能
* --在进行增删改操作时,每次不一样的时sql语句和其中的参数
*/
public void update3() {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
ComboPooledDataSource source = new ComboPooledDataSource();
try {
conn = source.getConnection();
ps = conn.prepareStatement("update account set money=? where name=?");
ps.setDouble(1, 999);
ps.setString(2, "a");
ps.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
DbUtils.closeQuietly(conn, ps, rs);
}
}
}
2、查询操作
- 新增一个接口:
MyResultSetHandler
package com.lmd.dbutils;
import java.sql.ResultSet;
import java.sql.SQLException;
public interface MyResultSetHandler<T> {
T handle(ResultSet rs) throws SQLException;
}
- 在自己设计DbUtils框架MyQueryRunner.java中新增:
//利用接口实现传进去
public <T> T query(String sql, MyResultSetHandler<T> rsh, Object... params) throws SQLException{
Connection conn = source.getConnection();
PreparedStatement ps = conn.prepareStatement(sql);
//--获取参数元数据
ParameterMetaData metaData = ps.getParameterMetaData();
int count = metaData.getParameterCount();
//--循环设置参数值
for (int i = 1; i <= count; i++) {
ps.setObject(i, params[i-1]);
}
//--执行query操作获取结果集
ResultSet rs = ps.executeQuery();
//--`回调`处理结果集的逻辑
T t = rsh.handle(rs);
DbUtils.closeQuietly(conn, ps, rs);
return t;
}
- 查询操作:
package com.lmd.dbutils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.dbutils.DbUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.ResultSetHandler;
import org.junit.Test;
import com.lmd.domain.Account;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import com.mysql.fabric.xmlrpc.base.Array;
public class DbUtilsQuery {
/**
* MyDbUtils实现查询功能
* @throws SQLException
*
* 回调函数:当方法a调用方法b时,而方法b在执行的过程中,
* 其中一些逻辑需要由方法a告知,此时需要方法a在调用
* 方法b时将逻辑传入,而java中是不允许传递java源代码的,
* 此时可以使用回调机制。所谓回调,就是方法a和方法b约定
* 一个接口,在这个接口中定义一个方法,这个方法通常叫handler方法,
* a调用b时,传入此接口实现,其中利用handler方法,将逻辑传入,
* 方法b在执行过程中需要执行a传入的逻辑时,调用接口实现的handler方法
* 即可,此时a调用b时,b回来调用的a传入的逻辑,所以此过程叫回调
*/
@Test
public void select1() throws SQLException {
MyQueryRunner runner = new MyQueryRunner(new ComboPooledDataSource());
List<Account> list = runner.query("select * from account where money>?"
, new MyResultSetHandler<List<Account>>(){
@Override
public List<Account> handle(ResultSet rs) throws SQLException {
List<Account> list = new ArrayList<Account>();
while (rs.next()) {
Account account = new Account();
account.setId(rs.getInt("id"));
account.setName(rs.getString("name"));
account.setMoney(rs.getDouble("money"));
list.add(account);
}
return list;
}
}, 800);
for (int i = 0; i < list.size(); i++) {
Account acc = list.get(i);
System.out.println(acc.getId()+"--"+acc.getName()+"--"+acc.getMoney());
}
}
/**
* DbUtils实现查询功能
* @throws SQLException
*/
public void select2() throws SQLException {
QueryRunner runner = new QueryRunner(new ComboPooledDataSource());
List<Account> list = runner.query("select * from account where money>?"
, new ResultSetHandler<List<Account>>(){
@Override
public List<Account> handle(ResultSet rs) throws SQLException {
List<Account> list = new ArrayList<Account>();
while (rs.next()) {
Account account = new Account();
account.setId(rs.getInt("id"));
account.setName(rs.getString("name"));
account.setMoney(rs.getDouble("money"));
list.add(account);
}
return list;
}
}, 800);
for (int i = 0; i < list.size(); i++) {
Account acc = list.get(i);
System.out.println(acc.getId()+"--"+acc.getName()+"--"+acc.getMoney());
}
}
/**
* 古老方法实现查询功能
* --在进行查询操作时,每次不一样的是sql语句、sql中的参数、结果集的处理
*/
public void select3() {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
ComboPooledDataSource source = new ComboPooledDataSource();
List<Account> list = new ArrayList<Account>();
try {
conn = source.getConnection();
ps = conn.prepareStatement("select * from account where money>?");
ps.setDouble(1, 800);
rs = ps.executeQuery();
while (rs.next()) {
Account account = new Account();
account.setId(rs.getInt("id"));
account.setName(rs.getString("name"));
account.setMoney(rs.getDouble("money"));
list.add(account);
}
for (int i = 0; i < list.size(); i++) {
Account acc = list.get(i);
System.out.println(acc.getId()+"--"+acc.getName()+"--"+acc.getMoney());
}
//1--a--999.0
//2--b--888.0
} catch (Exception e) {
e.printStackTrace();
} finally {
DbUtils.closeQuietly(conn, ps, rs);
}
}
}
(六)、其他知识点:
1、回调函数
- 所谓回调,就是客户程序C调用服务程序S中的某个函数A,然后S又在某个时候反过来调用C中的某个函数B,对于C来说,这个B便叫做回调函数。例如Win32下的窗口过程函数就是一个典型的回调函数。一般说来,C不会自己调用B,C提供B的目的就是让S来调用它,而且是C不得不提供。由于S并不知道C提供的B姓甚名谁,所以S会约定B的接口规范(函数原型),然后由C提前通过S的一个函数R告诉S自己将要使用B函数,这个过程称为回调函数的注册,R称为注册函数。Web Service以及Java的RMI都用到回调机制,可以访问远程服务器程序。
下面举个通俗的例子
:
某天,我打电话向你请教问题,当然是个难题,^_^,你一时想不出解决方法,我又不能拿着电话在那里傻等,于是我们约定:等你想出办法后打手机通知我,这样,我就挂掉电话办其它事情去了。过了XX分钟,我的手机响了,你兴高采烈的说问题已经搞定,应该如此这般处理。故事到此结束。这个例子说明了“异步+回调”的编程模式。其中,你后来打手机告诉我结果便是一个“回调”过程;我的手机号码必须在以前告诉你,这便是注册回调函数;我的手机号码应该有效并且手机能够接收到你的呼叫,这是回调函数必须符合接口规范。通过上面个人感觉到回调更多的应用就是结合异步。比如:Ajax中js通过组件和服务器的异步通信。
2、例子:
- 程序员A写了一段程序(程序a),其中预留有回调函数接口,并封装好了该程序。程序员B要让a调用自己的程序b中的一个方法,于是,他通过a中的接口回调自己b中的方法。目的达到。在C/C++中,要用回调函数,被掉函数需要告诉调用者自己的指针地址,但在JAVA中没有指针,怎么办?我们可以通过接口(interface)和类来实现回调函数的功能。
- 假设我是程序员A,以下是我的程序a:
public class Caller {
public MyCallInterface mc;
public void setCallfuc(MyCallInterface mc) {
this.mc= mc;
}
public void call(){
this.mc.method();
}
}
* 我还需要定义一个接口,以便程序员B根据我的定义编写程序实现接口。
public interface MyCallInterface {
public void method();
}
* 于是,程序员B只需要实现这个接口就能达到回调的目的了:
public class B implements MyCallInterface {
public void method() {
System.out.println("回调");
}
public static void main(String args[]) {
Caller call = new Caller();
call.setCallfuc(new B());
call.call();
}
}
3、例子:
package com.lmd.test;
//接口中定义比较大小的方法
interface IntCompare{
public int compare(int a, int b) ;
}
class AscendOrder implements IntCompare{
@Override
public int compare(int a, int b) {
return a>b ? 1 : (a<b ? -1 : 0);
}
}
class DescendOrder implements IntCompare{
@Override
public int compare(int a, int b) {
return a>b ? -1 : (a<b ? 1 : 0);
}
}
public class CallbackFunction {
public static void insertSort(int[] arr, IntCompare cmp) {
if (arr != null) {
for (int i = 1; i < arr.length; i++) {
int temp = arr[i], j=i;
if (cmp.compare(arr[j-1], temp) == 1) {
while (j >= 1 && cmp.compare(arr[j-1], temp)==1) {
arr[j] = arr[j-1];
j--;
}
}
arr[j] = temp;
}
}
}
public static String printSort(int[] arr) {
String s = "";
for (int i = 0; i < arr.length; i++) {
s += arr[i] + " ";
}
return s;
}
public static void main(String[] args) {
int[] arr1 = {12, 3, -2, 33, 24};
insertSort(arr1, new AscendOrder());
System.out.println("升序:" + printSort(arr1));
int[] arr2 = {12, 3, -2, 33, 24};
insertSort(arr2, new DescendOrder());
System.out.println("降序:" + printSort(arr2));
}
}
分页技术
- 物理分页
- 在sql查询时,从数据库只检索分页需要的数据
- 通常不同的数据库有着不同的物理分页语句
- mysql物理分页,采用limit关键字
- 例如:检索11-20条 select * from user limit 10,10 ;
- 在sql查询时,先从数据库检索出所有数据的结果集
- 在程序内,通过逻辑语句获得分页需要的的数据
- 例如: 检索11-20条 userList.subList(10,20);
(七)、分页技术概述
1、物理分页 – 常用,其优缺点与逻辑分页反之
- 在sql查询时,从数据库只检索分页需要的数据
- 通常不同的数据库有着不同的物理分页语句
- mysql物理分页,采用limit关键字
- 例如:检索11-20条 select * from user limit 10,10 ;
2、逻辑分页 – 数据少且很少变化的数据库,已不常用。例如:国家、省、县
- 在sql查询时,先从数据库检索出所有数据的结果集
- 在程序内,通过逻辑语句获得分页需要的的数据
- 例如: 检索11-20条 userList.subList(10,20);
- 优点:存在list中,仅查询一次数据库
- 缺点:数据过大时,存在内存中耗内存;数据库发生变化,内存中反映不出来
三、案例——客户管理系统:体验基于数据库javaweb的增删改查
(一)客户管理系统
- 1、实现功能:添加客户、查询客户列表、修改客户信息、删除客户、条件查询客户信息、分页查询客户
- 2、javaee的经典三层架构–工厂类实现解耦
- 3、使用技术:jsp+servlet+service+dao+jdbc+mysql+c3p0+dbutils
- 4、使用包:
- com.lmd.web
- com.lmd .service
- com.lmd.dao
- com.lmd.domain
- com.lmd.util
- com.lmd.exception
- com.lmd.factory
- 5、使用第三方包: JSTL、* mysql驱动、beanutils、c3p0包、dbutils包
- 6、配置文件:
- confing.properties src下
- c3p0-config.xml src下
- 7、设计数据库:
create table customer (
id int primary key auto_increment,
name varchar(20),
gender varchar(10),
birthday date,
cellphone varchar(20),
email varchar(40),
preference varchar(100),
type varchar(40),
description varchar(255)
);
字段名 | 说明 | 类型 |
---|---|---|
id | 编号 | int |
name | 客户姓名 | varchar(20) |
gender | 性别 | varchar(10) |
birthday | 生日 | date |
cellphone | 手机 | varchar(20) |
电子邮件 | varchar(40) | |
preference | 客户爱好 | varchar(100) |
type | 客户类型 | varchar(40) |
description | 备注 | varchar(255) |
- 8、工厂类实现解耦:
- 要有接口(CustDao、CustService)、要有配置文件(confing.properties )、要有工厂类。
- CustDaoImp和CustServiceImp两个实现类 设置了一个通用的工厂类。
CustDaoImp=com.lmd.dao.CustDaoImp //service层和Dao层的解耦
CustService=com.lmd.service.CustServiceImp //web层(servlet)和service层的解耦
按照需求从前向后开发
新建一个JavaBean类-Cust.java,设计一个工厂类BasicFactory.java
9、添加客户功能实现:
- –>addCust.jsp–>AddCustServlet.java(内含需要service层处理的方法void addCust(Cust cust);)
- –>CustService.java(接口,业务逻辑层,内含需要Dao层具体处理的方法:Cust findUserByName(String name);和void addCust(Cust cust);)
- –>CustServiceImp.java(接口实现类)
- –>CustDao.java(接口,数据访问层)–>CustDaoImp.java(接口实现类,其中设计一个工具类DaoUtils.java,获取数据源和连接池)
index.jsp 主页 提供<添加客户>超链接
- –>addCust.jsp 添加客户的页面,提供表单允许输入客户信息
- –>AddCustServlet 1.封装数据/校验数据 2.调用Service层添加客户的方法 3.重定向回到主页 –>Service 提供添加客户的方法,检查客户名是否已经存在,如果存在提示,如果不存在则调用dao增加客户方法
- –> Dao 根据用户名查找用户 添加客户
- 10、查询客户列表功能实现:
- –>AddCustServlet.java(内含需要service层处理的方法List
getAllCust();) - –>CustService.java(接口,业务逻辑层)
- –>CustServiceImp.java(接口实现类,内含需要Dao层具体处理的方法:List
getAllCust();) - –>CustDao.java(接口,数据访问层)–>CustDaoImp.java(接口实现类)
- –> listCust.jsp
- –>AddCustServlet.java(内含需要service层处理的方法List
index.jsp 页面中 提供<查询客户列表>超链接
- –>ListCustServlet 调用Service中查询所有客户的方法 查到数据后,将查到的数据存入request域中,请求转发listCust.jsp页面展示
- –>Service 调用dao中查询所有客户
- –>dao中查询所有客户
- –>listCust.jsp 页面,遍历list展示所有客户
11、修改客户信息 (查询/修改)功能实现:
- –>listCust.jsp(增加<修改>超链接,访问CustInfoServlet.java)
- –>UpdateCustServlet.java(内含需要service层处理的方法void updateCust(Cust cust);)
- –>CustService.java(接口,业务逻辑层)
- –>CustServiceImp.java(接口实现类,内含需要Dao层具体处理的方法void updateCust(Cust cust);)
- –>CustDao.java(接口,数据访问层)–>CustDaoImp.java(接口实现类)
- –> updateCust.jsp
在客户信息列表页面,每一条记录后面都有一个<修改>超链接
- –>CustInfoServlet 调用Service中的方法 找到当前客户信息 存入request域后带到updateCust.jsp页面显示
- –>updateCust.jsp 显示客户信息,并允许修改
- –>UpdateCustServlet 封装数据/调用Service中修改数据的方法
- –>Service 修改客户信息的方法,调用dao中的方法进行修改
- –>Dao 提供修改客户信息的方法
12、删除客户功能实现:
- –>listCust.jsp(增加<删除>超链接,访问DelCustServlet.java)
- –>DelCustServlet.java(内含需要service层处理的方法void delCustById(String id);)
- –>CustService.java(接口,业务逻辑层)
- –>CustServiceImp.java(接口实现类,内含需要Dao层具体处理的方法void delCustById(String id);)
- –>CustDao.java(接口,数据访问层)–>CustDaoImp.java(接口实现类)
在客户信息列表页面,每一条记录后面都有一个<删除>超链接
- –>DelCustServlet 获取要删除的客户id,调用Service中删除客户的方法,请求转发到客户列表页面
- –>Service 删除客户的方法 调用dao中对应方法
- –>Dao中根据id删除客户的方法
13、批量删除客户功能实现:
- –>listCust.jsp(增加“checkbox”复选框,访问BatchDelCustServlet.java)
- –>BatchDelCustServlet.java(内含需要service层处理的方法void batchDel(String[] ids);)
- –>CustService.java(接口,业务逻辑层)
- –>CustServiceImp.java(接口实现类,内含需要Dao层具体处理的方法void delCustByIdWithTrans(Connection conn, String id) throws SQLException;)
- –>CustDao.java(接口,数据访问层)–>CustDaoImp.java(接口实现类)
listCust.jsp 在客户信息列表页面的每一条记录之前都有一个复选框,选中后,可以删除
- –>BatchDelCustServlet 获取所有要删除的客户的id,调用Service中批量删除客户的方法做删除操作
- –>Service中提供批量删除客户的方法,事务的管理
- –>dao中删除客户的方法
14、条件查询客户信息功能实现:
- –>listCust.jsp(设置条件查询表单,访问FindCustByCondServlet.java)
- –>FindCustByCondServlet.java(内含需要service层处理的方法List
findCustByCond(Cust cust);) - –>CustService.java(接口,业务逻辑层)
- –>CustServiceImp.java(接口实现类,内含需要Dao层具体处理的方法List
findCustByCond(Cust cust);) - –>CustDao.java(接口,数据访问层)–>CustDaoImp.java(接口实现类)
listCust.jsp 在客户信息列表页面之前,提供一个条件查询的表单,允许通过用户名、性别、客户类型进项条件查询
- –>FindCustByCondServlet 将条件封装在bean中调用service中条件查询客户的方法,将查询到的所有客户信息存在request域带到listCust.jsp界面显示
- –>Service中提供根据条件查询客户的方法
- –>dao中条件查询客户的方法
15、分页查询客户信息功能实现:
- –>index.jsp(增加<分页查询客户信息>超链接,访问PageCustServlet.java)添加一个bean类Page.java
- –>PageCustServlet.java(内含需要service层处理的方法Page pageCust(int thispage, int rowperpaper);)
- –>CustService.java(接口,业务逻辑层)
- –>CustServiceImp.java(接口实现类,内含需要Dao层具体处理的方法int getCountRow();和List
getCustByPage(int from, int count);) - –>CustDao.java(接口,数据访问层)–>CustDaoImp.java(接口实现类)
- index.jsp上 listCust.jsp上程序过多,重新设计一个页面界面上设计:共xxx条记录 共xx页 首页 上一页 1 2 3 4 5 下一页 尾页
- –>listCust.jsp(增加<分页查询客户信息>超链接,访问PageCustServlet.java)
- –>PageCustServlet.java(获取要访问的页码以及每页显示多少条记录,调用serviece中分页查询客户的方法查询客户,存入request域带到pageList.jsp页面进行展示)
- –>Service中提供根据分页查询客户的方法(Page pageCust(int thispage, int rowperpaper);)
- –>dao中分页查询客户的方法(int getCountRow();和List
getCustByPage(int from, int count);) - if(总页码<=5){
- 显示所有页码;
- } else{
- if(当前页码<=3){
- 显示1到5;
- } else if(当前页码>=总页码-2){
- 显示总页码-4到总页码;
- } else {
- 显示当前页码-2到当前页码+2;
- }
- }
- 16、代码程序:
- c3p0-config.xml
<?xml version="1.0" encoding="utf-8"?>
<c3p0-config>
<default-config>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql:///day12?serverTimezone=UTC</property>(时区异常问题)
<property name="user">root</property>
<property name="password">666666</property>
</default-config>
</c3p0-config>
* `index.jsp`开始界面
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>客户管理系统</title>
</head>
<body>
<h1>客户管理系统_主页</h1>
<a href="${pageContext.request.contextPath}/addCust.jsp">添加客户</a>
<a href="${pageContext.request.contextPath}/ListCustServlet">查询客户列表</a>
<a href="${pageContext.request.contextPath}/ListCustServlet">修改客户信息</a>
<a href="${pageContext.request.contextPath}/ListCustServlet">删除客户</a>
<a href="${pageContext.request.contextPath}/PageCustServlet?thispage=1">分页查询客户</a>
</body>
</html>
* `web.xml` 配置错误提示界面
<error-page>
<error-code>500</error-code>
<location>/error/500.jsp</location>
</error-page>
<error-page>
<error-code>404</error-code>
<location>/error/404.jsp</location>
</error-page>
* `500/404.xml` 错误提示界面
<body>
服务器出错了~~~~~~出错原因:${pageContext.exception.message }
</body>
<body>
资源被搬走了~~~~~~出错原因:${pageContext.exception.message }
</body>
* `Cust.java` Dao类,这一般是指java中MVC架构中的model的概念,主要是访问数据库的一些方法。domain包下
package com.lmd.domain;
import java.io.Serializable;
import java.sql.Date;
public class Cust implements Serializable {
private int id;
private String name;
private String gender;
private Date birthday;
private String cellphone;
private String email;
private String preference;
private String type;
private String description;
//getter和setter
}
* `Page.java` Dao类分页查询使用 domain包下
package com.lmd.domain;
import java.util.List;
public class Page {
private int thispage;
private int rowperpage;
private int countrow;
private int countpage;
private int firstpage;
private int lastpage;
private int prevpage;
private int nextpage;
private List<Cust> custList;
//getter和setter
}
BasicFactory.java
工厂类解耦,需要接口和实现类、配置文件(confing.properties )
package com.lmd.factory;
import java.io.FileReader;
import java.util.Properties;
import com.lmd.dao.CustDao;
public class BasicFactory {
private static BasicFactory factory = new BasicFactory();
private static Properties prop = null;
private BasicFactory(){
}
public static BasicFactory getFactory() {
return factory;
}
static{
try {
prop = new Properties();
prop.load(new FileReader(BasicFactory.class
.getClassLoader().getResource("config.properties").getPath()));
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
public <T> T getInstance(Class<T> clazz) {//CustDao.class:com.lmd.dao.CustDaoImp
try {
String cName = clazz.getSimpleName();//"CustDao" 接口找实现
String cImplName = prop.getProperty(cName);//com.lmd.dao.CustDaoImp
return (T) Class.forName(cImplName).newInstance();
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
* `CustService.java` service包下 接口 业务逻辑层
package com.lmd.service;
import java.util.List;
import com.lmd.domain.Cust;
import com.lmd.domain.Page;
public interface CustService {
/**
* 添加客户
* @param cust 封装了用户信息的bean
*/
void addCust(Cust cust);
/**
* 查询所有客户信息
* @return
*/
List<Cust> getAllCust();
/**
* 根据id查找客户信息
* @param id 客户id
* @return 查找到的客户信息,如果找不到返回null;
*/
Cust findCustById(String id);
/**
* 修改客户信息的方法
* @param cust 封装了最新客户信息的方法
*/
void updateCust(Cust cust);
/**
* 根据id删除客户信息
* @param id 删除客户的id
*/
void delCustById(String id);
/**
* 批量删除客户
* @param ids 所有客户id组成的字符串数组
*/
void batchDel(String[] ids);
/**
* 根据条件查询客户信息
* @param cust 封装了查询条件的bean,有客户名/客户性别/客户类型
* @return 符合条件的客户集合
*/
List<Cust> findCustByCond(Cust cust);
/**
* 分页查询客户信息
* @param thispage 查询的页码
* @param rowperpage 每页的记录数
* @return 当前页的所有信息
*/
Page pageCust(int thispage, int rowperpaper);
}
* `CustServiceImp.java` service包下 实现类 内含需要Dao层具体实现的方法
package com.lmd.service;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import org.apache.commons.dbutils.DbUtils;
import com.lmd.dao.CustDao;
import com.lmd.domain.Cust;
import com.lmd.domain.Page;
import com.lmd.factory.BasicFactory;
import com.lmd.util.DaoUtils;
public class CustServiceImp implements CustService {
//CustDao dao = (CustDao) BasicFactory.getFactory().getInstance("CustDao");
CustDao dao = BasicFactory.getFactory().getInstance(CustDao.class);
//CustService service = BasicFactory.getFactory().getInstance(CustService.class);
@Override
public void addCust(Cust cust) {
//1.检查客户名是否已经存在
if (dao.findUserByName(cust.getName()) != null) {
throw new RuntimeException("用户名已经存在!!!");
}
//2.调用Dao中的方法增加用户,如果存在提示,如果不存在则调用dao增加客户方法
dao.addCust(cust);
}
@Override
public List<Cust> getAllCust() {
return dao.getAllCust();
}
@Override
public Cust findCustById(String id) {
return dao.findCustById(id);
}
@Override
public void updateCust(Cust cust) {
dao.updateCust(cust);
}
@Override
public void delCustById(String id) {
dao.delCustById(id);
}
@Override
public void batchDel(String[] ids) {
//为了实现事务,使用了Connection,其是Dao层的东西
//产生耦合,不好,后面会改进
Connection conn = DaoUtils.getConn();
try {
conn.setAutoCommit(false);
for (String id : ids) {
dao.delCustByIdWithTrans(conn,id);
}
//int i = 1/0;//回滚测试
DbUtils.commitAndCloseQuietly(conn);
} catch (Exception e) {
DbUtils.rollbackAndCloseQuietly(conn);
e.printStackTrace();
throw new RuntimeException(e);
}
}
@Override
public List<Cust> findCustByCond(Cust cust) {
return dao.findCustByCond(cust);
}
@Override
public Page pageCust(int thispage, int rowperpage) {
Page page = new Page();
//--当前页
page.setThispage(thispage);
//--每页记录数
page.setRowperpage(rowperpage);
//--总记录数
int countrow = dao.getCountRow();
page.setCountrow(countrow);
//--总页数
int countpage = countrow/rowperpage+(countrow%rowperpage==0?0:1);
page.setCountpage(countpage);
//--首页
page.setFirstpage(1);
//--尾页
page.setLastpage(countpage);
//--上一页
page.setPrevpage(thispage==1?1:thispage-1);
//--下一页
page.setNextpage(thispage==countpage?countpage:thispage+1);
//--当前页数据
List<Cust> list = dao.getCustByPage((thispage-1)*rowperpage,rowperpage);
page.setCustList(list);
return page;
}
}
* `DaoUtils.java` utils包下 访问数据源
package com.lmd.util;
import java.sql.Connection;
import javax.sql.DataSource;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class DaoUtils {
private static DataSource source = new ComboPooledDataSource();
private DaoUtils(){
}
public static DataSource getSource(){
return source;
}
public static Connection getConn(){
try {
return source.getConnection();
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
* `CustDao.java` dao包下 接口 数据访问层(访问数据库)
package com.lmd.dao;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import com.lmd.domain.Cust;
import com.lmd.domain.Page;
public interface CustDao {
/**
* 检查客户名是否已经存在
* @param name 客户名
* @return 找不到,返回null
*/
Cust findUserByName(String name);
/**
* 添加客户
* @param cust
*/
void addCust(Cust cust);
/**
* 查询所有客户信息组成的集合
* @return 封装了所有客户信息的集合,若没有返回null
*/
List<Cust> getAllCust();
/**
* 根据客户id查找客户信息
* @param id 客户id
* @return 最新客户信息bean
*/
Cust findCustById(String id);
/**
* 修改客户信息
* @param cust
* @return 最新客户信息bean
*/
void updateCust(Cust cust);
/**
* 根据id删除客户信息
* @param id 删除客户的id
*/
void delCustById(String id);
/**
* 根据id删除客户信息,并管理事务
* @param conn
* @param id 删除客户的id
* @throws SQLException
*/
void delCustByIdWithTrans(Connection conn, String id) throws SQLException;
/**
* 根据条件查询客户信息
* @param cust 封装了查询条件的bean,有客户名/客户性别/客户类型
* @return 符合条件的客户集合
*/
List<Cust> findCustByCond(Cust cust);
/**
* 查询数据库有多少条记录
* @return 记录数
*/
int getCountRow();
/**
* 查询指定记录后多少条记录
* @param from 从哪条记录后取
* @param count 取的记录数
* @return
*/
List<Cust> getCustByPage(int from, int count);
}
* `CustDaoImp.java` Dao层的接口实现类 (省写验证输入项是否正确或是否为空的方法)
package com.lmd.dao;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import com.lmd.domain.Cust;
import com.lmd.util.DaoUtils;
public class CustDaoImp implements CustDao{
@Override
public Cust findUserByName(String name) {
try {
String sql = "select * from customer where name=?";
QueryRunner runner = new QueryRunner(DaoUtils.getSource());
return runner.query(sql, new BeanHandler<Cust>(Cust.class), name);
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
@Override
public void addCust(Cust cust) {
String sql = "insert into customer values (null,?,?,?,?,?,?,?,?)";
try {
QueryRunner runner = new QueryRunner(DaoUtils.getSource());
runner.update(sql, cust.getName(), cust.getGender(), cust.getBirthday()
,cust.getCellphone(), cust.getEmail(), cust.getPreference()
,cust.getType(), cust.getDescription());
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
@Override
public List<Cust> getAllCust() {
String sql = "select * from customer";
try{
QueryRunner runner = new QueryRunner(DaoUtils.getSource());
return runner.query(sql, new BeanListHandler<Cust>(Cust.class));
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
@Override
public Cust findCustById(String id) {
try {
String sql = "select * from customer where id=?";
QueryRunner runner = new QueryRunner(DaoUtils.getSource());
return runner.query(sql, new BeanHandler<Cust>(Cust.class), id);
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
@Override
public void updateCust(Cust cust) {
try {
String sql = "update customer set name=?,gender=?,birthday=?,cellphone=?"
+ ",email=?,preference=?,type=?,description=? where id=?";
QueryRunner runner = new QueryRunner(DaoUtils.getSource());
runner.update(sql, cust.getName(), cust.getGender(), cust.getBirthday()
,cust.getCellphone(), cust.getEmail(), cust.getPreference()
,cust.getType(), cust.getDescription(),cust.getId());
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
@Override
public void delCustById(String id) {
try {
String sql = "delete from customer where id=?";
QueryRunner runner = new QueryRunner(DaoUtils.getSource());
runner.update(sql,id);
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
@Override
public void delCustByIdWithTrans(Connection conn, String id) throws SQLException {
String sql = "delete from customer where id=?";
QueryRunner runner = new QueryRunner();
runner.update(conn,sql,id);
}
@Override
public List<Cust> findCustByCond(Cust cust) {
String sql = "select * from customer where 1=1";
List<Object> list = new ArrayList<Object>();
if (cust.getName()!=null && !"".equals(cust.getName())) {
sql += " and name like ?";
list.add("%"+cust.getName()+"%");
}
if (cust.getGender()!=null && !"".equals(cust.getGender())) {
sql += " and gender=?";
list.add(cust.getGender());
}
if (cust.getType()!=null && !"".equals(cust.getType())) {
sql += " and type=?";
list.add(cust.getType());
}
try {
QueryRunner runner = new QueryRunner(DaoUtils.getSource());
if (list.size()<=0) {
return runner.query(sql, new BeanListHandler<Cust>(Cust.class));
}
return runner.query(sql, new BeanListHandler<Cust>(Cust.class), list.toArray());
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
@Override
public int getCountRow() {
String sql = "select count(*) from customer";
try {
QueryRunner runner = new QueryRunner(DaoUtils.getSource());
return ((Long) runner.query(sql, new ScalarHandler())).intValue();
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
@Override
public List<Cust> getCustByPage(int from, int count) {
String sql = "select * from customer limit ?,?";
try {
QueryRunner runner = new QueryRunner(DaoUtils.getSource());
return runner.query(sql, new BeanListHandler<Cust>(Cust.class), from, count);
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
(1)、添加用户
* `addCust.jsp` 添加用户界面
<body style="text-align: center;">
<h1>客户管理系统_添加客户</h1>
<form action="${pageContext.request.contextPath }/AddCustServlet" method="post">
<table align="center" border="1">
<tr>
<td>客户姓名</td>
<td><input type="text" name="name" /></td>
</tr>
<tr>
<td>客户性别</td>
<td>
<input type="radio" name="gender" value="男" checked="checked" />男
<input type="radio" name="gender" value="女" />女
</td>
</tr>
<tr>
<td>客户生日</td>
<td><input type="text" name="birthday" /></td>
</tr>
<tr>
<td>手机号码</td>
<td><input type="text" name="cellphone" /></td>
</tr>
<tr>
<td>电子邮件</td>
<td><input type="text" name="email" /></td>
</tr>
<tr>
<td>客户爱好</td>
<td>
<input type="checkbox" name="preference" value="篮球" />篮球(钢琴、舞蹈)
</td>
</tr>
<tr>
<td>客户类型</td>
<td>
<select name="type">
<option value="钻石用户">钻石用户</option>(白金、白银、青铜等等)
</select>
</td>
</tr>
<tr>
<td>备注信息</td>
<td><textarea rows="6" cols="30" name = "description"></textarea></td>
</tr>
<tr>
<td colspan="2">
<input type="submit" value="添加用户" />
</td>
</tr>
</table>
</form>
</body>
* `AddCustServlet.java 添加用户实现
package com.lmd.web;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.beanutils.BeanUtils;
import com.lmd.domain.Cust;
import com.lmd.factory.BasicFactory;
import com.lmd.service.CustService;
/**
* Servlet implementation class AddCustServlet
*/
@WebServlet("/AddCustServlet")
public class AddCustServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
response.setContentType("text/html; charset=UTF-8");
CustService service = BasicFactory.getFactory().getInstance(CustService.class);
// 1.封装数据,省写校验数据
Cust cust = new Cust();
try {
BeanUtils.populate(cust, request.getParameterMap());
//单独处理爱好
String[] prfs = request.getParameterValues("preference");
StringBuffer buffer = new StringBuffer();
for (String pref : prfs) {
buffer.append(pref+",");
}
String pref = buffer.substring(0, buffer.length()-1);
cust.setPreference(pref);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
// 2.调用Service层添加客户的方法
service.addCust(cust);//Ctrl+1添加方法
//3.重定向回到主页
response.sendRedirect(request.getContextPath()+"/index.jsp");
}
}
(2)、查询用户列表、修改、删除及条件查询
* `listCust.jsp` 显示所有用户信息、修改客户信息、条件查询客户信息、删除客户 界面
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<script type="text/javascript">
function checkAll(allC){
var otherChs = document.getElementsByName("delId");
for(var i=0; i<otherChs.length; i++){
otherChs[i].checked = allC.checked;
}
}
</script>
</head>
<body style="text-align: center;">
<h1>客户管理系统_客户列表页面</h1>
<form action="${pageContext.request.contextPath }/FindCustByCondServlet" method="post"">
客户姓名:<input type="text" name="name" value="${param.name }"/>
客户性别:<input type="radio" name="gender" value="男"
<c:if test="${param.gender=='男'}">checked='checked'</c:if>
/>男
<input type="radio" name="gender" value="女"
<c:if test="${param.gender=='女'}">checked='checked'</c:if>
/>女
<input type="radio" name="gender" value="" />无
客户类型:<select name="type">
<option value=""></option>
<option value="钻石用户"
<c:if test="${param.type=='钻石用户' }">
selected='selected'
</c:if>
>钻石用户</option>
<option value="白金用户"
<c:if test="${param.type=='白金用户' }">
selected='selected'
</c:if>
>白金用户</option>
<option value="黄金用户"
<c:if test="${param.type=='黄金用户' }">
selected='selected'
</c:if>
>黄金用户</option>
<option value="白银用户"
<c:if test="${param.type=='白银用户' }">
selected='selected'
</c:if>
>白银用户</option>
<option value="青铜用户"
<c:if test="${param.type=='青铜用户' }">
selected='selected'
</c:if>
>青铜用户</option>
<option value="普通用户"
<c:if test="${cust.type=='普通用户' }">
selected='selected'
</c:if>
>普通用户</option>
</select>
<input type="submit" value="条件查询用户" />
</form>
<form action="${pageContext.request.contextPath }/BatchDelCustServlet" method="post">
<table border="1" width="100%" align="center">
<tr>
<th><input type="checkbox" onchange="checkAll(this)" />全选</th>
<th>客户姓名</th>
<th>客户性别</th>
<th>出生日期</th>
<th>手机号码</th>
<th>电子邮件</th>
<th>客户爱好</th>
<th>客户类型</th>
<th>描述信息</th>
<th>修改</th>
<th>删除</th>
</tr>
<c:forEach items="${requestScope.list }" var="cust">
<tr>
<!-- 使用标签解决引导入侵,不让字符转义 -->
<td><input type="checkbox" name="delId" value="${cust.id }" /></td>
<td><c:out value="${cust.name }"/></td>
<td><c:out value="${cust.gender }"/></td>
<td><c:out value="${cust.birthday }"/></td>
<td><c:out value="${cust.cellphone }"/></td>
<td><c:out value="${cust.email }"/></td>
<td><c:out value="${cust.preference }"/></td>
<td><c:out value="${cust.type }"/></td>
<td><c:out value="${cust.description }"/></td>
<td><a href="${pageContext.request.contextPath }/CustInfoServlet?id=${cust.id}">修改</a></td>
<td><a href="${pageContext.request.contextPath }/DelCustServlet?id=${cust.id}">删除</a></td>
</tr>
</c:forEach>
</table>
<input type="submit" value="批量删除" />
</form>
</body>
</html>
* ListCustServlet.java
显示所有用户信息实现
package com.lmd.web;
import java.io.IOException;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.lmd.domain.Cust;
import com.lmd.factory.BasicFactory;
import com.lmd.service.CustService;
/**
* Servlet implementation class ListCustServlet
*/
@WebServlet("/ListCustServlet")
public class ListCustServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
CustService service = BasicFactory.getFactory().getInstance(CustService.class);
//1、调用service中查询所有客户的方法
List<Cust> list = service.getAllCust();
//2、将查找的信息存在request域,请求转发到listCust.jsp页面进行展示
request.setAttribute("list", list);
request.getRequestDispatcher("/listCust.jsp").forward(request, response);
}
}
1)、修改客户信息
* `updateCust.jsp` 修改客户信息界面
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
</head>
<body style="text-align: center;">
<h1>客户管理系统_修改客户</h1>
<form action="${pageContext.request.contextPath }/UpdateCustServlet" method="post">
<input type="hidden" name="id" value="${cust.id }" />
<table align="center" border="1">
<tr>
<td>客户姓名</td>
<td><input type="text" name="name" value="${cust.name }" readonly="readonly" style="background: silver;"/></td>
</tr>
<tr>
<td>客户性别</td>
<td>
<input type="radio" name="gender" value="男"
<c:if test="${cust.gender=='男'}">checked='checked'</c:if>
/>男
<input type="radio" name="gender" value="女"
<c:if test="${cust.gender=='女'}">checked='checked'</c:if>
/>女
</td>
</tr>
<tr>
<td>客户生日</td>
<td><input type="text" name="birthday" value="${cust.birthday }" /></td>
</tr>
<tr>
<td>手机号码</td>
<td><input type="text" name="cellphone" value="${cust.cellphone }" /></td>
</tr>
<tr>
<td>电子邮件</td>
<td><input type="text" name="email" value="${cust.email }" /></td>
</tr>
<tr>
<td>客户爱好</td>
<td>
<input type="checkbox" name="preference" value="篮球"
<c:forTokens items="${cust.preference }" delims="," var="pref">
<c:if test="${pref=='篮球'}">
checked='checked'
</c:if>
</c:forTokens>
/>篮球
<input type="checkbox" name="preference" value="钢琴"
<c:if test="${fn:contains(cust.preference, '钢琴') }">
checked='checked'
</c:if>
/>钢琴
<input type="checkbox" name="preference" value="舞蹈"
<c:if test="${fn:contains(cust.preference, '舞蹈') }">
checked='checked'
</c:if>
/>舞蹈
<input type="checkbox" name="preference" value="跑步"
<c:if test="${fn:contains(cust.preference, '跑步') }">
checked='checked'
</c:if>
/>跑步
</td>
</tr>
<tr>
<td>客户类型</td>
<td>
<select name="type">
<option value="钻石用户"
<c:if test="${cust.type=='钻石用户' }">
selected='selected'
</c:if>
>钻石用户</option>
<option value="白金用户"
<c:if test="${cust.type=='白金用户' }">
selected='selected'
</c:if>
>白金用户</option>
<option value="黄金用户"
<c:if test="${cust.type=='黄金用户' }">
selected='selected'
</c:if>
>黄金用户</option>
<option value="白银用户"
<c:if test="${cust.type=='白银用户' }">
selected='selected'
</c:if>
>白银用户</option>
<option value="青铜用户"
<c:if test="${cust.type=='青铜用户' }">
selected='selected'
</c:if>
>青铜用户</option>
<option value="普通用户"
<c:if test="${cust.type=='普通用户' }">
selected='selected'
</c:if>
>普通用户</option>
</select>
</td>
</tr>
<!-- 造成引导入侵,例如输入javascript代码,会弹出结果 -->
<tr>
<td>备注信息</td>
<td><textarea rows="6" cols="30" name="description">${cust.description }</textarea></td>
</tr>
<tr>
<td colspan="2">
<a href="${pageContext.request.contextPath}/updateCust.jsp"><input type="submit" value="添加用户"/></a>
</td>
</tr>
</table>
</form>
</body>
</html>
* `UpdateCustServlet.java` 修改客户信息实现
package com.lmd.web;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.beanutils.BeanUtils;
import com.lmd.domain.Cust;
import com.lmd.factory.BasicFactory;
import com.lmd.service.CustService;
/**
* Servlet implementation class UpdateCustServlet
*/
@WebServlet("/UpdateCustServlet")
public class UpdateCustServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
CustService service = BasicFactory.getFactory().getInstance(CustService.class);
// 1.封装数据,省写校验数据
Cust cust = new Cust();
try {
BeanUtils.populate(cust, request.getParameterMap());
//单独处理爱好
String[] prfs = request.getParameterValues("preference");
StringBuffer buffer = new StringBuffer();
for (String pref : prfs) {
buffer.append(pref+",");
}
String pref = buffer.substring(0, buffer.length()-1);
cust.setPreference(pref);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
// 2.调用Service层修改客户的方法
service.updateCust(cust);//Ctrl+1添加方法
//3.重定向回到客户列表页面
request.getRequestDispatcher("/ListCustServlet").forward(request, response);
}
}
2)、单个删除客户
* `ListCustServlet.java` 单个删除客户实现
package com.lmd.web;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.beanutils.BeanUtils;
import com.lmd.domain.Cust;
import com.lmd.factory.BasicFactory;
import com.lmd.service.CustService;
/**
* Servlet implementation class DelCustServlet
*/
@WebServlet("/DelCustServlet")
public class DelCustServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
CustService service = BasicFactory.getFactory().getInstance(CustService.class);
// 1.获取要删除的客户id
String id = request.getParameter("id");
// 2.调用Service层id删除客户的方法
service.delCustById(id);//Ctrl+1添加方法
//3.转发到客户列表页面
request.getRequestDispatcher("/ListCustServlet").forward(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
3)、批量删除客户
* `ListCustServlet.java` 显示所有用户信息实现
package com.lmd.web;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.beanutils.BeanUtils;
import com.lmd.domain.Cust;
import com.lmd.factory.BasicFactory;
import com.lmd.service.CustService;
/**
* Servlet implementation class BatchDelCustServlet
*/
@WebServlet("/BatchDelCustServlet")
public class BatchDelCustServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
CustService service = BasicFactory.getFactory().getInstance(CustService.class);
// 1.获取所有删除的客户id
String[] ids = request.getParameterValues("delId");
// 2.调用Service层批量删除客户的方法
service.batchDel(ids);//Ctrl+1添加方法
//3.转发到客户列表页面
request.getRequestDispatcher("/ListCustServlet").forward(request, response);
}
}
(3)、分页查询用户列表
* `pageCust.jsp` 分页显示用户信息界面
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<script type="text/javascript">
function changePage(obj){
if(isNaN(obj.value)){
alert("必须是数字!!!");
obj.value = ${page.thispage};
} else{
if(obj.value<=0 || obj.value>${page.countpage}){
alert("必须是有效范围内的页码!!!");
obj.value = ${page.thispage};
return;
} else {
window.location.href = "${pageContext.request.contextPath }/PageCustServlet?thispage="+obj.value;
}
}
}
</script>
</head>
<body style="text-align: center;">
<h1>客户管理系统_客户列表页面</h1>
<table border="1" width="100%" align="center">
<tr>
<th>客户姓名</th>
<th>客户性别</th>
<th>出生日期</th>
<th>手机号码</th>
<th>电子邮件</th>
<th>客户爱好</th>
<th>客户类型</th>
<th>描述信息</th>
<th>修改</th>
<th>删除</th>
</tr>
<c:forEach items="${requestScope.page.custList }" var="cust">
<tr>
<!-- 使用标签解决引导入侵,不让字符转义 -->
<td><c:out value="${cust.name }"/></td>
<td><c:out value="${cust.gender }"/></td>
<td><c:out value="${cust.birthday }"/></td>
<td><c:out value="${cust.cellphone }"/></td>
<td><c:out value="${cust.email }"/></td>
<td><c:out value="${cust.preference }"/></td>
<td><c:out value="${cust.type }"/></td>
<td><c:out value="${cust.description }"/></td>
<td><a href="${pageContext.request.contextPath }/CustInfoServlet?id=${cust.id}">修改</a></td>
<td><a href="${pageContext.request.contextPath }/DelCustServlet?id=${cust.id}">删除</a></td>
</tr>
</c:forEach>
</table>
<div style="text-align: center;">
共${page.countrow }条记录 共${page.countpage }页
<a href="${pageContext.request.contextPath }/PageCustServlet?thispage=${page.firstpage}">首页</a>
<a href="${pageContext.request.contextPath }/PageCustServlet?thispage=${page.prevpage}">上一页</a>
<!-- 分页逻辑开始 -->
<c:if test="${page.countpage<=5 }">
<c:set var="begin" value="1" scope="page"></c:set>
<c:set var="end" value="${page.countpage }" scope="page"></c:set>
</c:if>
<c:if test="${page.countpage>5 }">
<c:choose>
<c:when test="${page.thispage<=3 }">
<c:set var="begin" value="1" scope="page"></c:set>
<c:set var="end" value="5" scope="page"></c:set>
</c:when>
<c:when test="${page.thispage>=page.countpage-2 }">
<c:set var="begin" value="${page.countpage-4 }" scope="page"></c:set>
<c:set var="end" value="${page.countpage}" scope="page"></c:set>
</c:when>
<c:otherwise>
<c:set var="begin" value="${page.thispage-2 }" scope="page"></c:set>
<c:set var="end" value="${page.thispage+2}" scope="page"></c:set>
</c:otherwise>
</c:choose>
</c:if>
<c:forEach begin="${begin }" end="${end }" var="i">
<c:if test="${i==page.thispage }">
${i }
</c:if>
<c:if test="${i!=page.thispage }">
<a href="${pageContext.request.contextPath }/PageCustServlet?thispage=${i}">${i }</a>
</c:if>
</c:forEach>
<!-- 分页逻辑结束 -->
<a href="${pageContext.request.contextPath }/PageCustServlet?thispage=${page.nextpage}">下一页</a>
<a href="${pageContext.request.contextPath }/PageCustServlet?thispage=${page.lastpage}">尾页</a>
跳转到<input type="text" value="${page.thispage }" size="1" onchange="changePage(this)"/>页
</div>
</body>
</html>
* PageCustServle.java
显示所有用户信息实现
package com.lmd.web;
import java.io.IOException;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.lmd.domain.Cust;
import com.lmd.domain.Page;
import com.lmd.factory.BasicFactory;
import com.lmd.service.CustService;
/**
* Servlet implementation class PageCustServlet
*/
@WebServlet("/PageCustServlet")
public class PageCustServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
CustService service = BasicFactory.getFactory().getInstance(CustService.class);
//1、获取当前要显示的页和每页记录数
int thispage = Integer.parseInt(request.getParameter("thispage"));
int rowperpage = 5;
//2、调用service中分页查询客户的方法,查找出客户信息
Page page = service.pageCust(thispage,rowperpage);
//2、存入request域,请求转发到pageCust.jsp页面进行展示
request.setAttribute("page", page);
request.getRequestDispatcher("/pageCust.jsp").forward(request, response);
}
}