JavaEE课程复习1--数据库相关操作

首页 > JavaEE课程复习1--数据库相关操作 > 列表

JavaEE课程复习1--数据库相关操作

〇、本模块内容简介

30=(DB5+前端5+Web Core15+Project5)

Junit、注解

MySQL、JDBC、JDBCUtils、c3p0、Druid连接池及工具类、JDBCTemplate

---------------------------------------------------------------------------------------------

HTML、CSS、JavaScript、BootStrap、Xml、Jsoup、JQuery

----------------------------------------------------------------------------------------------

Tomcat、Servlet、Request、Response、Cookie、Session、JSP、EL、JSTL、Maven、Redis、Nginx、Linux

-------------------------------------------------------------------------------------------------------------------------------------------------------

基于缓存与异步技术的旅游网设计

------------------------------------------

一、基础增强

1、Junit单元测试

  • 测试分类:黑盒、白盒、单元
  • 使用步骤:
    • 定义类:*.test.类名Test,如com.itheima.test.UserTest
    • 定义方法:testXxx(),如testAdd()
    • 加@Test注解,并导入依赖
    • 使用断言处理结果:Assert.assertEquals(期望的结果,运算的结果);
  • @Before和@After用于资源的申请与释放

2、注解

  • 概念:Annotation,在jdk1.5后,说明程序中的类、方法、变量、参数和包(给计算机看的注释)
  • 作用:编译检查@Override重写、生成文档@Documented、使用反射进行代码分析
  • 学习
    • 预定义注解/内置注解
      • @Override:检查是否继承自父类
      • @Deprecated:标记过时的方法,编译警告及删除线。如Date类建议修改为Calender类
      • @SupressWarnings("all"):忽略注解声明的警告
    • 自定义注解
      • 格式
元注解
@Documented //注解会抽取到文档中
@Retention(RUNTIME)//注解被保留的阶段:Source/Class/Runtime
@Target(TYPE,METHOD,FIELD)//作用位置:类、方法、成员变量
@Inherited //加注解的类的子类会自动继承父类注解
public @interface 注解名称(){ 属性列表,如
   public abstaract String show(); }
      • 本质:反编译后发现是一个继承Annotation的接口(注释类型扩展的公共接口)
      • 属性:可以定义的抽象方法,使用时需要赋值
        • 返回值类型:不包括void和对象
  • 程序中的解析注解:获取注解属性值
    • 获取注解定义位置的对象(Class,Method,Field)
    • 获取指定注解getAnnotation(Class)--相当于内存中生成一个注解接口的子类实现对象
 1 package com.liujinhui.Day1209BaseEnhance.annotation;
 2 import java.io.InputStream;
 3 import java.lang.reflect.Method;
 4 import java.util.Properties;
 5 /*
 6     假设的框架类
 7     改配置文件使程序的扩展性更强,配置文件中使用了全类名,则使用了反射机制
 8 * */
 9 @Pro(className = "com.liujinhui.Day1209BaseEnhance.annotation.Demo1",methodName = "show")
10 //要写全类名
11 public class ReflectTest {
12     /**
13      * @author: Liu Jinhui
14      * @description: 创建任意对象
15      * @date: 2020/12/9 20:42
16      * @return  * @param null
17      */
18     public static void main(String[] args) throws Exception{
19         //可以创建任意类的对象,可以执行任意方法
20         /*
21             前提:不能改变该类的任何代码,可以创建任意类的对象,可以执行任意方法
22         * */
23         //1.解析注解
24         //1.1获取该类的字节码文件对象
25         ClassReflectTest reflectTestClass = ReflectTest.class;
26         //2.获取上面的注解对象
27         //method也有getAnno
28         Pro an = reflectTestClass.getAnnotation(Pro.class);
29         //其实就是在内存中生成了一个该注解接口的子类实现对象
30         /*
31             public class ProIMpl implements Pro{
32                    public String className(){
33                         return  "com.liujinhui.Day1209BaseEnhance.annotation.Demo1";
34                    }
35                    public String methodName(){
36                         return "show";
37                    }
38          */
39         //3.调用注解对象中调用的抽象方法,获取返回值
40         String className = an.className();
41         String methodName = an.methodName();
42         System.out.println(className+methodName);
43         //4.加载该类进内存
44         Class cls = Class.forName(className);
45         //5.创建对象
46         Object obj = cls.newInstance();
47         //6.获取方法对象
48         Method method = cls.getMethod(methodName);
49         //7.执行方法
50         method.invoke(obj);
51     }
52 }
1 /*
2     描述需要执行的类名和方法名
3  */
4 @Target({ElementType.TYPE})
5 @Retention(RetentionPolicy.RUNTIME)
6 public @interface Pro {
7     String className();
8     String methodName();
9 }

3、基于注解解析的自定义测试框架

使用技术:字符缓冲输出流、注解解析

 1 package com.liujinhui.Day1209BaseEnhance.annotation.demo;
 2 
 3 import java.lang.annotation.ElementType;
 4 import java.lang.annotation.Retention;
 5 import java.lang.annotation.RetentionPolicy;
 6 import java.lang.annotation.Target;
 7 
 8 @Target(value = {ElementType.METHOD})
 9 @Retention(RetentionPolicy.RUNTIME)
10 @interface Check {
11 }
 1 package com.liujinhui.Day1209BaseEnhance.annotation.demo;
 2 
 3 /**
 4  * 小明定义的计算器类
 5  * 需要测试是否有错误
 6  */
 7 public class Calculator {
 8     //加法
 9     @Check
10     public void add(){
11         System.out.println("1+0="+(1+0));
12     }
13     //减法
14     @Check
15     public void sub(){
16         System.out.println("1 - 0 ="+(1 - 0));
17     }
18     //乘法
19     @Check
20     public void mul(){
21         System.out.println("1*0="+(1*0));
22     }
23     //除法
24     @Check
25     public void div(){
26         System.out.println("1/0="+(1/0));
27     }
28     //结果
29     public void show(){
30         System.out.println("永无bug...");
31     }
32 }
 1 package com.liujinhui.Day1209BaseEnhance.annotation.demo;
 2 
 3 import java.io.BufferedWriter;
 4 import java.io.FileWriter;
 5 import java.io.IOException;
 6 import java.lang.reflect.InvocationTargetException;
 7 import java.lang.reflect.Method;
 8 
 9 /**
10  * 简单的测试框架
11  * 当主方法执行后,会自动执行被检测的所有方法(加了@Check的方法)
12  * 判断方法是否有异常,并记录到文件中
13  */
14 public class TestCheck {
15     public static void main(String[] args) throws IOException {
16         //1.创建计算器对象
17         Calculator c = new Calculator();
18         //2.获取字节码文件对象
19         Class cls = c.getClass();
20         //3.获取所有的方法
21         Method[] methods = cls.getMethods();
22         int number=0;//记录异常出现的次数
23         BufferedWriter bw=new BufferedWriter(new FileWriter("bug.txt"));
24         for (Method method : methods) {
25             //4.判断方法上是否有check注解
26             if (method.isAnnotationPresent(Check.class)) {
27                 //判断当前方法上有无指定注解
28                 //5.有就执行该方法
29                 try {
30                     method.invoke(c);
31                 } catch (Exception e) {
32                     //6.捕获异常
33                     number++;
34                     //记录到文件中
35                     bw.write(method.getName() + "方法出异常了");
36                     bw.newLine();
37                     bw.write("异常的名称:" + e.getCause().getClass().getSimpleName());
38                     bw.newLine();
39                     bw.write("异常的原因:" + e.getCause().getMessage());
40                     bw.newLine();
41                     bw.write("-----------------------");
42                 }
43             }
44         }
45         bw.write("本次测试共出现"+ number +"次异常");
46         bw.flush();
47         bw.close();
48     }
49 }

二、MySQL基础

1、概念

  • 持久化和管理数据的仓库
  • 常用

2、DB软件的基本使用

  • 安装
  • 卸载
  • 配置-启动、关闭和登录
    • 服务:services.msc
    • 命令:net start mysql/net stop mysql
    • 远程登录:-h127.0.0.1或-host=127.0.0.1

3、SQL语句

  • 概念:结构化查询语言,关系型的准则;各种数据库有对应方言
  • 语法:
    • 注释:-- xx或/* xx */或# xx(特有)
  • 分类:
    • DDL:建库、建表
    • DML:CUD
      • 改表名:alter table 表名 rename to 新表名;
      • 改字符集:alter table stu character set utf8;
      • 改列名:alter table 表名 change 列名 新列名 新的类型;
      • 删表:DELETE和TRUNCATE(先删再建效率高)
    • DQL:Retrieve
    • DCL:权限控制

三、MySQL约束

1、DQL查询语句

  • 排序
  • 聚合:排除空值,空值需要使用IFNULL函数
  • 分组查询:where不能加聚合函数,在分组前限定分组的记录
  • 分页查询:
    • limit 开始索引,每页条数
    • 公式:开始索引=(当前页码-1)*每页条数
    • 如:(1-1)*3,(2-1)*3,(3-1)*3

2、约束

  • 主键(自增长)、非空、唯一、外键(constraint)
  • 外键-级联操作ON DELETE/UPDATE CASCADE

3、数据库的设计:多表关系

4、数据库设计范式

5、数据库的备份还原

  • 备份:mysqldum -uroot -proot ssm d://db1.sql
  • 还原:source d://db1.sql

四、MySQL多表和事务

1、多表查询

  • 笛卡尔积(×)
  • 内连接:显式where,隐式inner join 表名 on 条件
  • 外连接:
    • 左外:左表所有--left outer join
    • 右外:右表所有--right outer join
  • 子查询:
    • 单行单列:条件运算符
    • 多行单列:in
    • 多行多列:作为虚拟表

2、事务

  • 概念:start transaction、commit(MySQL自动提交1,改为手动提交SET @@autocommit=0;)、rollback(放到最后)
  • 特征:原子性、一致性※、持久性、隔离性
  • 隔离级别:
    • 脏读、不可重复读/虚读、幻读

3、DCL

  • SQL分类:DDL是操作数据库和表,DML、DQL是操作表中数据,DCL是管理用户权限
  • 用户管理:添加删除用户,修改用户、忘记密码解决
  • 权限管理:查询(SHOW GRANTS FOR)、授予(GRANT ALL ON *.* TO )、撤销权限(REVOKE SELECT ON *.* FROM root@主机名)

五、JDBC

1、概念:Java Database Connectivity

  • 数据库操作规则,本质是接口,真正执行的是实现类

2、对象详解

  • DriverManager--驱动管理对象
    • 注册驱动:Class.forName("com.mysql.jdbc.Driver");---jdk1.5后可以省略,把字节码文件加载至内存
      • Driver类内的静态代码块实现了DriverManager类的registerDriver(Driver driver) 方法,本质相同
    • 获取连接:Connection conn= DriverManager.getConnection("jdbc:mysql://localhost:3306/db3","root","root");
  • Connection--数据库连接对象
    • 获取SQL执行对象:Statement stmt = conn.createStatement();
    • 事务管理
      • 开启事务void setAutoCommit(boolean autoCommit)
      • 提交事务void commit()
      • 回滚事务void rollback()
  • Statement--执行SQL的对象
    • 执行任意SQL:boolean execute()
    • 执行DML和DDL:int executeUpdate()
    • 执行DQL:ResultSet executeQuery(String sql)
  • ResultSet--结果集对象
    • 通过游标,获取每一行  rs.next()
    • 获取指定类型数据: rs.getInt(1);---参数为列编号或列名
  • PreparedStatement--解决SQL注入的预处理对象
    • 之前:字符串拼接,会导致SQL注入安全性问题
    • 解决:
      • pstmt=conn.prepareStatement(String sql) ;---使用从1开始做占位符
      • pstmt.setString(1,"zhangsan");

3、JDBC工具类抽取:JDBCUtils

  • 通过配置文件jdbc.properties配置数据库连接信息
  • 在工具类中设置获取连接方法和释放资源的方法
  1 package cn.itcast.utils;
  2 import java.io.FileReader;
  3 import java.io.IOException;
  4 import java.net.URL;
  5 import java.sql.*;
  6 import java.util.Properties;
  7 
  8 /**
  9  * JDBC工具类
 10  * 一个获取连接的方法
 11  * 一个释放资源的方法
 12  */
 13 public class JDBCUtils {
 14     private static String url;
 15     private static String user;
 16     private static String password;
 17     private static String driver;
 18     /**
 19      * 文件的读取,只需要读取一次就可以拿到这些值
 20      * 方案:通过静态代码块
 21      */
 22     static{
 23         //读取配置资源文件,获取值
 24         //BufeeredReader。。。麻烦
 25         try {
 26             //1.创建Properties集合类
 27             Properties prop=new Properties();
 28             //2.加载文件,代码提示
 29             //prop.load(new FileReader("src/jdbc.properties"));
 30             //找不到资源文件,最笨的方法---可以写绝对路径D:\IdeaProjects\liujinhui\day04_jdbc_20201220\src\jdbc.properties
 31             //另外:获取src路径下的文件---ClassLoader  类加载器:可以 加载字节码文件进内存,同时可以获取src下的资源文件
 32             ClassLoader classLoader = JDBCUtils.class.getClassLoader();
 33             //传的是以src相对的文件路径
 34             //返回统一资源定位符,即文件的绝对路径
 35             URL res= classLoader.getResource("jdbc.properties");
 36             String path = res.getPath();
 37             System.out.println(path);
 38             prop.load(new FileReader(path));
 39             //3.获取数据,赋值
 40             url=prop.getProperty("url");
 41             user=prop.getProperty("user");
 42             password=prop.getProperty("password");
 43             driver=prop.getProperty("driver");
 44             //4.注册驱动
 45             Class.forName(driver);
 46         } catch (IOException e) {
 47             e.printStackTrace();
 48         } catch (ClassNotFoundException e) {
 49             e.printStackTrace();
 50         }
 51     }
 52     //Arrays等都是静态,方便类直接调用
 53     /**
 54      * 获取连接的工具方法
 55      * @return 连接对象
 56      */
 57     //String url,String root,String password有参数仍然很麻烦
 58     //通过私有变量、配置文件及静态代码块解决
 59     public static Connection getConnection() throws SQLException{
 60         return DriverManager.getConnection(url,user,password);
 61     }
 62     /**
 63      * 释放资源
 64      * @param stmt
 65      * @param conn
 66      */
 67     public static void close(Statement stmt,Connection conn){
 68         if (stmt!=null){
 69             try {
 70                 stmt.close();
 71                 //conn.close();多个语句要放到多个try..catch中
 72             } catch (SQLException e) {
 73                 e.printStackTrace();
 74             }
 75         }
 76         if (conn!=null){
 77             try {
 78                 conn.close();
 79             } catch (SQLException e) {
 80                 e.printStackTrace();
 81             }
 82         }
 83     }
 84     /**
 85      * 释放资源
 86      * @param rs
 87      * @param stmt
 88      * @param conn
 89      */
 90     public static void close(ResultSet rs, Statement stmt, Connection conn){
 91         if (stmt!=null){
 92             try {
 93                 stmt.close();
 94                 //conn.close();多个语句要放到多个try..catch中
 95             } catch (SQLException e) {
 96                 e.printStackTrace();
 97             }
 98         }
 99         if (conn!=null){
100             try {
101                 conn.close();
102             } catch (SQLException e) {
103                 e.printStackTrace();
104             }
105         }
106         if (rs!=null){
107             try {
108                 rs.close();
109             } catch (SQLException e) {
110                 e.printStackTrace();
111             }
112         }
113     }
114 }

测试

1     /**
2      * 登录方法
3      */
4     public boolean login(String username ,String password){
5         if (username==null||password==null){
6             return false;
7         }
8         Connection conn=null;
9         Statement stmt=null;
10         ResultSet rs=null;
11         try {
12             //连接数据库判断是否登录成功
13             //1.获取连接,更改数据库只需要修改配置文件,可扩展性强
14              conn = JDBCUtils.getConnection();
15             //2.定义 sql
16             String sql="select * from user where username='"+username+"' and password='"+password+"'";
17             //3.获取执行SQL的对象
18              stmt = conn.createStatement();
19             //4.执行查询
20              rs = stmt.executeQuery(sql);
21             //5.判断
22             /*if (rs.next()){
23                 return  true;
24             }else{
25                 return false;
26             }*/
27             //直接返回
28             return rs.next();
29         } catch (SQLException e) {
30             e.printStackTrace();
31         }finally {
32             JDBCUtils.close(rs,stmt,conn);
33         }
34         return false;
35     }
36 }

4、控制事务

  • 使用Connection对象(获取连接、事务管理)
  • 在执行sql之前开启事务
  • 在当所有sql执行完提交事务
  • 在 catch中回滚事务

package cn.itcast.jdbc;

import cn.itcast.utils.JDBCUtils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

/**
 * 事务操作
 */
public class JDBCDemo11 {

    public static void main(String[] args) {
        Connection conn=null;
        PreparedStatement pstmt1=null;
        PreparedStatement pstmt2=null;
        try {
            //1.获取连接
            conn = JDBCUtils.getConnection();
            //开启事务
            conn.setAutoCommit(false);
            //2,定义SQL
            //2.1 张三-500
            //String sql1="update account set balance=balance-500 where id=1";
            //2.2 李四+500
            //String sql2="update account set balance=balance+500 where id=2";
            //通用写法
            String sql1="update account set balance=balance- where id=";
            String sql2="update account set balance=balance+ where id=";
            //3.获取执行sql对象
            pstmt1 = conn.prepareStatement(sql1);
            pstmt2= conn.prepareStatement(sql2);
            //代码格式化快捷键
            //4.设置参数
            pstmt1.setDouble(1,500);
            pstmt1.setInt(2,1);
            pstmt2.setDouble(1,500);
            pstmt2.setInt(2,2);
            //5.执行SQL
            pstmt1.executeUpdate();
            //手动制造异常
            int i=3/0;
            pstmt2.executeUpdate();
            //提交事务
            conn.commit();
            //使用大异常
        } catch (Exception e) {
            try {

                //事务回滚,前提不为null
                if (conn!=null){
                    conn.rollback();
                }
            } catch (SQLException e1) {
                e1.printStackTrace();
            }
            e.printStackTrace();
        }finally {
            JDBCUtils.close(pstmt1,conn);
            JDBCUtils.close(pstmt2,null);
        }
    }
}

六、JDBC连接池和JDBCTemplate

1、数据库连接池

  • 概念:容器存放数据库连接对象
  • 实现:DataSource的接口(基本实现、连接池实现、分布式事务实现)
    • C3P0连接池
    • Druid连接池(阿里巴巴提供)
  • 方法:
    • 获取连接:Connection getConnection()
    • 释放连接:Connection.close()--连接池则归还连接

2、C3P0连接池

  • 方式:硬编码/配置文件--src/c3p0.properties 或src/ c3p0-config.xml(推荐)
  • 使用:
    • DataSource ds = new ComboPooledDataSource();--构造传连接池名
    • ds.getConnection();
    • 可以配置多个连接池default-config和named-config name="otherc3p0"
c3p0-config  
named-config name="otherc3p0" 
    !--  连接参数 --
    property name="driverClass"com.mysql.jdbc.Driver/property
    property name="jdbcUrl"jdbc:mysql://localhost:3306/day25/property
    property name="user"root/property
    property name="password"root/property
    !-- 连接池参数 --
    property name="initialPoolSize"5/property
    property name="maxPoolSize"8/property
    property name="checkoutTimeout"1000/property
  /named-config
/c3p0-config

3、Druid连接池

  • 导入jar包,定义配置文件druid.properties
  • 加载配置文件,通过工厂类DruidDataSourceFactory获取连接池createDataSource(Properties)
/**
 * Druid演示
 */
public class DruidDemo {
    public static void main(String[] args) throws Exception {
        //1.导入jar包
        //2.定义配置文件
        //3.加载配置文件
        Properties pro=new Properties();
        InputStream is = DruidDemo.class.getClassLoader().getResourceAsStream("druid.properties");
        pro.load(is);
        //4.获取连接池对象
        DataSource ds = DruidDataSourceFactory.createDataSource(pro);
        //5.获取连接
        Connection conn=ds.getConnection();
        System.out.println(conn);
    }
}
  • 定义工具类,将加载配置文件放至工厂类,提供静态方法,直接由类名调用
    • 获取连接池DataSource
    • 获取连接
    • 释放资源
package cn.itcast.datasource.utils;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
/**
 * Druid连接池的工具类
 */
public class JDBCUtils {
    //1.定义一个成员变量 DataSource
    private static DataSource ds;
    static{

        try {
            //1.加载配置文件
            Properties pro=new Properties();
            pro.load(JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties"));
            //2.获取DataSource
            ds = DruidDataSourceFactory.createDataSource(pro);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * 获取连接
     */
    public static Connection getConnection() throws SQLException {
        return ds.getConnection();
    }
    /**
     * 释放资源
     */
    public static void close(Statement stmt,Connection conn){
        /*if (stmt!=null){
            try {
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (conn!=null){
            try {
                conn.close();//归还连接
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }*/
        //简化书写
        close(null,stmt,conn);
    }

    //方法重载
    public static void close(ResultSet rs,Statement stmt, Connection conn){
        if (rs!=null){
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (stmt!=null){
            try {
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (conn!=null){
            try {
                conn.close();//归还连接
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
    /**
     * 获取连接池方法
     */
    public static DataSource getDataSource(){
        return ds;
    }
}

使用连接池测试

package cn.itcast.datasource.druid;
import cn.itcast.datasource.utils.JDBCUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

/**
 * 使用新的工具类
 */
public class DruidDemo2 {
    public static void main(String[] args) {
        /**
         * 完成添加的操作,给account表添加一条记录
         */
        Connection conn=null;
        PreparedStatement pstmt=null;
        try {
            //1.获取连接
            conn = JDBCUtils.getConnection();
            //2.定义sql
            String sql="insert into account values(null,,)";
            //3.获取pstmt对象
            pstmt = conn.prepareStatement(sql);
            //4.给赋值
            pstmt.setString(1,"王五");
            pstmt.setDouble(2,3000);
            int count = pstmt.executeUpdate();
            System.out.println(count);
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            //6.释放资源
            JDBCUtils.close(pstmt,conn);
        }
    }
}

4、JDBCTemplate

  • 创建对象:JDBCTemplate template =new JDBCTemplate(ds)
  • 调用方法完成CRUD操作:
    • update()---DML语句实现CUD
    • queryForMap()--DQL实现R,将结果封装为map集合({列名:值})
    • queryForList()--DQL实现R,将将map结果封装为list结果集(map的集合)
    • query(new BeanPropertyRowMapper类型(类型.class))--将结果集封装为JavaBean对象
    • queryForObject()--对象查询,将结果集封装为对象,一般用于聚合函数
 /**
     * 查询所有id为1的记录,将其封装为map集合
     */
    @Test
    public void test4(){
        String sql="select * from emp where id=";
        MapString, Object map = template.queryForMap(sql, 1001);
        System.out.println(map);
        //{id=1001, ename=孙悟空, job_id=4, mgr=1004, joindate=2000-12-17, salary=10000.00, bonus=null, dept_id=20}
    }
    /**
     * 如果有多条记录
     * 注意:此方法queryForMap结果集长度只能为1
     */
    @Test
    public void test5(){
        String sql="select * from emp where id=  or id= ";
        MapString, Object map = template.queryForMap(sql, 1001,1002);
        System.out.println(map);
        //{id=1001, ename=孙悟空, job_id=4, mgr=1004, joindate=2000-12-17, salary=10000.00, bonus=null, dept_id=20}
    }
    /**
     * 查询所有记录,将其封装为list集合
     */
    @Test
    public void test6(){
        String sql="select * from emp";
        ListMapString, Object list = template.queryForList(sql);
        for (MapString, Object stringObjectMap : list) {
            System.out.println(stringObjectMap);
        }
    }
    /**
     * 查询所有记录,将其封装为 Emp对象的list集合
     */
    @Test
    public void test7(){
        String sql="select * from emp";
        ListEmp list = template.query(sql, new RowMapperEmp() {
            @Nullable
            @Override
            public Emp mapRow(ResultSet rs, int i) throws SQLException {
                Emp emp=new Emp();
                int id = rs.getInt("id");
                String ename = rs.getString("ename");
                int job_id = rs.getInt("job_id");
                int mgr = rs.getInt("mgr");
                Date joindate = rs.getDate("joindate");
                double salary = rs.getDouble("salary");
                double bonus = rs.getDouble("bonus");
                int dept_id = rs.getInt("dept_id");
                emp.setId(id);
                emp.setEname(ename);
                emp.setJob_id(job_id);
                emp.setMgr(mgr);
                emp.setJoindate(joindate);
                emp.setSalary(salary);
                emp.setBonus(bonus);
                emp.setDept_id(dept_id);
                return emp;
            }
        });
        for (Emp emp : list) {
            System.out.println(emp);
        }
    }
    /**
     * 查询所有记录,将其封装为 Emp对象的list集合
     * template已经提供了实现类
     */
    @Test
    public void test8(){
        String sql="select * from emp";
        ListEmp list = template.query(sql,new BeanPropertyRowMapperEmp(Emp.class));
        //提示空值不能转换为double,则需要修改javabean为引用数据类型
        for (Emp emp : list) {
            System.out.println(emp);
        }
    }
    /**
     * 查询总的记录数(count')
     */@Test
    public void test9(){
        String sql="select count(id) from emp";
        Long total = template.queryForObject(sql, Long.class);//用于执行聚合函数
        System.out.println(total);
    }
}

七、HTML

1、概述

2、标签 介绍

八、HTMLCSS

1、表单

2、CSS

九、JavaScript基础

1、简介

2、语法

3、对象

十、JavaScript高级

1、入门

2、BOM

3、DOM

4、事件※

十一、BootStrap

1、概念

2、响应式布局

3、案例介绍

十二、XML

1、概念

2、约束

3、解析

4、Jsoup

十三、TomcatServlet基础

1、Web回顾

2、Web服务器软件

3、Servlet入门

十四、Servlet高级HTTPRequest

1、Servlet介绍

2、HTTP

3、Request

4、基于BeanUtils的用户登录案例

十五、Response

1、Http响应消息

2、Response

3、ServletContext

十六、CookieSession

1、会话技术介绍

2、Cookie

3、Session

4、JSP

5、案例:验证码判断

十七、ELJSTL

1、JSP指令、注释、内置对象

2、MVC开发模式

3、EL表达式

4、JSTL表达式

5、三层架构

6、案例:用户信息列表展示

十八、综合练习

1、界面设计

2、登录功能

3、添加功能

4、删除功能

5、修改功能

6、删除选中

7、分页查询

8、复杂条件查询

十九、FilterListener

1、Filter过滤器

2、案例:登录验证

3、案例:敏感词汇

4、Listener监听器

二十、JQuery基础

1、 概念

2、选择器

3、DOM操作

4、案例:隔行变色、表情选择

二十一、JQuery高级

1、动画

2、遍历

3、事件绑定

4、案例:广告的定时显示与隐藏

二十二、AjaxJson

1、Ajax

2、JSON

3、案例:检验用户名是否存在

二十三、Redis

1、介绍

2、命令操作

3、Redis持久化

4、Jedis操作

5、案例:下拉列表缓存加载省份信息

二十四、Maven基础

1、介绍

2、具体使用

3、Maven详细介绍

4、Idea使用Maven

5、基于Maven的Servlet实例

二十五、Web项目旅游网1

1、项目介绍

2、前台表单校验

3、后台功能:数据库查询、邮件激活

4、登录实现

二十六、Web项目旅游网2

1、BaseServlet抽取

2、分类数据展示

3、旅游线路分页展示

二十七、Web项目旅游网3

1、旅游线路名称查询

2、旅游线路详情展示

二十八、Web项目旅游网4

1、旅游线路收藏

2、收藏次数的动态展示

3、补充

二十九、Linux

1、概述

2、安装

3、常用命令

4、其他功能

三十、LinuxNginx

1、安装软件

2、常用软件的安装

3、Nginx

4、Nginx静态网站部署

5、反向代理与负载均衡