11第十二天DBUtils

一、前言:元数据介绍

准备工作:数据库day12(account)、mysql-connector-java-5.1.40-bin.jar和c3p0-0.9.1.2.jar,以及c3p0-config.xml:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <c3p0-config>
  3. <default-config name="aaa">
  4. <property name="driverClass">com.mysql.jdbc.Driver</property>
  5. <property name="jdbcUrl">jdbc:mysql:///day12</property>
  6. <property name="user">root</property>
  7. <property name="password">666666</property>
  8. </default-config>
  9. </c3p0-config>
  1. select * from account;
  2. +----+------+-------+
  3. | id | name | money |
  4. +----+------+-------+
  5. | 1 | a | 1000 |
  6. | 2 | b | 1000 |
  7. | 3 | c | 1000 |
  8. +----+------+-------+

(一)、元数据

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 - 表名称;它必须与存储在数据库中的表名称匹配。
  1. 每个主键列描述都有以下列:
  2. TABLE_CAT String => 表类别(可为 null
  3. TABLE_SCHEM String => 表模式(可为 null
  4. TABLE_NAME String => 表名称
  5. COLUMN_NAME String => 列名称
  6. KEY_SEQ short => 主键中的序列号(值 1 表示主键中的第一列,值 2 表示主键中的第二列)。
  7. PK_NAME String => 主键的名称(可为 null
  8. ```
  9. * `getTables(String catalog, String schemaPattern,String tableNamePattern,String[] types)` - 获取可在给定类别中使用的表的描述。仅返回与类别、模式、表名称和类型标准匹配的表描述。它们根据 TABLE_TYPE、TABLE_CAT、TABLE_SCHEM 和 TABLE_NAME 进行排序。
  10. ```sql
  11. 每个表描述都有以下列:
  12. TABLE_CAT String => 表类别(可为 null
  13. TABLE_SCHEM String => 表模式(可为 null
  14. TABLE_NAME String => 表名称
  15. TABLE_TYPE String => 表类型。典型的类型是 "TABLE""VIEW""SYSTEM TABLE""GLOBAL TEMPORARY""LOCAL TEMPORARY""ALIAS" "SYNONYM"
  16. REMARKS String => 表的解释性注释
  17. TYPE_CAT String => 类型的类别(可为 null
  18. TYPE_SCHEM String => 类型模式(可为 null
  19. TYPE_NAME String => 类型名称(可为 null
  20. SELF_REFERENCING_COL_NAME String => 有类型表的指定 "identifier" 列的名称(可为 null
  21. REF_GENERATION String => 指定在 SELF_REFERENCING_COL_NAME 中创建值的方式。这些值为 "SYSTEM""USER" "DERIVED"。(可能为 null
  22. 注: 有些数据库可能不返回用于所有表的信息。
  • 方法练习:
  1. package com.lmd.metadata;
  2. import java.sql.Connection/DatabaseMetaData;
  3. import java.sql.PreparedStatement;
  4. import java.sql.ResultSet/SQLException;
  5. import com.mchange.v2.c3p0.ComboPooledDataSource;
  6. public class DataBaseMetaDataDemo {
  7. public static void main(String[] args) {
  8. Connection conn = null;
  9. PreparedStatement ps = null;
  10. ResultSet rs = null;
  11. ComboPooledDataSource source = new ComboPooledDataSource();
  12. try {
  13. conn = source.getConnection();
  14. //--获取当前数据库的元数据
  15. DatabaseMetaData metaData = conn.getMetaData();
  16. //--获取数据库连接时使用的URL 框架设计者使用
  17. String url = metaData.getURL();
  18. System.out.println(url);//输出:jdbc:mysql:///day12
  19. //--获取数据库的用户名 框架设计者使用
  20. String name = metaData.getUserName();
  21. System.out.println(name);//输出:root@localhost
  22. //--返回驱动驱动程序的名称。 框架设计者使用
  23. String driver = metaData.getDriverName();
  24. System.out.println(driver);//输出:MySQL Connector Java
  25. //--返回指定表主键的结果集 框架设计者使用
  26. rs = metaData.getPrimaryKeys(null, null, "account");
  27. while (rs.next()) {
  28. //获取主键的序列号和名称
  29. short cseq = rs.getShort("KEY_SEQ");
  30. String cname = rs.getString("PK_NAME");
  31. System.out.println(cseq+":"+cname);//1:PRIMARY
  32. }
  33. //-获取表, "acc%":以acc开头的表;"%":所有 表
  34. rs = metaData.getTables(null, null, "%", new String[]{"TABLE"});
  35. while (rs.next()) {
  36. //获取表名称
  37. String tname = rs.getString("TABLE_NAME");
  38. System.out.println(tname);//输出:account
  39. }
  40. } catch (Exception e) {
  41. e.printStackTrace();
  42. } finally {
  43. //rs、ps和conn释放
  44. }
  45. }
  46. }

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
    • 方法练习:
  1. package com.lmd.metadata;
  2. import java.sql.Connection;
  3. import java.sql.DatabaseMetaData/ParameterMetaData;
  4. import java.sql.PreparedStatement/ResultSet;
  5. import java.sql.SQLException;
  6. import com.mchange.v2.c3p0.ComboPooledDataSource;
  7. public class PMMetaDataDemo {
  8. public static void main(String[] args) {
  9. Connection conn = null;
  10. PreparedStatement ps = null;
  11. ResultSet rs = null;
  12. ComboPooledDataSource source = new ComboPooledDataSource();
  13. try {
  14. conn = source.getConnection();
  15. ps = conn.prepareStatement("select * from account where name=? and money=?");
  16. //---获取参数元数据
  17. ParameterMetaData metaData = ps.getParameterMetaData();
  18. //--获取参数个数
  19. int count = metaData.getParameterCount();
  20. System.out.println(count);//2
  21. //--获取数据的类型
  22. // 要修改c3p0-config.xml:<property name="jdbcUrl">jdbc:mysql:///day12
  23. // ?generateSimpleParameterMetadata=true</property>
  24. String type = metaData.getParameterTypeName(1);//mysql支持不好
  25. System.out.println(type);//VARCHAR
  26. String type2 = metaData.getParameterTypeName(2);
  27. System.out.println(type2);//VARCHAR
  28. } catch (Exception e) {
  29. e.printStackTrace();
  30. } finally {
  31. //rs、ps和conn释放
  32. }
  33. }
  34. }

3、ResultSetMetaData

(1)、ResultSet. getMetaData()

  • 获得代表ResultSet对象元数据的ResultSetMetaData对象。

(2)、ResultSetMetaData对象

  • getColumnCount() 返回resultset对象的列数
  • getColumnName(int column) 获得指定列的名称
  • getColumnTypeName(int column) 获得指定列的类型
    • 方法练习:
  1. package com.lmd.metadata;
  2. import java.sql.Connection;
  3. import java.sql.PreparedStatement;
  4. import java.sql.ResultSet;
  5. import java.sql.ResultSetMetaData;
  6. import java.sql.SQLException;
  7. import com.mchange.v2.c3p0.ComboPooledDataSource;
  8. public class PMMetaDataDemo {
  9. public static void main(String[] args) {
  10. Connection conn = null;
  11. PreparedStatement ps = null;
  12. ResultSet rs = null;
  13. ComboPooledDataSource source = new ComboPooledDataSource();
  14. try {
  15. conn = source.getConnection();
  16. ps = conn.prepareStatement("select * from account");
  17. rs = ps.executeQuery();
  18. //框架设计者使用
  19. //--获取结果集元数据
  20. ResultSetMetaData metaData = rs.getMetaData();
  21. //--获取结果集中列的个数
  22. int ccount = metaData.getColumnCount();
  23. System.out.println(ccount);//3
  24. //--获取结果集中指定列的名称
  25. String cname = metaData.getColumnName(2);
  26. System.out.println(cname);//name
  27. //--获取结果集中指定列的类型的名称
  28. String tname = metaData.getColumnTypeName(3);
  29. System.out.println(tname);//DOUBLE
  30. } catch (Exception e) {
  31. e.printStackTrace();
  32. } finally {
  33. //rs、ps和conn释放
  34. }
  35. }
  36. }
  • 总练习:
  1. Connection conn = null;
  2. PreparedStatement ps = null;
  3. ResultSet rs = null;
  4. ComboPooledDataSource source = new ComboPooledDataSource();
  5. try {
  6. conn = source.getConnection();
  7. ps = conn.prepareStatement("select * from account");
  8. rs = ps.executeQuery();
  9. //框架设计者使用
  10. //--获取结果集元数据
  11. ResultSetMetaData metaData = rs.getMetaData();
  12. //--获取结果集中列的个数
  13. int ccount = metaData.getColumnCount();
  14. //System.out.println(ccount);//3
  15. //--获取结果集中指定列的名称
  16. //String cname = metaData.getColumnName(2);
  17. //System.out.println(cname);//name
  18. //--获取结果集中指定列的类型的名称
  19. //String tname = metaData.getColumnTypeName(3);
  20. //System.out.println(tname);//DOUBLE
  21. System.out.println("----------------------------------------------------");
  22. for (int i = 1; i <= ccount; i++) {
  23. String cname = metaData.getColumnName(i);
  24. String ctype = metaData.getColumnTypeName(i);
  25. System.out.print(cname+":"+ctype+"\t\t");
  26. }
  27. System.out.println();
  28. System.out.println("----------------------------------------------------");
  29. while (rs.next()) {
  30. for (int i = 1; i <= ccount; i++) {
  31. Object obj = rs.getObject(i);
  32. System.out.print(obj+"\t\t ");
  33. }
  34. System.out.println();
  35. }
  36. System.out.println("----------------------------------------------------");
  37. } catch (Exception e) {
  38. e.printStackTrace();
  39. } finally {
  40. //rs、ps和conn释放
  41. }
  42. <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 语句。


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),再把这些map再存到一个map里,其key为指定的列。
  • !!!!!ScalarHandler:获取结果集中第一行数据指定列的值,常用来进行单值查询

2、练习:

  1. package com.lmd.metadata;
  2. import java.sql.SQLException;
  3. import java.util.List;
  4. import java.util.Map;
  5. import org.apache.commons.dbutils.QueryRunner;
  6. import org.apache.commons.dbutils.handlers.ArrayHandler;
  7. import org.apache.commons.dbutils.handlers.ArrayListHandler;
  8. import org.apache.commons.dbutils.handlers.BeanHandler;
  9. import org.apache.commons.dbutils.handlers.BeanListHandler;
  10. import org.apache.commons.dbutils.handlers.ColumnListHandler;
  11. import org.apache.commons.dbutils.handlers.KeyedHandler;
  12. import org.apache.commons.dbutils.handlers.MapHandler;
  13. import org.apache.commons.dbutils.handlers.MapListHandler;
  14. import org.apache.commons.dbutils.handlers.ScalarHandler;
  15. import org.junit.Test;
  16. import com.lmd.domain.Account;
  17. import com.mchange.v2.c3p0.ComboPooledDataSource;
  18. public class RSHandlerDemo {
  19. //ArrayHandler:把结果集中的第一行数据转成对象数组
  20. public void testArrayHandler() throws SQLException {
  21. QueryRunner runner = new QueryRunner(new ComboPooledDataSource());
  22. Object[] obj = runner.query("select * from account where money>?", new ArrayHandler(), 800);
  23. for (int i = 0; i < obj.length; i++) {
  24. System.out.print(i == obj.length-1 ? obj[i] : obj[i]+"--");
  25. }
  26. }//输出:1--a--999.0
  27. //ArrayListHandler:把结果集中的每一行数据都转成一个对象数组,再存放到List中。
  28. public void testArrayListHandler() throws SQLException {
  29. QueryRunner runner = new QueryRunner(new ComboPooledDataSource());
  30. List<Object[]> list = runner.query("select * from account where money>?", new ArrayListHandler(), 800);
  31. for (int i = 0; i < list.size(); i++) {
  32. Object[] obj = list.get(i);
  33. for (int j = 0; j < obj.length; j++) {
  34. System.out.print(j == obj.length-1 ? obj[j] : obj[j]+"--");
  35. }
  36. System.out.println();
  37. }
  38. }//输出:1--a--999.0 换行 2--b--888.0
  39. //BeanHandler:将结果集中的第一行数据封装到一个对应的JavaBean实例中。
  40. public void testBeanHandler() throws SQLException {
  41. QueryRunner runner = new QueryRunner(new ComboPooledDataSource());
  42. Account acc = runner.query("select * from account where money>?", new BeanHandler<Account>(Account.class), 800);
  43. System.out.println(acc.getId()+"--"+acc.getName()+"--"+acc.getMoney());
  44. }//输出:1--a--999.0
  45. //BeanHandler:将结果集中的第一行数据封装到一个对应的JavaBean实例中。
  46. public void testBeanListHandler() throws SQLException {
  47. QueryRunner runner = new QueryRunner(new ComboPooledDataSource());
  48. List<Account> list = runner.query("select * from account where money>?", new BeanListHandler<Account>(Account.class), 800);
  49. for (int i = 0; i < list.size(); i++) {
  50. Account acc = list.get(i);
  51. System.out.println(acc.getId()+"--"+acc.getName()+"--"+acc.getMoney());
  52. }
  53. }//输出:1--a--999.0 换行 2--b--888.0
  54. //MapHandler:将结果集中的第一行数据封装到一个Map里,key是列名,value就是对应的值。
  55. public void testMapHandler() throws SQLException {
  56. QueryRunner runner = new QueryRunner(new ComboPooledDataSource());
  57. Map<String, Object> map = runner.query("select * from account where money>?", new MapHandler(), 800);
  58. System.out.println(map );
  59. }//输出:{money=999.0, name=a, id=1}
  60. //MapListHandler:将结果集中的每一行数据都封装到一个Map里,然后再存放到List
  61. public void testMapListHandler() throws SQLException {
  62. QueryRunner runner = new QueryRunner(new ComboPooledDataSource());
  63. List<Map<String, Object>> list = runner.query("select * from account where money>?", new MapListHandler(), 800);
  64. for (Map<String, Object> map : list) {
  65. System.out.println(map);
  66. }
  67. }//输出:{money=999.0, name=a, id=1}换行{money=888.0, name=b, id=2
  68. //ColumnListHandler:将结果集中某一列的数据存放到List中。
  69. public void testColumnListHandler() throws SQLException {
  70. QueryRunner runner = new QueryRunner(new ComboPooledDataSource());
  71. List<Object> list = runner.query("select * from account where money>?", new ColumnListHandler(2), 800);
  72. for (Object obj : list) {
  73. System.out.print(obj +" ");
  74. }
  75. }//输出:a b
  76. //KeyedHandler(name):将结果集中的每一行数据都封装到一个Map里(List<Map>),
  77. //再把这些map再存到一个map里,其key为指定的列。
  78. public void testKeyedHandler() throws SQLException {
  79. QueryRunner runner = new QueryRunner(new ComboPooledDataSource());
  80. Map<Object, Map<String, Object>> map = runner.query("select * from account where money>?", new KeyedHandler("id"), 800);
  81. System.out.println(map);
  82. //输出:{1={money=999.0, name=a, id=1}, 2={money=888.0, name=b, id=2}}
  83. System.out.println(map.get(2).get("name"));
  84. }//输出: b
  85. //ScalarHandler:获取结果集中第一行数据指定列的值,常用来进行单值查询
  86. //默认第一行第一列
  87. @Test
  88. public void testScalarHandler() throws SQLException {
  89. QueryRunner runner = new QueryRunner(new ComboPooledDataSource());
  90. Long count = (Long) runner.query("select count(*) from account", new ScalarHandler());
  91. System.out.println(count);
  92. }//输出: 3
  93. }

(五)、QueryRunner类更新和查询操作练习:

1、更新操作

  1. //自己设计DbUtils框架
  2. package com.lmd.dbutils;
  3. import java.sql.Connection/ParameterMetaData;
  4. import java.sql.PreparedStatement/SQLException;
  5. import javax.sql.DataSource;
  6. import org.apache.commons.dbutils.DbUtils;
  7. public class MyQueryRunner {
  8. private DataSource source = null;
  9. public MyQueryRunner(){ }
  10. public MyQueryRunner(DataSource source){
  11. this.source = source;
  12. }
  13. public int update(String sql, Object... params)throws SQLException {
  14. Connection conn = source.getConnection();
  15. PreparedStatement ps = conn.prepareStatement(sql);
  16. //--获取参数元数据
  17. ParameterMetaData metaData = ps.getParameterMetaData();
  18. int count = metaData.getParameterCount();
  19. //--循环设置参数值
  20. for (int i = 1; i <= count; i++) {
  21. ps.setObject(i, params[i-1]);
  22. }
  23. //--执行update操作
  24. int num = ps.executeUpdate();
  25. DbUtils.closeQuietly(conn, ps, null);
  26. return num;
  27. }
  28. }
  • 实现更新操作:
  1. package com.lmd.dbutils;
  2. import java.sql.Connection;
  3. import java.sql.PreparedStatement;
  4. import java.sql.ResultSet;
  5. import java.sql.SQLException;
  6. import org.apache.commons.dbutils.DbUtils;
  7. import org.apache.commons.dbutils.QueryRunner;
  8. import org.junit.Test;
  9. import com.mchange.v2.c3p0.ComboPooledDataSource;
  10. public class DbUtilsUpdate {
  11. public void delete() throws SQLException {
  12. MyQueryRunner runner = new MyQueryRunner(new ComboPooledDataSource());
  13. runner.update("delete from account where id=?", 7);
  14. }
  15. public void add() throws SQLException {
  16. MyQueryRunner runner = new MyQueryRunner(new ComboPooledDataSource());
  17. runner.update("insert into account values(null,?,?)", "d", 1000);
  18. }
  19. /**
  20. * MyDbUtils实现增删改功能
  21. * @throws SQLException
  22. */
  23. /@Test
  24. public void update1() throws SQLException {
  25. MyQueryRunner runner = new MyQueryRunner(new ComboPooledDataSource());
  26. runner.update("update account set money=? where name=?", 777, "c");
  27. }
  28. /**
  29. * DbUtils实现增删改功能
  30. * @throws SQLException
  31. */
  32. public void update2() throws SQLException {
  33. QueryRunner runner = new QueryRunner(new ComboPooledDataSource());
  34. runner.update("update account set money=? where name=?", 888, "b");
  35. }
  36. /**
  37. * 古老方法实现增删改功能
  38. * --在进行增删改操作时,每次不一样的时sql语句和其中的参数
  39. */
  40. public void update3() {
  41. Connection conn = null;
  42. PreparedStatement ps = null;
  43. ResultSet rs = null;
  44. ComboPooledDataSource source = new ComboPooledDataSource();
  45. try {
  46. conn = source.getConnection();
  47. ps = conn.prepareStatement("update account set money=? where name=?");
  48. ps.setDouble(1, 999);
  49. ps.setString(2, "a");
  50. ps.executeUpdate();
  51. } catch (Exception e) {
  52. e.printStackTrace();
  53. } finally {
  54. DbUtils.closeQuietly(conn, ps, rs);
  55. }
  56. }
  57. }

2、查询操作

  • 新增一个接口:MyResultSetHandler
  1. package com.lmd.dbutils;
  2. import java.sql.ResultSet;
  3. import java.sql.SQLException;
  4. public interface MyResultSetHandler<T> {
  5. T handle(ResultSet rs) throws SQLException;
  6. }
  • 在自己设计DbUtils框架MyQueryRunner.java中新增:
  1. //利用接口实现传进去
  2. public <T> T query(String sql, MyResultSetHandler<T> rsh, Object... params) throws SQLException{
  3. Connection conn = source.getConnection();
  4. PreparedStatement ps = conn.prepareStatement(sql);
  5. //--获取参数元数据
  6. ParameterMetaData metaData = ps.getParameterMetaData();
  7. int count = metaData.getParameterCount();
  8. //--循环设置参数值
  9. for (int i = 1; i <= count; i++) {
  10. ps.setObject(i, params[i-1]);
  11. }
  12. //--执行query操作获取结果集
  13. ResultSet rs = ps.executeQuery();
  14. //--`回调`处理结果集的逻辑
  15. T t = rsh.handle(rs);
  16. DbUtils.closeQuietly(conn, ps, rs);
  17. return t;
  18. }
  • 查询操作:
  1. package com.lmd.dbutils;
  2. import java.sql.Connection;
  3. import java.sql.PreparedStatement;
  4. import java.sql.ResultSet;
  5. import java.sql.SQLException;
  6. import java.util.ArrayList;
  7. import java.util.List;
  8. import org.apache.commons.dbutils.DbUtils;
  9. import org.apache.commons.dbutils.QueryRunner;
  10. import org.apache.commons.dbutils.ResultSetHandler;
  11. import org.junit.Test;
  12. import com.lmd.domain.Account;
  13. import com.mchange.v2.c3p0.ComboPooledDataSource;
  14. import com.mysql.fabric.xmlrpc.base.Array;
  15. public class DbUtilsQuery {
  16. /**
  17. * MyDbUtils实现查询功能
  18. * @throws SQLException
  19. *
  20. * 回调函数:当方法a调用方法b时,而方法b在执行的过程中,
  21. * 其中一些逻辑需要由方法a告知,此时需要方法a在调用
  22. * 方法b时将逻辑传入,而java中是不允许传递java源代码的,
  23. * 此时可以使用回调机制。所谓回调,就是方法a和方法b约定
  24. * 一个接口,在这个接口中定义一个方法,这个方法通常叫handler方法,
  25. * a调用b时,传入此接口实现,其中利用handler方法,将逻辑传入,
  26. * 方法b在执行过程中需要执行a传入的逻辑时,调用接口实现的handler方法
  27. * 即可,此时a调用b时,b回来调用的a传入的逻辑,所以此过程叫回调
  28. */
  29. @Test
  30. public void select1() throws SQLException {
  31. MyQueryRunner runner = new MyQueryRunner(new ComboPooledDataSource());
  32. List<Account> list = runner.query("select * from account where money>?"
  33. , new MyResultSetHandler<List<Account>>(){
  34. @Override
  35. public List<Account> handle(ResultSet rs) throws SQLException {
  36. List<Account> list = new ArrayList<Account>();
  37. while (rs.next()) {
  38. Account account = new Account();
  39. account.setId(rs.getInt("id"));
  40. account.setName(rs.getString("name"));
  41. account.setMoney(rs.getDouble("money"));
  42. list.add(account);
  43. }
  44. return list;
  45. }
  46. }, 800);
  47. for (int i = 0; i < list.size(); i++) {
  48. Account acc = list.get(i);
  49. System.out.println(acc.getId()+"--"+acc.getName()+"--"+acc.getMoney());
  50. }
  51. }
  52. /**
  53. * DbUtils实现查询功能
  54. * @throws SQLException
  55. */
  56. public void select2() throws SQLException {
  57. QueryRunner runner = new QueryRunner(new ComboPooledDataSource());
  58. List<Account> list = runner.query("select * from account where money>?"
  59. , new ResultSetHandler<List<Account>>(){
  60. @Override
  61. public List<Account> handle(ResultSet rs) throws SQLException {
  62. List<Account> list = new ArrayList<Account>();
  63. while (rs.next()) {
  64. Account account = new Account();
  65. account.setId(rs.getInt("id"));
  66. account.setName(rs.getString("name"));
  67. account.setMoney(rs.getDouble("money"));
  68. list.add(account);
  69. }
  70. return list;
  71. }
  72. }, 800);
  73. for (int i = 0; i < list.size(); i++) {
  74. Account acc = list.get(i);
  75. System.out.println(acc.getId()+"--"+acc.getName()+"--"+acc.getMoney());
  76. }
  77. }
  78. /**
  79. * 古老方法实现查询功能
  80. * --在进行查询操作时,每次不一样的是sql语句、sql中的参数、结果集的处理
  81. */
  82. public void select3() {
  83. Connection conn = null;
  84. PreparedStatement ps = null;
  85. ResultSet rs = null;
  86. ComboPooledDataSource source = new ComboPooledDataSource();
  87. List<Account> list = new ArrayList<Account>();
  88. try {
  89. conn = source.getConnection();
  90. ps = conn.prepareStatement("select * from account where money>?");
  91. ps.setDouble(1, 800);
  92. rs = ps.executeQuery();
  93. while (rs.next()) {
  94. Account account = new Account();
  95. account.setId(rs.getInt("id"));
  96. account.setName(rs.getString("name"));
  97. account.setMoney(rs.getDouble("money"));
  98. list.add(account);
  99. }
  100. for (int i = 0; i < list.size(); i++) {
  101. Account acc = list.get(i);
  102. System.out.println(acc.getId()+"--"+acc.getName()+"--"+acc.getMoney());
  103. }
  104. //1--a--999.0
  105. //2--b--888.0
  106. } catch (Exception e) {
  107. e.printStackTrace();
  108. } finally {
  109. DbUtils.closeQuietly(conn, ps, rs);
  110. }
  111. }
  112. }

(六)、其他知识点:

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:
  1. public class Caller {
  2. public MyCallInterface mc;
  3. public void setCallfuc(MyCallInterface mc) {
  4. this.mc= mc;
  5. }
  6. public void call(){
  7. this.mc.method();
  8. }
  9. }
* 我还需要定义一个接口,以便程序员B根据我的定义编写程序实现接口。
  1. public interface MyCallInterface {
  2. public void method();
  3. }
* 于是,程序员B只需要实现这个接口就能达到回调的目的了:
  1. public class B implements MyCallInterface {
  2. public void method() {
  3. System.out.println("回调");
  4. }
  5. public static void main(String args[]) {
  6. Caller call = new Caller();
  7. call.setCallfuc(new B());
  8. call.call();
  9. }
  10. }

3、例子:


  1. package com.lmd.test;
  2. //接口中定义比较大小的方法
  3. interface IntCompare{
  4. public int compare(int a, int b) ;
  5. }
  6. class AscendOrder implements IntCompare{
  7. @Override
  8. public int compare(int a, int b) {
  9. return a>b ? 1 : (a<b ? -1 : 0);
  10. }
  11. }
  12. class DescendOrder implements IntCompare{
  13. @Override
  14. public int compare(int a, int b) {
  15. return a>b ? -1 : (a<b ? 1 : 0);
  16. }
  17. }
  18. public class CallbackFunction {
  19. public static void insertSort(int[] arr, IntCompare cmp) {
  20. if (arr != null) {
  21. for (int i = 1; i < arr.length; i++) {
  22. int temp = arr[i], j=i;
  23. if (cmp.compare(arr[j-1], temp) == 1) {
  24. while (j >= 1 && cmp.compare(arr[j-1], temp)==1) {
  25. arr[j] = arr[j-1];
  26. j--;
  27. }
  28. }
  29. arr[j] = temp;
  30. }
  31. }
  32. }
  33. public static String printSort(int[] arr) {
  34. String s = "";
  35. for (int i = 0; i < arr.length; i++) {
  36. s += arr[i] + " ";
  37. }
  38. return s;
  39. }
  40. public static void main(String[] args) {
  41. int[] arr1 = {12, 3, -2, 33, 24};
  42. insertSort(arr1, new AscendOrder());
  43. System.out.println("升序:" + printSort(arr1));
  44. int[] arr2 = {12, 3, -2, 33, 24};
  45. insertSort(arr2, new DescendOrder());
  46. System.out.println("降序:" + printSort(arr2));
  47. }
  48. }

分页技术


  • 物理分页

  • 在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、设计数据库:
    1. create table customer (
    2. id int primary key auto_increment,
    3. name varchar(20),
    4. gender varchar(10),
    5. birthday date,
    6. cellphone varchar(20),
    7. email varchar(40),
    8. preference varchar(100),
    9. type varchar(40),
    10. description varchar(255)
    11. );
    字段名 说明 类型
    id 编号 int
    name 客户姓名 varchar(20)
    gender 性别 varchar(10)
    birthday 生日 date
    cellphone 手机 varchar(20)
    email 电子邮件 varchar(40)
    preference 客户爱好 varchar(100)
    type 客户类型 varchar(40)
    description 备注 varchar(255)
    • 8、工厂类实现解耦:
      • 要有接口(CustDao、CustService)、要有配置文件(confing.properties )、要有工厂类。
      • CustDaoImp和CustServiceImp两个实现类 设置了一个通用的工厂类。
    1. CustDaoImp=com.lmd.dao.CustDaoImp //service层和Dao层的解耦
    2. 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
    • 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
    1. <?xml version="1.0" encoding="utf-8"?>
    2. <c3p0-config>
    3. <default-config>
    4. <property name="driverClass">com.mysql.jdbc.Driver</property>
    5. <property name="jdbcUrl">jdbc:mysql:///day12?serverTimezone=UTC</property>(时区异常问题)
    6. <property name="user">root</property>
    7. <property name="password">666666</property>
    8. </default-config>
    9. </c3p0-config>
    * `index.jsp`开始界面
    
    1. <%@ page language="java" contentType="text/html; charset=UTF-8"%>
    2. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    3. <html>
    4. <head>
    5. <title>客户管理系统</title>
    6. </head>
    7. <body>
    8. <h1>客户管理系统_主页</h1>
    9. <a href="${pageContext.request.contextPath}/addCust.jsp">添加客户</a>
    10. <a href="${pageContext.request.contextPath}/ListCustServlet">查询客户列表</a>
    11. <a href="${pageContext.request.contextPath}/ListCustServlet">修改客户信息</a>
    12. <a href="${pageContext.request.contextPath}/ListCustServlet">删除客户</a>
    13. <a href="${pageContext.request.contextPath}/PageCustServlet?thispage=1">分页查询客户</a>
    14. </body>
    15. </html>

    * `web.xml` 配置错误提示界面
    
    1. <error-page>
    2. <error-code>500</error-code>
    3. <location>/error/500.jsp</location>
    4. </error-page>
    5. <error-page>
    6. <error-code>404</error-code>
    7. <location>/error/404.jsp</location>
    8. </error-page>
    * `500/404.xml` 错误提示界面
    
    1. <body>
    2. 服务器出错了~~~~~~出错原因:${pageContext.exception.message }
    3. </body>
    4. <body>
    5. 资源被搬走了~~~~~~出错原因:${pageContext.exception.message }
    6. </body>
    * `Cust.java` Dao类,这一般是指java中MVC架构中的model的概念,主要是访问数据库的一些方法。domain包下
    
    1. package com.lmd.domain;
    2. import java.io.Serializable;
    3. import java.sql.Date;
    4. public class Cust implements Serializable {
    5. private int id;
    6. private String name;
    7. private String gender;
    8. private Date birthday;
    9. private String cellphone;
    10. private String email;
    11. private String preference;
    12. private String type;
    13. private String description;
    14. //getter和setter
    15. }
    * `Page.java` Dao类分页查询使用  domain包下
    
    1. package com.lmd.domain;
    2. import java.util.List;
    3. public class Page {
    4. private int thispage;
    5. private int rowperpage;
    6. private int countrow;
    7. private int countpage;
    8. private int firstpage;
    9. private int lastpage;
    10. private int prevpage;
    11. private int nextpage;
    12. private List<Cust> custList;
    13. //getter和setter
    14. }
    • BasicFactory.java 工厂类解耦,需要接口和实现类、配置文件(confing.properties )
    1. package com.lmd.factory;
    2. import java.io.FileReader;
    3. import java.util.Properties;
    4. import com.lmd.dao.CustDao;
    5. public class BasicFactory {
    6. private static BasicFactory factory = new BasicFactory();
    7. private static Properties prop = null;
    8. private BasicFactory(){
    9. }
    10. public static BasicFactory getFactory() {
    11. return factory;
    12. }
    13. static{
    14. try {
    15. prop = new Properties();
    16. prop.load(new FileReader(BasicFactory.class
    17. .getClassLoader().getResource("config.properties").getPath()));
    18. } catch (Exception e) {
    19. e.printStackTrace();
    20. throw new RuntimeException(e);
    21. }
    22. }
    23. public <T> T getInstance(Class<T> clazz) {//CustDao.class:com.lmd.dao.CustDaoImp
    24. try {
    25. String cName = clazz.getSimpleName();//"CustDao" 接口找实现
    26. String cImplName = prop.getProperty(cName);//com.lmd.dao.CustDaoImp
    27. return (T) Class.forName(cImplName).newInstance();
    28. } catch (Exception e) {
    29. e.printStackTrace();
    30. throw new RuntimeException(e);
    31. }
    32. }
    33. }
    * `CustService.java`  service包下  接口  业务逻辑层
    
    1. package com.lmd.service;
    2. import java.util.List;
    3. import com.lmd.domain.Cust;
    4. import com.lmd.domain.Page;
    5. public interface CustService {
    6. /**
    7. * 添加客户
    8. * @param cust 封装了用户信息的bean
    9. */
    10. void addCust(Cust cust);
    11. /**
    12. * 查询所有客户信息
    13. * @return
    14. */
    15. List<Cust> getAllCust();
    16. /**
    17. * 根据id查找客户信息
    18. * @param id 客户id
    19. * @return 查找到的客户信息,如果找不到返回null;
    20. */
    21. Cust findCustById(String id);
    22. /**
    23. * 修改客户信息的方法
    24. * @param cust 封装了最新客户信息的方法
    25. */
    26. void updateCust(Cust cust);
    27. /**
    28. * 根据id删除客户信息
    29. * @param id 删除客户的id
    30. */
    31. void delCustById(String id);
    32. /**
    33. * 批量删除客户
    34. * @param ids 所有客户id组成的字符串数组
    35. */
    36. void batchDel(String[] ids);
    37. /**
    38. * 根据条件查询客户信息
    39. * @param cust 封装了查询条件的bean,有客户名/客户性别/客户类型
    40. * @return 符合条件的客户集合
    41. */
    42. List<Cust> findCustByCond(Cust cust);
    43. /**
    44. * 分页查询客户信息
    45. * @param thispage 查询的页码
    46. * @param rowperpage 每页的记录数
    47. * @return 当前页的所有信息
    48. */
    49. Page pageCust(int thispage, int rowperpaper);
    50. }
    * `CustServiceImp.java`  service包下  实现类   内含需要Dao层具体实现的方法
    
    1. package com.lmd.service;
    2. import java.sql.Connection;
    3. import java.sql.SQLException;
    4. import java.util.List;
    5. import org.apache.commons.dbutils.DbUtils;
    6. import com.lmd.dao.CustDao;
    7. import com.lmd.domain.Cust;
    8. import com.lmd.domain.Page;
    9. import com.lmd.factory.BasicFactory;
    10. import com.lmd.util.DaoUtils;
    11. public class CustServiceImp implements CustService {
    12. //CustDao dao = (CustDao) BasicFactory.getFactory().getInstance("CustDao");
    13. CustDao dao = BasicFactory.getFactory().getInstance(CustDao.class);
    14. //CustService service = BasicFactory.getFactory().getInstance(CustService.class);
    15. @Override
    16. public void addCust(Cust cust) {
    17. //1.检查客户名是否已经存在
    18. if (dao.findUserByName(cust.getName()) != null) {
    19. throw new RuntimeException("用户名已经存在!!!");
    20. }
    21. //2.调用Dao中的方法增加用户,如果存在提示,如果不存在则调用dao增加客户方法
    22. dao.addCust(cust);
    23. }
    24. @Override
    25. public List<Cust> getAllCust() {
    26. return dao.getAllCust();
    27. }
    28. @Override
    29. public Cust findCustById(String id) {
    30. return dao.findCustById(id);
    31. }
    32. @Override
    33. public void updateCust(Cust cust) {
    34. dao.updateCust(cust);
    35. }
    36. @Override
    37. public void delCustById(String id) {
    38. dao.delCustById(id);
    39. }
    40. @Override
    41. public void batchDel(String[] ids) {
    42. //为了实现事务,使用了Connection,其是Dao层的东西
    43. //产生耦合,不好,后面会改进
    44. Connection conn = DaoUtils.getConn();
    45. try {
    46. conn.setAutoCommit(false);
    47. for (String id : ids) {
    48. dao.delCustByIdWithTrans(conn,id);
    49. }
    50. //int i = 1/0;//回滚测试
    51. DbUtils.commitAndCloseQuietly(conn);
    52. } catch (Exception e) {
    53. DbUtils.rollbackAndCloseQuietly(conn);
    54. e.printStackTrace();
    55. throw new RuntimeException(e);
    56. }
    57. }
    58. @Override
    59. public List<Cust> findCustByCond(Cust cust) {
    60. return dao.findCustByCond(cust);
    61. }
    62. @Override
    63. public Page pageCust(int thispage, int rowperpage) {
    64. Page page = new Page();
    65. //--当前页
    66. page.setThispage(thispage);
    67. //--每页记录数
    68. page.setRowperpage(rowperpage);
    69. //--总记录数
    70. int countrow = dao.getCountRow();
    71. page.setCountrow(countrow);
    72. //--总页数
    73. int countpage = countrow/rowperpage+(countrow%rowperpage==0?0:1);
    74. page.setCountpage(countpage);
    75. //--首页
    76. page.setFirstpage(1);
    77. //--尾页
    78. page.setLastpage(countpage);
    79. //--上一页
    80. page.setPrevpage(thispage==1?1:thispage-1);
    81. //--下一页
    82. page.setNextpage(thispage==countpage?countpage:thispage+1);
    83. //--当前页数据
    84. List<Cust> list = dao.getCustByPage((thispage-1)*rowperpage,rowperpage);
    85. page.setCustList(list);
    86. return page;
    87. }
    88. }
    * `DaoUtils.java` utils包下  访问数据源
    
    1. package com.lmd.util;
    2. import java.sql.Connection;
    3. import javax.sql.DataSource;
    4. import com.mchange.v2.c3p0.ComboPooledDataSource;
    5. public class DaoUtils {
    6. private static DataSource source = new ComboPooledDataSource();
    7. private DaoUtils(){
    8. }
    9. public static DataSource getSource(){
    10. return source;
    11. }
    12. public static Connection getConn(){
    13. try {
    14. return source.getConnection();
    15. } catch (Exception e) {
    16. e.printStackTrace();
    17. throw new RuntimeException(e);
    18. }
    19. }
    20. }
    * `CustDao.java` dao包下  接口  数据访问层(访问数据库)
    
    1. package com.lmd.dao;
    2. import java.sql.Connection;
    3. import java.sql.SQLException;
    4. import java.util.List;
    5. import com.lmd.domain.Cust;
    6. import com.lmd.domain.Page;
    7. public interface CustDao {
    8. /**
    9. * 检查客户名是否已经存在
    10. * @param name 客户名
    11. * @return 找不到,返回null
    12. */
    13. Cust findUserByName(String name);
    14. /**
    15. * 添加客户
    16. * @param cust
    17. */
    18. void addCust(Cust cust);
    19. /**
    20. * 查询所有客户信息组成的集合
    21. * @return 封装了所有客户信息的集合,若没有返回null
    22. */
    23. List<Cust> getAllCust();
    24. /**
    25. * 根据客户id查找客户信息
    26. * @param id 客户id
    27. * @return 最新客户信息bean
    28. */
    29. Cust findCustById(String id);
    30. /**
    31. * 修改客户信息
    32. * @param cust
    33. * @return 最新客户信息bean
    34. */
    35. void updateCust(Cust cust);
    36. /**
    37. * 根据id删除客户信息
    38. * @param id 删除客户的id
    39. */
    40. void delCustById(String id);
    41. /**
    42. * 根据id删除客户信息,并管理事务
    43. * @param conn
    44. * @param id 删除客户的id
    45. * @throws SQLException
    46. */
    47. void delCustByIdWithTrans(Connection conn, String id) throws SQLException;
    48. /**
    49. * 根据条件查询客户信息
    50. * @param cust 封装了查询条件的bean,有客户名/客户性别/客户类型
    51. * @return 符合条件的客户集合
    52. */
    53. List<Cust> findCustByCond(Cust cust);
    54. /**
    55. * 查询数据库有多少条记录
    56. * @return 记录数
    57. */
    58. int getCountRow();
    59. /**
    60. * 查询指定记录后多少条记录
    61. * @param from 从哪条记录后取
    62. * @param count 取的记录数
    63. * @return
    64. */
    65. List<Cust> getCustByPage(int from, int count);
    66. }
    * `CustDaoImp.java`  Dao层的接口实现类  (省写验证输入项是否正确或是否为空的方法)
    
    1. package com.lmd.dao;
    2. import java.sql.Connection;
    3. import java.sql.SQLException;
    4. import java.util.ArrayList;
    5. import java.util.List;
    6. import org.apache.commons.dbutils.QueryRunner;
    7. import org.apache.commons.dbutils.handlers.BeanHandler;
    8. import org.apache.commons.dbutils.handlers.BeanListHandler;
    9. import org.apache.commons.dbutils.handlers.ScalarHandler;
    10. import com.lmd.domain.Cust;
    11. import com.lmd.util.DaoUtils;
    12. public class CustDaoImp implements CustDao{
    13. @Override
    14. public Cust findUserByName(String name) {
    15. try {
    16. String sql = "select * from customer where name=?";
    17. QueryRunner runner = new QueryRunner(DaoUtils.getSource());
    18. return runner.query(sql, new BeanHandler<Cust>(Cust.class), name);
    19. } catch (SQLException e) {
    20. e.printStackTrace();
    21. throw new RuntimeException(e);
    22. }
    23. }
    24. @Override
    25. public void addCust(Cust cust) {
    26. String sql = "insert into customer values (null,?,?,?,?,?,?,?,?)";
    27. try {
    28. QueryRunner runner = new QueryRunner(DaoUtils.getSource());
    29. runner.update(sql, cust.getName(), cust.getGender(), cust.getBirthday()
    30. ,cust.getCellphone(), cust.getEmail(), cust.getPreference()
    31. ,cust.getType(), cust.getDescription());
    32. } catch (Exception e) {
    33. e.printStackTrace();
    34. throw new RuntimeException(e);
    35. }
    36. }
    37. @Override
    38. public List<Cust> getAllCust() {
    39. String sql = "select * from customer";
    40. try{
    41. QueryRunner runner = new QueryRunner(DaoUtils.getSource());
    42. return runner.query(sql, new BeanListHandler<Cust>(Cust.class));
    43. } catch (Exception e) {
    44. e.printStackTrace();
    45. throw new RuntimeException(e);
    46. }
    47. }
    48. @Override
    49. public Cust findCustById(String id) {
    50. try {
    51. String sql = "select * from customer where id=?";
    52. QueryRunner runner = new QueryRunner(DaoUtils.getSource());
    53. return runner.query(sql, new BeanHandler<Cust>(Cust.class), id);
    54. } catch (SQLException e) {
    55. e.printStackTrace();
    56. throw new RuntimeException(e);
    57. }
    58. }
    59. @Override
    60. public void updateCust(Cust cust) {
    61. try {
    62. String sql = "update customer set name=?,gender=?,birthday=?,cellphone=?"
    63. + ",email=?,preference=?,type=?,description=? where id=?";
    64. QueryRunner runner = new QueryRunner(DaoUtils.getSource());
    65. runner.update(sql, cust.getName(), cust.getGender(), cust.getBirthday()
    66. ,cust.getCellphone(), cust.getEmail(), cust.getPreference()
    67. ,cust.getType(), cust.getDescription(),cust.getId());
    68. } catch (SQLException e) {
    69. e.printStackTrace();
    70. throw new RuntimeException(e);
    71. }
    72. }
    73. @Override
    74. public void delCustById(String id) {
    75. try {
    76. String sql = "delete from customer where id=?";
    77. QueryRunner runner = new QueryRunner(DaoUtils.getSource());
    78. runner.update(sql,id);
    79. } catch (SQLException e) {
    80. e.printStackTrace();
    81. throw new RuntimeException(e);
    82. }
    83. }
    84. @Override
    85. public void delCustByIdWithTrans(Connection conn, String id) throws SQLException {
    86. String sql = "delete from customer where id=?";
    87. QueryRunner runner = new QueryRunner();
    88. runner.update(conn,sql,id);
    89. }
    90. @Override
    91. public List<Cust> findCustByCond(Cust cust) {
    92. String sql = "select * from customer where 1=1";
    93. List<Object> list = new ArrayList<Object>();
    94. if (cust.getName()!=null && !"".equals(cust.getName())) {
    95. sql += " and name like ?";
    96. list.add("%"+cust.getName()+"%");
    97. }
    98. if (cust.getGender()!=null && !"".equals(cust.getGender())) {
    99. sql += " and gender=?";
    100. list.add(cust.getGender());
    101. }
    102. if (cust.getType()!=null && !"".equals(cust.getType())) {
    103. sql += " and type=?";
    104. list.add(cust.getType());
    105. }
    106. try {
    107. QueryRunner runner = new QueryRunner(DaoUtils.getSource());
    108. if (list.size()<=0) {
    109. return runner.query(sql, new BeanListHandler<Cust>(Cust.class));
    110. }
    111. return runner.query(sql, new BeanListHandler<Cust>(Cust.class), list.toArray());
    112. } catch (SQLException e) {
    113. e.printStackTrace();
    114. throw new RuntimeException(e);
    115. }
    116. }
    117. @Override
    118. public int getCountRow() {
    119. String sql = "select count(*) from customer";
    120. try {
    121. QueryRunner runner = new QueryRunner(DaoUtils.getSource());
    122. return ((Long) runner.query(sql, new ScalarHandler())).intValue();
    123. } catch (SQLException e) {
    124. e.printStackTrace();
    125. throw new RuntimeException(e);
    126. }
    127. }
    128. @Override
    129. public List<Cust> getCustByPage(int from, int count) {
    130. String sql = "select * from customer limit ?,?";
    131. try {
    132. QueryRunner runner = new QueryRunner(DaoUtils.getSource());
    133. return runner.query(sql, new BeanListHandler<Cust>(Cust.class), from, count);
    134. } catch (SQLException e) {
    135. e.printStackTrace();
    136. throw new RuntimeException(e);
    137. }
    138. }
    139. }
    (1)、添加用户
    * `addCust.jsp`   添加用户界面
    
    1. <body style="text-align: center;">
    2. <h1>客户管理系统_添加客户</h1>
    3. <form action="${pageContext.request.contextPath }/AddCustServlet" method="post">
    4. <table align="center" border="1">
    5. <tr>
    6. <td>客户姓名</td>
    7. <td><input type="text" name="name" /></td>
    8. </tr>
    9. <tr>
    10. <td>客户性别</td>
    11. <td>
    12. <input type="radio" name="gender" value="男" checked="checked" />
    13. <input type="radio" name="gender" value="女" />
    14. </td>
    15. </tr>
    16. <tr>
    17. <td>客户生日</td>
    18. <td><input type="text" name="birthday" /></td>
    19. </tr>
    20. <tr>
    21. <td>手机号码</td>
    22. <td><input type="text" name="cellphone" /></td>
    23. </tr>
    24. <tr>
    25. <td>电子邮件</td>
    26. <td><input type="text" name="email" /></td>
    27. </tr>
    28. <tr>
    29. <td>客户爱好</td>
    30. <td>
    31. <input type="checkbox" name="preference" value="篮球" />篮球(钢琴、舞蹈)
    32. </td>
    33. </tr>
    34. <tr>
    35. <td>客户类型</td>
    36. <td>
    37. <select name="type">
    38. <option value="钻石用户">钻石用户</option>(白金、白银、青铜等等)
    39. </select>
    40. </td>
    41. </tr>
    42. <tr>
    43. <td>备注信息</td>
    44. <td><textarea rows="6" cols="30" name = "description"></textarea></td>
    45. </tr>
    46. <tr>
    47. <td colspan="2">
    48. <input type="submit" value="添加用户" />
    49. </td>
    50. </tr>
    51. </table>
    52. </form>
    53. </body>

    * `AddCustServlet.java   添加用户实现
    
    1. package com.lmd.web;
    2. import java.io.IOException;
    3. import javax.servlet.ServletException;
    4. import javax.servlet.annotation.WebServlet;
    5. import javax.servlet.http.HttpServlet;
    6. import javax.servlet.http.HttpServletRequest;
    7. import javax.servlet.http.HttpServletResponse;
    8. import org.apache.commons.beanutils.BeanUtils;
    9. import com.lmd.domain.Cust;
    10. import com.lmd.factory.BasicFactory;
    11. import com.lmd.service.CustService;
    12. /**
    13. * Servlet implementation class AddCustServlet
    14. */
    15. @WebServlet("/AddCustServlet")
    16. public class AddCustServlet extends HttpServlet {
    17. public void doGet(HttpServletRequest request, HttpServletResponse response)
    18. throws ServletException, IOException {
    19. request.setCharacterEncoding("UTF-8");
    20. response.setContentType("text/html; charset=UTF-8");
    21. CustService service = BasicFactory.getFactory().getInstance(CustService.class);
    22. // 1.封装数据,省写校验数据
    23. Cust cust = new Cust();
    24. try {
    25. BeanUtils.populate(cust, request.getParameterMap());
    26. //单独处理爱好
    27. String[] prfs = request.getParameterValues("preference");
    28. StringBuffer buffer = new StringBuffer();
    29. for (String pref : prfs) {
    30. buffer.append(pref+",");
    31. }
    32. String pref = buffer.substring(0, buffer.length()-1);
    33. cust.setPreference(pref);
    34. } catch (Exception e) {
    35. e.printStackTrace();
    36. throw new RuntimeException(e);
    37. }
    38. // 2.调用Service层添加客户的方法
    39. service.addCust(cust);//Ctrl+1添加方法
    40. //3.重定向回到主页
    41. response.sendRedirect(request.getContextPath()+"/index.jsp");
    42. }
    43. }
    (2)、查询用户列表、修改、删除及条件查询
    * `listCust.jsp`   显示所有用户信息、修改客户信息、条件查询客户信息、删除客户   界面
    
    1. <%@ page language="java" contentType="text/html; charset=UTF-8"%>
    2. <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
    3. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    4. <html>
    5. <head>
    6. <script type="text/javascript">
    7. function checkAll(allC){
    8. var otherChs = document.getElementsByName("delId");
    9. for(var i=0; i<otherChs.length; i++){
    10. otherChs[i].checked = allC.checked;
    11. }
    12. }
    13. </script>
    14. </head>
    15. <body style="text-align: center;">
    16. <h1>客户管理系统_客户列表页面</h1>
    17. <form action="${pageContext.request.contextPath }/FindCustByCondServlet" method="post"">
    18. 客户姓名:<input type="text" name="name" value="${param.name }"/>
    19. 客户性别:<input type="radio" name="gender" value="男"
    20. <c:if test="${param.gender=='男'}">checked='checked'</c:if>
    21. />男
    22. <input type="radio" name="gender" value="女"
    23. <c:if test="${param.gender=='女'}">checked='checked'</c:if>
    24. />女
    25. <input type="radio" name="gender" value="" />
    26. 客户类型:<select name="type">
    27. <option value=""></option>
    28. <option value="钻石用户"
    29. <c:if test="${param.type=='钻石用户' }">
    30. selected='selected'
    31. </c:if>
    32. >钻石用户</option>
    33. <option value="白金用户"
    34. <c:if test="${param.type=='白金用户' }">
    35. selected='selected'
    36. </c:if>
    37. >白金用户</option>
    38. <option value="黄金用户"
    39. <c:if test="${param.type=='黄金用户' }">
    40. selected='selected'
    41. </c:if>
    42. >黄金用户</option>
    43. <option value="白银用户"
    44. <c:if test="${param.type=='白银用户' }">
    45. selected='selected'
    46. </c:if>
    47. >白银用户</option>
    48. <option value="青铜用户"
    49. <c:if test="${param.type=='青铜用户' }">
    50. selected='selected'
    51. </c:if>
    52. >青铜用户</option>
    53. <option value="普通用户"
    54. <c:if test="${cust.type=='普通用户' }">
    55. selected='selected'
    56. </c:if>
    57. >普通用户</option>
    58. </select>
    59. <input type="submit" value="条件查询用户" />
    60. </form>
    61. <form action="${pageContext.request.contextPath }/BatchDelCustServlet" method="post">
    62. <table border="1" width="100%" align="center">
    63. <tr>
    64. <th><input type="checkbox" onchange="checkAll(this)" />全选</th>
    65. <th>客户姓名</th>
    66. <th>客户性别</th>
    67. <th>出生日期</th>
    68. <th>手机号码</th>
    69. <th>电子邮件</th>
    70. <th>客户爱好</th>
    71. <th>客户类型</th>
    72. <th>描述信息</th>
    73. <th>修改</th>
    74. <th>删除</th>
    75. </tr>
    76. <c:forEach items="${requestScope.list }" var="cust">
    77. <tr>
    78. <!-- 使用标签解决引导入侵,不让字符转义 -->
    79. <td><input type="checkbox" name="delId" value="${cust.id }" /></td>
    80. <td><c:out value="${cust.name }"/></td>
    81. <td><c:out value="${cust.gender }"/></td>
    82. <td><c:out value="${cust.birthday }"/></td>
    83. <td><c:out value="${cust.cellphone }"/></td>
    84. <td><c:out value="${cust.email }"/></td>
    85. <td><c:out value="${cust.preference }"/></td>
    86. <td><c:out value="${cust.type }"/></td>
    87. <td><c:out value="${cust.description }"/></td>
    88. <td><a href="${pageContext.request.contextPath }/CustInfoServlet?id=${cust.id}">修改</a></td>
    89. <td><a href="${pageContext.request.contextPath }/DelCustServlet?id=${cust.id}">删除</a></td>
    90. </tr>
    91. </c:forEach>
    92. </table>
    93. <input type="submit" value="批量删除" />
    94. </form>
    95. </body>
    96. </html>


    * ListCustServlet.java 显示所有用户信息实现

    1. package com.lmd.web;
    2. import java.io.IOException;
    3. import java.util.List;
    4. import javax.servlet.ServletException;
    5. import javax.servlet.annotation.WebServlet;
    6. import javax.servlet.http.HttpServlet;
    7. import javax.servlet.http.HttpServletRequest;
    8. import javax.servlet.http.HttpServletResponse;
    9. import com.lmd.domain.Cust;
    10. import com.lmd.factory.BasicFactory;
    11. import com.lmd.service.CustService;
    12. /**
    13. * Servlet implementation class ListCustServlet
    14. */
    15. @WebServlet("/ListCustServlet")
    16. public class ListCustServlet extends HttpServlet {
    17. public void doGet(HttpServletRequest request, HttpServletResponse response)
    18. throws ServletException, IOException {
    19. CustService service = BasicFactory.getFactory().getInstance(CustService.class);
    20. //1、调用service中查询所有客户的方法
    21. List<Cust> list = service.getAllCust();
    22. //2、将查找的信息存在request域,请求转发到listCust.jsp页面进行展示
    23. request.setAttribute("list", list);
    24. request.getRequestDispatcher("/listCust.jsp").forward(request, response);
    25. }
    26. }
    1)、修改客户信息
     * `updateCust.jsp`  修改客户信息界面
    
    1. <%@ page language="java" contentType="text/html; charset=UTF-8"%>
    2. <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
    3. <%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
    4. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    5. <html>
    6. <head>
    7. </head>
    8. <body style="text-align: center;">
    9. <h1>客户管理系统_修改客户</h1>
    10. <form action="${pageContext.request.contextPath }/UpdateCustServlet" method="post">
    11. <input type="hidden" name="id" value="${cust.id }" />
    12. <table align="center" border="1">
    13. <tr>
    14. <td>客户姓名</td>
    15. <td><input type="text" name="name" value="${cust.name }" readonly="readonly" style="background: silver;"/></td>
    16. </tr>
    17. <tr>
    18. <td>客户性别</td>
    19. <td>
    20. <input type="radio" name="gender" value="男"
    21. <c:if test="${cust.gender=='男'}">checked='checked'</c:if>
    22. />男
    23. <input type="radio" name="gender" value="女"
    24. <c:if test="${cust.gender=='女'}">checked='checked'</c:if>
    25. />女
    26. </td>
    27. </tr>
    28. <tr>
    29. <td>客户生日</td>
    30. <td><input type="text" name="birthday" value="${cust.birthday }" /></td>
    31. </tr>
    32. <tr>
    33. <td>手机号码</td>
    34. <td><input type="text" name="cellphone" value="${cust.cellphone }" /></td>
    35. </tr>
    36. <tr>
    37. <td>电子邮件</td>
    38. <td><input type="text" name="email" value="${cust.email }" /></td>
    39. </tr>
    40. <tr>
    41. <td>客户爱好</td>
    42. <td>
    43. <input type="checkbox" name="preference" value="篮球"
    44. <c:forTokens items="${cust.preference }" delims="," var="pref">
    45. <c:if test="${pref=='篮球'}">
    46. checked='checked'
    47. </c:if>
    48. </c:forTokens>
    49. />篮球
    50. <input type="checkbox" name="preference" value="钢琴"
    51. <c:if test="${fn:contains(cust.preference, '钢琴') }">
    52. checked='checked'
    53. </c:if>
    54. />钢琴
    55. <input type="checkbox" name="preference" value="舞蹈"
    56. <c:if test="${fn:contains(cust.preference, '舞蹈') }">
    57. checked='checked'
    58. </c:if>
    59. />舞蹈
    60. <input type="checkbox" name="preference" value="跑步"
    61. <c:if test="${fn:contains(cust.preference, '跑步') }">
    62. checked='checked'
    63. </c:if>
    64. />跑步
    65. </td>
    66. </tr>
    67. <tr>
    68. <td>客户类型</td>
    69. <td>
    70. <select name="type">
    71. <option value="钻石用户"
    72. <c:if test="${cust.type=='钻石用户' }">
    73. selected='selected'
    74. </c:if>
    75. >钻石用户</option>
    76. <option value="白金用户"
    77. <c:if test="${cust.type=='白金用户' }">
    78. selected='selected'
    79. </c:if>
    80. >白金用户</option>
    81. <option value="黄金用户"
    82. <c:if test="${cust.type=='黄金用户' }">
    83. selected='selected'
    84. </c:if>
    85. >黄金用户</option>
    86. <option value="白银用户"
    87. <c:if test="${cust.type=='白银用户' }">
    88. selected='selected'
    89. </c:if>
    90. >白银用户</option>
    91. <option value="青铜用户"
    92. <c:if test="${cust.type=='青铜用户' }">
    93. selected='selected'
    94. </c:if>
    95. >青铜用户</option>
    96. <option value="普通用户"
    97. <c:if test="${cust.type=='普通用户' }">
    98. selected='selected'
    99. </c:if>
    100. >普通用户</option>
    101. </select>
    102. </td>
    103. </tr>
    104. <!-- 造成引导入侵,例如输入javascript代码,会弹出结果 -->
    105. <tr>
    106. <td>备注信息</td>
    107. <td><textarea rows="6" cols="30" name="description">${cust.description }</textarea></td>
    108. </tr>
    109. <tr>
    110. <td colspan="2">
    111. <a href="${pageContext.request.contextPath}/updateCust.jsp"><input type="submit" value="添加用户"/></a>
    112. </td>
    113. </tr>
    114. </table>
    115. </form>
    116. </body>
    117. </html>

     * `UpdateCustServlet.java`  修改客户信息实现
    
    1. package com.lmd.web;
    2. import java.io.IOException;
    3. import javax.servlet.ServletException;
    4. import javax.servlet.annotation.WebServlet;
    5. import javax.servlet.http.HttpServlet;
    6. import javax.servlet.http.HttpServletRequest;
    7. import javax.servlet.http.HttpServletResponse;
    8. import org.apache.commons.beanutils.BeanUtils;
    9. import com.lmd.domain.Cust;
    10. import com.lmd.factory.BasicFactory;
    11. import com.lmd.service.CustService;
    12. /**
    13. * Servlet implementation class UpdateCustServlet
    14. */
    15. @WebServlet("/UpdateCustServlet")
    16. public class UpdateCustServlet extends HttpServlet {
    17. public void doGet(HttpServletRequest request, HttpServletResponse response)
    18. throws ServletException, IOException {
    19. CustService service = BasicFactory.getFactory().getInstance(CustService.class);
    20. // 1.封装数据,省写校验数据
    21. Cust cust = new Cust();
    22. try {
    23. BeanUtils.populate(cust, request.getParameterMap());
    24. //单独处理爱好
    25. String[] prfs = request.getParameterValues("preference");
    26. StringBuffer buffer = new StringBuffer();
    27. for (String pref : prfs) {
    28. buffer.append(pref+",");
    29. }
    30. String pref = buffer.substring(0, buffer.length()-1);
    31. cust.setPreference(pref);
    32. } catch (Exception e) {
    33. e.printStackTrace();
    34. throw new RuntimeException(e);
    35. }
    36. // 2.调用Service层修改客户的方法
    37. service.updateCust(cust);//Ctrl+1添加方法
    38. //3.重定向回到客户列表页面
    39. request.getRequestDispatcher("/ListCustServlet").forward(request, response);
    40. }
    41. }
    2)、单个删除客户
     * `ListCustServlet.java`   单个删除客户实现
    
    1. package com.lmd.web;
    2. import java.io.IOException;
    3. import javax.servlet.ServletException;
    4. import javax.servlet.annotation.WebServlet;
    5. import javax.servlet.http.HttpServlet;
    6. import javax.servlet.http.HttpServletRequest;
    7. import javax.servlet.http.HttpServletResponse;
    8. import org.apache.commons.beanutils.BeanUtils;
    9. import com.lmd.domain.Cust;
    10. import com.lmd.factory.BasicFactory;
    11. import com.lmd.service.CustService;
    12. /**
    13. * Servlet implementation class DelCustServlet
    14. */
    15. @WebServlet("/DelCustServlet")
    16. public class DelCustServlet extends HttpServlet {
    17. public void doGet(HttpServletRequest request, HttpServletResponse response)
    18. throws ServletException, IOException {
    19. CustService service = BasicFactory.getFactory().getInstance(CustService.class);
    20. // 1.获取要删除的客户id
    21. String id = request.getParameter("id");
    22. // 2.调用Service层id删除客户的方法
    23. service.delCustById(id);//Ctrl+1添加方法
    24. //3.转发到客户列表页面
    25. request.getRequestDispatcher("/ListCustServlet").forward(request, response);
    26. }
    27. public void doPost(HttpServletRequest request, HttpServletResponse response)
    28. throws ServletException, IOException {
    29. doGet(request, response);
    30. }
    31. }
    3)、批量删除客户
     * `ListCustServlet.java`   显示所有用户信息实现
    
    1. package com.lmd.web;
    2. import java.io.IOException;
    3. import javax.servlet.ServletException;
    4. import javax.servlet.annotation.WebServlet;
    5. import javax.servlet.http.HttpServlet;
    6. import javax.servlet.http.HttpServletRequest;
    7. import javax.servlet.http.HttpServletResponse;
    8. import org.apache.commons.beanutils.BeanUtils;
    9. import com.lmd.domain.Cust;
    10. import com.lmd.factory.BasicFactory;
    11. import com.lmd.service.CustService;
    12. /**
    13. * Servlet implementation class BatchDelCustServlet
    14. */
    15. @WebServlet("/BatchDelCustServlet")
    16. public class BatchDelCustServlet extends HttpServlet {
    17. public void doGet(HttpServletRequest request, HttpServletResponse response)
    18. throws ServletException, IOException {
    19. CustService service = BasicFactory.getFactory().getInstance(CustService.class);
    20. // 1.获取所有删除的客户id
    21. String[] ids = request.getParameterValues("delId");
    22. // 2.调用Service层批量删除客户的方法
    23. service.batchDel(ids);//Ctrl+1添加方法
    24. //3.转发到客户列表页面
    25. request.getRequestDispatcher("/ListCustServlet").forward(request, response);
    26. }
    27. }
    (3)、分页查询用户列表
     * `pageCust.jsp`   分页显示用户信息界面
    
    1. <%@ page language="java" contentType="text/html; charset=UTF-8"%>
    2. <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
    3. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    4. <html>
    5. <head>
    6. <script type="text/javascript">
    7. function changePage(obj){
    8. if(isNaN(obj.value)){
    9. alert("必须是数字!!!");
    10. obj.value = ${page.thispage};
    11. } else{
    12. if(obj.value<=0 || obj.value>${page.countpage}){
    13. alert("必须是有效范围内的页码!!!");
    14. obj.value = ${page.thispage};
    15. return;
    16. } else {
    17. window.location.href = "${pageContext.request.contextPath }/PageCustServlet?thispage="+obj.value;
    18. }
    19. }
    20. }
    21. </script>
    22. </head>
    23. <body style="text-align: center;">
    24. <h1>客户管理系统_客户列表页面</h1>
    25. <table border="1" width="100%" align="center">
    26. <tr>
    27. <th>客户姓名</th>
    28. <th>客户性别</th>
    29. <th>出生日期</th>
    30. <th>手机号码</th>
    31. <th>电子邮件</th>
    32. <th>客户爱好</th>
    33. <th>客户类型</th>
    34. <th>描述信息</th>
    35. <th>修改</th>
    36. <th>删除</th>
    37. </tr>
    38. <c:forEach items="${requestScope.page.custList }" var="cust">
    39. <tr>
    40. <!-- 使用标签解决引导入侵,不让字符转义 -->
    41. <td><c:out value="${cust.name }"/></td>
    42. <td><c:out value="${cust.gender }"/></td>
    43. <td><c:out value="${cust.birthday }"/></td>
    44. <td><c:out value="${cust.cellphone }"/></td>
    45. <td><c:out value="${cust.email }"/></td>
    46. <td><c:out value="${cust.preference }"/></td>
    47. <td><c:out value="${cust.type }"/></td>
    48. <td><c:out value="${cust.description }"/></td>
    49. <td><a href="${pageContext.request.contextPath }/CustInfoServlet?id=${cust.id}">修改</a></td>
    50. <td><a href="${pageContext.request.contextPath }/DelCustServlet?id=${cust.id}">删除</a></td>
    51. </tr>
    52. </c:forEach>
    53. </table>
    54. <div style="text-align: center;">
    55. ${page.countrow }条记录&nbsp;共${page.countpage }页&nbsp;
    56. <a href="${pageContext.request.contextPath }/PageCustServlet?thispage=${page.firstpage}">首页</a>
    57. <a href="${pageContext.request.contextPath }/PageCustServlet?thispage=${page.prevpage}">上一页</a>
    58. <!-- 分页逻辑开始 -->
    59. <c:if test="${page.countpage<=5 }">
    60. <c:set var="begin" value="1" scope="page"></c:set>
    61. <c:set var="end" value="${page.countpage }" scope="page"></c:set>
    62. </c:if>
    63. <c:if test="${page.countpage>5 }">
    64. <c:choose>
    65. <c:when test="${page.thispage<=3 }">
    66. <c:set var="begin" value="1" scope="page"></c:set>
    67. <c:set var="end" value="5" scope="page"></c:set>
    68. </c:when>
    69. <c:when test="${page.thispage>=page.countpage-2 }">
    70. <c:set var="begin" value="${page.countpage-4 }" scope="page"></c:set>
    71. <c:set var="end" value="${page.countpage}" scope="page"></c:set>
    72. </c:when>
    73. <c:otherwise>
    74. <c:set var="begin" value="${page.thispage-2 }" scope="page"></c:set>
    75. <c:set var="end" value="${page.thispage+2}" scope="page"></c:set>
    76. </c:otherwise>
    77. </c:choose>
    78. </c:if>
    79. <c:forEach begin="${begin }" end="${end }" var="i">
    80. <c:if test="${i==page.thispage }">
    81. ${i }
    82. </c:if>
    83. <c:if test="${i!=page.thispage }">
    84. <a href="${pageContext.request.contextPath }/PageCustServlet?thispage=${i}">${i }</a>
    85. </c:if>
    86. </c:forEach>
    87. <!-- 分页逻辑结束 -->
    88. <a href="${pageContext.request.contextPath }/PageCustServlet?thispage=${page.nextpage}">下一页</a>
    89. <a href="${pageContext.request.contextPath }/PageCustServlet?thispage=${page.lastpage}">尾页</a>
    90. 跳转到<input type="text" value="${page.thispage }" size="1" onchange="changePage(this)"/>页
    91. </div>
    92. </body>
    93. </html>


    * PageCustServle.java 显示所有用户信息实现

    1. package com.lmd.web;
    2. import java.io.IOException;
    3. import java.util.List;
    4. import javax.servlet.ServletException;
    5. import javax.servlet.annotation.WebServlet;
    6. import javax.servlet.http.HttpServlet;
    7. import javax.servlet.http.HttpServletRequest;
    8. import javax.servlet.http.HttpServletResponse;
    9. import com.lmd.domain.Cust;
    10. import com.lmd.domain.Page;
    11. import com.lmd.factory.BasicFactory;
    12. import com.lmd.service.CustService;
    13. /**
    14. * Servlet implementation class PageCustServlet
    15. */
    16. @WebServlet("/PageCustServlet")
    17. public class PageCustServlet extends HttpServlet {
    18. public void doGet(HttpServletRequest request, HttpServletResponse response)
    19. throws ServletException, IOException {
    20. CustService service = BasicFactory.getFactory().getInstance(CustService.class);
    21. //1、获取当前要显示的页和每页记录数
    22. int thispage = Integer.parseInt(request.getParameter("thispage"));
    23. int rowperpage = 5;
    24. //2、调用service中分页查询客户的方法,查找出客户信息
    25. Page page = service.pageCust(thispage,rowperpage);
    26. //2、存入request域,请求转发到pageCust.jsp页面进行展示
    27. request.setAttribute("page", page);
    28. request.getRequestDispatcher("/pageCust.jsp").forward(request, response);
    29. }
    30. }
    posted @ 2017-03-08 17:05  欧阳蝶梦  阅读(214)  评论(0编辑  收藏  举报