Week07手写笔记

本周内容

1.数据库的约束
定义:约束用户在操作数据表的一种"行为"
1.1 默认约束default
当前操作表的时候,如果某个字段没有插入值的时候,默认约束可以起作用
指定字段 default 默认值;---给指定字段一个默认值
删除默认约束---modify
2.2 非空约束not null
指定字段 not null;---给指定字段不能为空
删除非空约束---modify
3.3 唯一约束unique
unique:约束字段值不能重复
指定字段 uniquel;---给指定字段不能重复
删除唯一约束:alter table 表名 drop index 唯一约束所在的字段名称;
添加唯一约束:modify;
4.4 主键约束primary key(非空且唯一)
特点:一般主键作用在一张表的非业务字段(id),--非空且唯一,一般和自增长约束一起使用
指定字段 primary key;
添加主键约束:modify
删除主键约束:alter table 表名 drop primary key;---只删除主键约束,非空约束并没有删除
5.5 自增长约束auto_increment
一般和主键约束一起使用,作用在非业务字段(id)
字段名称 primary key auto_increment;
添加自增长约束:modify
删除自增长约束:modify
先删除主键约束,再删除自增长约束
select last_insert_id;查询到最后一次自增长主键的id值;
6.6 外键约束(表和表之间的关系)foreign key
CONSTRAINT  -- 声明  
	dept_employee_fk  -- 后面跟外键名称 (命名规范:主表名_从表名_fk)
	FOREIGN KEY (dept_id) -- 外键作用的从表字段名称;格式--
	REFERENCES  -- -- 关联
	dept(id)  -- 主表的主键id

删除外键约束:alter table 表名 drop foreign key 外键名称;
添加外键:alter table 表名 add constraint 外键名称 foreign key(从表字段名称) references 主表(字段名称)
6.7 级联操作–cascade
级联操作是外键约束的基础之后后面加如这两个约束
级联修改:on updata cascade;
级联删除:on delete cascade;
2.数据库的备份和还原
2.1 图形界面化的方式–SQLyog
SQLYog图形界面化工具
备份:选中库---->右键---->backup/export----> 以sql转存文件导出到指定的目录中---->选中structure and data--->选择指定的路径
还原:将原来的库删除,然后在创建新的库--->右键--->import--->Execute Sql Script(执行sql脚本)--->找到sql脚本路径--->将sql脚本中的存储的表数据和结构全部执行!
2.2 命令行的方式
 备份:使用dos控制台的方式
管理员身份运行dos控制台,不需要登录mysql
	mysqldump -uroot -p密码 库名 > 路径\xxx.sql	
还原:命令的方式还原
mysql -uroot -p -->回车输入密码--->dos控制台登录mysql-->source 路径\xxx.sql
3.表和表的关系
4. 数据库的三大范式(重点)–数据库的基本标准
设计关系数据库时,遵从不同的规范要求,设计出合理的关系型数据库,这些不同的规范要求被称为不同的范式,各种范式呈递次规范,越高的范式数据库冗余越小,关系数据库有六种范式:第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、巴斯-科德范式(BCNF)、第四范式(4NF)和第五范式(5NF,又称完美范式)。
第一范式(1NF):数据库表的每一列都是不可分割的原子项,即实体中的某个属性有多个值时,必须拆分为不同的属性。每列不能再拆分
第二范式(2NF):在1NF的基础上,非主键的列(字段)完全依赖于主键列(字段),不产生局部依赖;
	特点:1)一张表只描述一件事情;
		2)表中的每一列都依赖于主键;
第三范式(3NF):在2NF基础上,非主键列不能产生传递依赖于主键列;
5. 多表查询
操作步骤:1)查询哪些表
2)查询表中的哪些字段
3)表和表之间的关系:连接条件
5.1 内连接查询–隐式和显示内连接
隐式内连接:使用where条件
select 字段列表 from 表名1,表名2 where 表名1.某个字段=表名2.某个字段;
	SELECT 
  * 
FROM
  emp e,
  dept d 
WHERE e.`dept_id` = d.`id` ;
显示内连接:关键字 select 字段列表 from 表名1 inner join 表名2 on 表名1.某个字段 = 表名2.某个字段;(inner可以省略不写)
	SELECT 
  e.*,
  d.`NAME` '部门名称' 
FROM
  emp e 
  INNER JOIN dept d 
    ON e.`dept_id` = d.`id` ;
实际开发中,多去使用where语句
5.2 外连接查询–左外和右外连接
左外连接查询:select 字段列表 from 左表 left outer join 右表 on 连接条件;--将左表的信息全部查询出来以及交集部分的数据
右外连接查询 和左外相反:将右表的数据全部查询出来以及交集部分的数据  -->rigth (outer可以省略不写) join
SELECT  * FROM emp e 
  RIGHT JOIN dept d 
    ON e.`dept_id` = d.`id` ;
5.3 子查询—select嵌套
1)利用聚合函数以及比较运算符
		select 嵌套
2)利用in集合语句 in(值1,值2,值3)
	字段名称 in(值1,值2,值3)
3)将某个查询语句的结果--多行多列--看做"虚表"和当前其他表进行关联查询
	--将第一查询的结果表起一个别名,作为虚表
6.数据库的事物
在实际开发中,每一个业务操作(看成一个整体)可能同时操作多个表或者多个sql语句,要么同时执行成功要么同时执行失败!
6.1 传统事物的特点:ACID(必须记住)
1)A(原子性):针对当前某个事物,执行多个sql的时候,要么同时成功,要么同时失败
2)C(一致性):事物操作的前后,总量保持一致的
3)I(隔离性):事物和事物(业务和业务)之间是独立的,不能相互影响
4)D(持久性):如果开启了事物,并且提交事物,对数据的修改它是持续的,即使关机,数据依然存在!
6.2 事物的隔离级别
1)read uncommitted:读未提交(安全行低,效率最高),严重会导致"脏读",一个事物读到另一个没有提交的事物!
2)read committed:读已提交(安全性高于前者),有效防止脏读,但是出现新的问题-->不可重复读的问题;
3)repeatable read:可重复的默认隔离级别,有效防止脏读,不可重复的问题;
4)serializable:串行话:级别最高,效率低;有效防止脏读,不可重复的问题,幻读的问题;
5.5版本,SELECT @@tx_transaction;查看隔离级别
set global transaction isolation level 隔离级别名称---设置隔离级别;
6.3 在命令行操作事物
1)start transaction:开启事物
2)执行sql语句:updata/delete/insert...
3)commit:提交事物
4)rollback:回滚事物-->回到最初始的状态
7.什么是JDBC?repet
JDBC((java database connectivity)java操作数据库的一种连接器
7.1 jdbc的本质
就是java连接特定的数据库,本质是实现了sun公司提供的接口的实现类(数据库厂商提供的)
7.2 jdbc原生的7大操作步骤
1.加载驱动--导入数据库的驱动包
2.注册驱动
3.获取数据库的连接对象				
4.准备静态sql语句
5.通过连接对象获取执行对象
6.通过执行对象执行静态sql语句并返回结果
7.释放资源
public class JDBCdemo {
    public static void main(String[] args) throws Exception{
        //1)加载驱动,导包
        //2)注册驱动
        Class.forName("com.mysql.jdbc.Driver");//驱动类的全限定名称
        //3)获取数据库的连接对象
        /*sun公司提供类:驱动管理类DriverManager  用于管理一组JDBC驱动程序的基本服务。
        *静态功能:public static Connection getConnection(
        * String url, 统一资源定位符
        * String user, 数据库的用户 root
        * String password) 数据库的密码
        * throws SQLException 获取数据库的连接对象
        * url =jdbc:关系型数据库的类型://域名:端口号/库名"
        * mysql-server:安装mysql版本8.0后面库名要带上 一堆参数  字符集是utf8,是否进行数据库验证(false),以及服务器时区还有是否公开访问
        *mysql-server:安装mysql8.0以下的版本,5.0以上的版本  :库名的后面通常情况下可以不带参数 (备注5.7的版本最起码带上?characterEncoding=utf8)
        * */
        String url = "jdbc:mysql://localhost:3306/myee_2113";
        String user = "root";
        String password = "root";
        Connection connection = DriverManager.getConnection(url,user,password);
        //4)准备静态sql语句
        String sql = "insert into amount values (3,'王五',1500,2000)";
        //5)通过数据库的连接对象获取执行对象
        //java.sql.Connection--->Statement createStatement() throws SQLException
        Statement stmt = connection.createStatement();
        //6)执行sql语句并返回结果
        //Statement:通用的方法:
        // int executeUpdate(String sql)throws SQLException :
        // 执行DML语句 inseret into/update/delete,DDL (创建表/修改表...);
        //ResultSet executeQuery(String sql)throws SQLException 执行DML语句,查询
        int count = stmt.executeUpdate(sql);
        System.out.println("本次操作影响了"+count+"行");
        //7)释放资源
        stmt.close();
        connection.close();
    }
}
	
7.3 优化–自定义一个工具类:JDBCUtils
作用:为了简写7大步骤的书写格式,将加载驱动,获取数据的连接对象,以及释放资源都封装到静态成员方法中
import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
public class JDBCUtil {
    //静态代码块随类的加载二加载
    private static String url = null;
    private static String user = null;
    private static String password = null;
    private static String driverClass = null;
   // ResultSet rs = null;

    static {
        try {
            Properties popo = new Properties();
            InputStream inputStream = JDBCUtil.class.getClassLoader().
                    getResourceAsStream("jdbc.properties");
            popo.load(inputStream);
            //通过键获取值
            driverClass = popo.getProperty("driverClass");
            url = popo.getProperty("url");
            user = popo.getProperty("user");
            password = popo.getProperty("password");
            //注册驱动
            Class.forName(driverClass);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //静态功能的方法来获取数据库的连接对象
    public static Connection getconnection() {
        Connection connection = null;
        try {
            connection = DriverManager.getConnection(url, user, password);
            return connection;
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }
    public static void close(Statement stmt,Connection connection,ResultSet rs){
        if(stmt!=null){
            try {
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(connection!=null){
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(rs!=null){
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }

        }
    }

    public static void main(String[] args) {
        Connection connection = JDBCUtil.getconnection();
        System.out.println(connection);
    }
}
7.4 使用JDBC方式如何操作DQL语句(数据库查询语句)
 ResultSet executeQuery(String sql) throws SQLException; 执行查询语句(select)
 boolean next()  throws SQLException将光标从当前位置移动到下一行
 	public class JDBC_Demo2 {
    public static void main(String[] args) {
        Statement stmt =null;
        ResultSet rs =null;
        Connection connection =null;
        try {
            connection = JDBCUtil.getconnection();
            String sql = "select * from student1;";
            stmt = connection.createStatement();
            rs =stmt.executeQuery(sql);
            while(rs.next()){
                int id = rs.getInt(1);
                String name = rs.getString("name");
                int age = rs.getInt(3);
                System.out.println(id+"\t"+name+"\t"+age);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally{
            JDBCUtil.close(stmt,connection,rs);
        }
    }
}

7.5 JDBC操作数据库,使用PreparedStatement的预编译操作步骤
定义:表示预编译的SQL语句的对象
操作:在通过连接对象获取预编译对象的时候,同时将参数化的SQL语句发送到数据库并且保存到编译对象中
参数化Sql的写法:1)insert into (字段名称)  values (?..?):----?是占位符号
2)PreparedStatement给占位符号赋值,通过void setXXX(占位符号,XXX是实际参数)
	public class PreparedStatementDemo {
    public static void main(String[] args) {
        //获取数据库的连接对象
        Connection connection = JDBCUtil.getconnection();
        //准备预编译的sql语句,values后为占位符
        String sql = "insert into user values (?,?,?)";
        try {
            //获取预编译执行对象
            PreparedStatement stmt = connection.prepareStatement(sql);
            //给sql语句进行赋值
            stmt.setInt(1,1);
            stmt.setString(2,"liu");
            stmt.setString(3,"liubaoshou");
            //执行语句
            int i = stmt.executeUpdate();
            System.out.println("影响了:"+i+"行");
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}
7.5.1面试题: 数据库的操作的执行对象PreparedStatement和Statement具体区别–>通过"sql注入弊端"区分
1)能有效防止sql注入
2)比statement对象执行效率高
sql语句:String sql = "select * from  user where username = '"+user+"' and password = '"+psw+"';"
当输入用户名和密码时,密码输入格式为  a' or '1=1',那么修改了原来的sql语句,则会重现sql注入现象,无论正确还是错误,都会全部查询;
通过preparedStatement防止sql注入:select * from user where username = ? and password = ?;
具体区别:
Statement对象:1)执行的静态sql语句,存在一种硬编码行为,sql语句会有字符串拼接行为-->就可能出现"sql注入",不安全!
2)执行sql效率比较与prepareStatement低
PreparedStatement:
1)执行的参数化的sql语句,不存在字符串拼接行为,有效防止"sql注入'现象;
2)通过预编译对象给占位符号"?"赋值,赋值多次,执行sql效率高;
8 JDBC数据库管理"事物"
connection管理事物;
 1)void setAutoCommit(boolean autoCommit) throws SQLException---参数true:表示自动提交模式,false,禁用自动提交,手动提交
2)void rollback() throws SQLException:事务回滚,撤销之前的所有操作,回滚到操作之前的状态
3)void commit() throws SQLException使上次提交/回滚之后所做的所有更改都将永久性 (提交事务
public class Shiwu {
    public static void main(String[] args) {
        Connection connection = JDBCUtil.getconnection();
        PreparedStatement stmt = null ;
        PreparedStatement stmt2 = null ;
        String sql1 = "update amount set balance = balance - 500 where id = ?";
        String sql2 = "update amount set balance = balance + 500 where id = ?";
        try {
            stmt = connection.prepareStatement(sql1);
            stmt2 = connection.prepareStatement(sql2);
            //连接对象控制事物,禁止自动提交,转为手动提交,true为自动提交,false是手动提交
            connection.setAutoCommit(false);
            stmt.setInt(1,1);
            stmt2.setInt(1,2);
            int i = stmt.executeUpdate();
            //int num = 10/0;
            int j = stmt2.executeUpdate();
            System.out.println(i+"----"+j);
            connection.commit();//提交事物,将所有操作都转为永久性
        } catch (SQLException e) {
            try {
                connection.rollback();//当发生错误是,回滚所有操作
            } catch (SQLException ex) {
                ex.printStackTrace();
            }
        }finally {
            JDBCUtil.close(connection,stmt);
        }
    }
}
9.数据库的连接池
数据库连接池的目的:创建一些固定的可重用的连接对象,当使用完连接对象之后不会将对象真正释放,而是归还到连接池中,等待下一次继续去利用!
c3p0;---两种使用方式
	方式(1):src下面提供配置文件,名称必须是c3po-config.xml
	方式(2):src下面提供c3p0.properties
dbcp:功能非常强大--->是阿里提供的开源,不仅仅是作为"连接池",而且提供SQL Parser
(推荐使用)druid(德鲁伊)--功能非常强大--->是阿里提供的开源,不仅仅是作为"连接池",而且提供SQL Parser
数据库连接池的操作步骤:
1)导入druid-1.1.10.jar包 /junit的jar包以及依赖包/mysql驱动包
2)准备好的德鲁伊的配置文件

9.1 数据库连接池的操作步骤
数据库连接池的操作步骤:
1)导入druid-1.1.10.jar包 /junit的jar包以及依赖包/mysql驱动包
2)准备好的德鲁伊的配置文件jdbc.properties/druid.properties;名称需要查看jar包的datasource中的名称
3)创建配置文件对象,获取配置文件的资源输入流
4)将资源输入流内容保存到属性列表集合中
5)获取数据源的方法,通过中间关系"druitdatafactory工厂类",连接数据库
4)获取连接对象
<druid.properties?
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/myee_2113
username=root
password=root

	public class DruidDemo {
    public static void main(String[] args) throws Exception {
        //1)创建配置文件的对象
        Properties popo = new Properties();
        //2)获取资源文件的资源输入流
        InputStream inputStream = DruidDemo.
                class.getClassLoader().getResourceAsStream("Druid.properties");
        //3)将资源输入流保存到属性列表集合中
        popo.load(inputStream);
        //4)public static DataSource createDataSource(Properties properties)
        //通过中间介质工厂类连接数据库连接池
        DataSource dataSource = DruidDataSourceFactory.createDataSource(popo);
        //5)获取连接对象
        Connection connection = dataSource.getConnection();
        //输出数据库连接对象
        System.out.println(connection);//com.mysql.jdbc.JDBC4Connection@759ebb3d
    }
}

10.模拟真实场景–JDBCUtil优化
import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;

public class JDBCUtil {
    private static DataSource ds = null ;
    private static ThreadLocal<Connection> t1 = new ThreadLocal<>();
    private  static Connection conn;
    private  static ResultSet rs;
    //静态代码块读取配置文件并获取数据源对象
    static {
        Properties prop = new Properties();
        InputStream inputStream = JDBCUtil.class.getClassLoader().
                getResourceAsStream("Druid.properties");
        try {
            prop.load(inputStream);
            ds = DruidDataSourceFactory.createDataSource(prop);//获取数据源对象
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //获取连接对象
    public static Connection getConnection () {
        try {
            Connection conn = t1.get();//从线程中获取对象
            if (conn == null) {
                conn = ds.getConnection();//从数据源对象中获取对象
                t1.set(conn);//绑定到线程中
            }
            return conn;
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }
    public static DataSource getDataSource(){
        return ds;
    }
    //释放对象,针对查询DQL
    public static void close(ResultSet rs,PreparedStatement 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 {
                //将连接对象从线程中解绑出来
                t1.remove() ;
                conn.close(); //归还连接池中
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
    //释放资源---针对添加,删除,修改
    public static void close(PreparedStatement stmt,Connection conn){

        //调用上面close
        close(null,stmt,conn);
    }
    //加入JDBC管理事物,开启事务并将连接对象释放调用(解绑)
    public static void setAotoClose(){
        //获取连接对象
        Connection connection = getConnection();
        try {
            connection.setAutoCommit(false);//禁用自动提交,切换手动提交
            //解绑
            t1.remove() ;
            connection.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    //加入事物回滚并将连接对象释放回归
    public static void rollbackAndClose(){
        Connection connection = getConnection();
        try {
            connection.rollback();
            t1.remove();
            connection.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    //事物提交并且连接对象释放回归
    public static void commitAndClose(){
        Connection connection = getConnection();
        try {
            connection.commit();
            t1.remove();
            connection.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    //main测试
    public static void main(String[] args) {
        DataSource dataSource = getDataSource();
        System.out.println(dataSource);
        Connection connection = getConnection();
        System.out.println(connection);
    }
}
11.Apache机构提供的工具(对jdbc封装)–>comments-dbutils.jar
Common-dbtuls就是针对原生jdbc的操作进行简易封装
1)导入jar包 commons-dbutils-1.7.jar
2)操作数据库 ---> 创建QueryRunner对象
        执行对象:QueryRunner
        创建QueryRunner对象
        public QueryRunner()  :手动提交模式
        创建QueryRunner对象
         public QueryRunner(DataSource ds) :参数为数据源   自动提交模式(推荐)
3) 准备的sql ,参数化的sql语句
4)QueryRunner对象执行的sql语句
     4.1)针对添加,删除,修改的sql语句通用的方式
            public int update(String sql, Object... params),返回值是int类型
            参数1:参数化的sql语句
            参数2:给"占位符?" 赋值实际参数
     4.2)针对查询的sql语句
        通用的查询方法
            public <T> T query(String sql, ResultSetHandler<T> rsh, Object... params)
           参数1:查询的sql语句  举例:select * from 表名 where id = ? ;
           参数2:接口
                 ResultSetHandler :针对查询的结果集的数据表的处理
                        子实现类
                         BeanListHandler<T> :将查询的每一条记录封装到T中,然后结果多条记录
                         封装到一个List<T> 集合中
                         BeanHandler<T> :将查询的某一条记录封装到T中,返回就是当前T
                         ScalarHandler<T>:查询单行单列数据封装到Object中
                                举例
                                        查询总记录数 select count(id) from 表名;
                                        Object obj = qr.query(sql, new ScalarHandler<>());
                         ...
           参数3:带条件的实际参数


针对增删改的语句update:
 	 public void addStudent(Student s) {
        QueryRunner qr = new QueryRunner(JDBCUtil2.getDataSource());
        String sql = "insert into student2 values (?,?,?,?,?)";
        try {
            int x = qr.update(sql, s.getId(), s.getName(),
                    s.getAge(), s.getGender(), s.getAddress());
            System.out.println("影响了:"+x+"行");
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
针对查询的语句,并且返回的是一个集合;
  public List<Student> findAllStudent(Student s) throws SQLException {
        QueryRunner qr1 = new QueryRunner(JDBCUtil2.getDataSource());
        String sql1 = "select * from student2";
        List<Student> list = qr1.query(sql1, new BeanListHandler<Student>(Student.class));
        return list;
    }
针对查询的语句,并且返回的是一个单独的事物,单条查询
  public Student findOneStudent(int id) throws SQLException {
        QueryRunner qr2 = new QueryRunner(JDBCUtil2.getDataSource());
        String sql2 = "select * from student2 where id = ?";
        Student s2 = qr2.query(sql2, new BeanHandler<Student>(Student.class), id);
        return s2;
    }
   查询的是一个单行单列的数据(有多少列,多少行),返回的是一个单独的object类,需要转换成int类型,输出
    public int countEmpl(String file) throws SQLException {
        QueryRunner qr = new QueryRunner(JDBCUtil2.getDataSource());
        String sql = "select count(?) from emp";
        Emploee obj = qr.query(sql, new ScalarHandler<Emploee>(), id);
        String s = String.valueOf(obj);
        int count = Integer.parseInt(s);
        return count;
    }
11.动态代理
代理设计模式属于"结构型设计模式"
代理设计模式:1)静态代理 2)动态代理
动态代理:1)jdk动态代理 2)cglib动态代理(第三方)
前提条件:必须存在一个接口,基于这个接口来完成加强代理的!
通过反射的方式直接产生代理实例对象
操作步骤:
1)创建代理类的对象
2)获取调用代理对象的处理程序对象,参数为代理类的实例
3)通过proxy的newproxyinstance来获取经过调用处理程序加强的代理类对象
4)调用方法

public class ProxyTest {
    public static void main(String[] args) {
        //1)创建代理类的实例对象
        UserDao ud = new UserDaoImpl();
        //2)获取调用实例对象的处理程序对象,参数为代理类的实例
        InvocationHandler handler = new MyInvocationHandler(ud);
        //3)java.lang.reflect.Proxy的静态功能:
        // public static Object newProxyInstance(   -->//返回值是代理类的对象(被处理程序对象加强了成员方法)
        // ClassLoader loader,   代理类的类加载器
        // Class<?>[] interfaces,代理类实现的接口列表
        //      public Class<?>[] getInterfaces():Class提供的方法,返回值是该类实现的类或者接口列表
        // InvocationHandler h):基于代理的处理程序
        UserDao udo = (UserDao)Proxy.newProxyInstance(ud.getClass().getClassLoader(), ud.getClass().
                getInterfaces(), handler);
        //因为返回值是代理类对象,代理类对象无法使用增强的功能,所以需要向下转型为接口对象,调用增强后的方法!
        udo.add();
        udo.delete();
        udo.select();
        udo.update();
    }
}
//实现调用处理程序接口的子实现类
public class MyInvocationHandler implements InvocationHandler {
    //声明代理对象,构造方法传参
    private Object target;
    public MyInvocationHandler(Object target){
        this.target = target;
    }
    /**
     * @param proxy 代理对象	//代理类对象
     * @param method 基于代理接口的方法的类对象  FileMethod:反射获取成员方法对象
     * @param args  基于代理接口的方法的实际参数数组
     * @return 产生的代理类对象
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("校验日志");
        method.invoke(target,args);
        System.out.println("产生日志文件");
        return target;
    }
}
真实接口和它的代理子实现类此处省略;
12.单元测试的步骤
 junit使用步骤
1)Java项目 导包 需要导入核心包:junit-4.13.jar以及它的依赖包hamcrest-core-1.3.jar,以后 "maven管理工具",只需要导入junit-4.13.jar,后面的依赖包自动导入
2)定义一个类:专门针对不同的功能进行测试的
3)在类中成员方法,单元测试的方法必须在成员方法上加入@Test, 这个方法没有任何参数,也不需要写返回值 都是void
 4) 使用 "断言",将预期的结果和最终结果进行对比,如果不一致,单元测试通过不了,如果一致,单元测试就是正常数据!使用"断言"Assert (junit提供的)的assertEquals(预期值,实际值) 
 在单元测试里面:
     @Test标记当前这个单元测试方法
     @Before 标记某个方法是在@Test标记的单元测试方法之前先执行
                举例:初始化的功能
     @After 标记某个方法是@Test标记的单元测试方法之后执行的
                    举例,释放相关的资源
public class Calculatortest {
    private Calculator cal;
    @Before
    public void inuit(){
        cal = new Calculator();
        System.out.println("在测试方法执行前先执行@Before");
    }
    @Test
    public void addtest(){
        int num = cal.add(3,4);
        Assert.assertEquals(7,num);
        System.out.println("测试成功");
    }
    @After
    public void shifang(){
        System.out.println("在测试方法执行后再执行@After");
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值