zoukankan      html  css  js  c++  java
  • Java 25-Java基础知识复习②

    1.Junit测试-单元测试

              测试分为黑盒测试和白盒测试,其中黑盒最为简单,不用管运行逻辑,只管input和output;白盒测试需要写一些代码,结合input和output查看运行效果。传统测试方法,多次调用容易混淆输出结果,单独新建

    1619165095(1)

    使用junit测试步骤:

    ①定义一个测试类(测试用例)

        建议:测试类名: 被测试的类名Test DemoTest

                  包名  : xxx.xxx.xx.test        cn.itcast.test

    ②定义测试方法:可以独立运行

          建议:方法名:test测试的方法名    testAdd();

                    返回值 :void

                    参数列表:空参  不调用 有参数没意思

                    注意: 方法上@Test

                    导入Jnuit依赖-导包

    ③判断结果:执行日志 绿色字体代表成功,红色字体代表出现bug

    ④ 特别说明-断言Assert.assert(期望值,实际值):

    某些时候,代码编写出错junit输出结果不是预期,那么如何有效核实,可以用断言来判断。Assert.assertEquals(3,result)

    image

    ⑤特别说明:@Before和@After -用于重复使用,例如啥资源申请或释放,其他代码会在此期间执行,那么久可以用这两个注解来先和后执行。

    image


    2.反射

            反射:俗称框架设计的灵魂,在未来框架中,进行开发可以简化代码。一句话:反射就是将类的各个组成部分封装为其他对象,这就是反射机制。参考下图理解:

    java代码在计算机中经历的三个阶段:

    首先我们在ide开发工具中,假设写某个person类,包含成员变量和构造方法,成员方法,通过javac编译 形成一个Person.class字节码文件,当然我们看不懂字节码文件,但其字节码Person.class文件主要包含三块内容:成员变量内容,构造方法内容,成员方法内容等等,也有类名称等信息。此时切记 类文件person.java和person.class都在电脑硬盘上存储着。此阶段是Source源代码阶段-并未进内存

    中间:有个东西:类加载器(对应着java中的对象ClassLoader)可以将源代码中的字节码.class文件加载进入内存中。那么此时产生一个问题,在内存中怎么描述这个字节码文件.class加载后情况:java中一切皆对象,这个把字节码文件经过类加载器classLoader加载进入内存后形成新的对象 叫 Class类对象(描述所有字节码文件进入内存后对象,共性抽取为将成员变量封装为Field数组对象装载所有成员变量 构造方法封装为Constructor数组对象装载 ,成员方法封装为method数组对象装载),最终我们根据class类对象的行为来创建new 对象

    最后 我们常见是用new对象 如 new Person(),进行使用,这个阶段称之为Runtime运行阶段。但其实这中间有个第二阶段就是讲字节码文件加载进入内存中,我们才能有这个对象。

    image

    2.1 反射的好处:

    1)可以在程序的运行过程中,操作这些对象。例如我们在idea 编写string str=“123”; 我们可以用str.很多方法出来,这里其实就是用到了反射:细想一下:idea时刻在运行,我们的str定义出来后,它string类的方法类加载器进入到class类对象的method方法中,同时把str加载进入内存,这样我们新建的对象也就可以直接使用了string其他方法了。

    2)可以解耦,提供程序的可扩展性。


    2.2. 反射的API操作

            我们前面讲了,从class类对象阶段到创建对象进入runtime运行时阶段,最为关键的是如何获取class类对象(因为我们要用成员变量操作对象 Field[],构造方法操作对象 Constructor[] 成员方法操作对象Method[] ,肯定是要先获取Class类对象)

    ******获取Class类对象的三种方法:分别对应java代码三种阶段

    第一种:java源代码阶段-Person.java编译为Person.class(仍然是源代码)

                Class.forName("全限定类名");将字节码.class文件加载进内存,返回class类对象。

    image

    第二种:Class类对象阶段,也就是已经加载进内存中,那么可以

                  类名.class:通过类名.class属性获取class类对象。

    第三种:运行期阶段,也就是已经产生new对象。

                 对象.getClass();getClass方法封装在object中,所有对象都可用

    image

    public class ReflectDemoOne {
        /**
         * 获取类的三种方式
         * 源代码阶段 Class.forName("全限定类名"),返回内存中的class类对象
         * class类对象阶段:类名.class属性即可,此时已经在内存中
         * 运行期阶段:对象.getClass();getClass()方法在object中
         */
        public static void main(String[] args) {
            try {
                //第一种方式:源代码阶段 class.forName
                Class<?> personClass = Class.forName("com.itheima.domain.Person");
                System.out.println(personClass);//class com.itheima.domain.Person
                //第二种方式:class类对象阶段 类名.class获取
                Class<Person> personClassTwo = Person.class;
                System.out.println(personClassTwo);//class com.itheima.domain.Person
                //第三种方式:对象.getClass()方法获取
                Class<? extends Person> personClassThree = new Person().getClass();
                System.out.println(personClassThree);//class com.itheima.domain.Person
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
    }

    结论:同一个字节码.class文件,在一次程序运行中,class类对象是唯一的。

    第一种全限定类名 因为传递的是字符串 多用于配置文件

    第二种多用于参数传递,如某个方法里面需要class.类对象。就类名.class即可

    第三种多用于对象的获取字节码的方式。

    2.3 class类对象的功能

    * 获取功能:

    (1)获取成员变量们

    * Field[] getFields() :获取所有public修饰的成员变量

    * Field getField(String name) 获取指定名称的 public修饰的成员变量

    * Field[] getDeclaredFields() 获取所有的成员变量,不考虑修饰符

    * Field getDeclaredField(String name) :获取指定名称的的成员变量,不考虑修饰符

    (2)获取构造方法们

    * Constructor<?>[] getConstructors()

    * Constructor<T> getConstructor(类<?>... parameterTypes)

    * Constructor<T> getDeclaredConstructor(类<?>... parameterTypes)

    * Constructor<?>[] getDeclaredConstructors()

    (3)获取成员方法们:

    * Method[] getMethods()

    * Method getMethod(String name, 类<?>... parameterTypes)

    * Method[] getDeclaredMethods()

    * Method getDeclaredMethod(String name, 类<?>... parameterTypes)

    (4)获取全类名

      * String getName()对象.getName()获取全限定类名。返回由类对象表示的实体(类、接口、数组类、原始类型或空白)的名称,作为string。

    * Field:成员变量对象 * 操作:

    (1). 设置值 * void set(Object obj, Object value) :将指定的参数上的此field对象表示的字段设置为指定的新值。

    (2) 获取值 * get(Object obj) :返回改所表示的字段的值field,指定对象上

    (3)忽略访问权限修饰符的安全检查  * setAccessible(true):暴力反射,设置暴力反射后,再给定值,获取值。

    image

        public static void main(String[] args) {
            //1.获取Person的class对象.用第二种方式获取,类名.class
            Class<Person> personClass = Person.class;
            try {
                //2.获取成员变量们
                Field field = personClass.getField("height");
                Person person = new Person();
    
    
                //set(对象)设置值
                field.set(person,123);
                //get(对象)获取值 ,person的height是public修饰,int类型,默认值为0
                Object value = field.get(person);
                System.out.println(field);//public int com.itheima.domain.Person.height
                System.out.println(value);//123
                System.out.println(person);//Person{name='null', age=0, height=123}
            }


    * Constructor:构造方法们

    最为主要的要注意获取构造方法时,需要给予指定的构造方法参数的类型,也就是class,例如int 是Intage


    (1) 创建对象:

               * T newInstance(Object... initargs) : 如果使用空参数构造方法创建对象,操作可以简化:Class对象的newInstance方法

        public static void main(String[] args) {
            //1.获取Person的class对象.用第二种方式获取,类名.class
            Class<Person> personClass = Person.class;
            //2.获取构造方法们
            try {
                Person person = personClass.getConstructor(String.class,Integer.class).newInstance("123", 123);
                System.out.println(person);

    如果是直接获取空参构造器创建对象,也可以直接用class类对象来newInstance。:object person =personclass.newInstance() 


    * Method:方法对象

    (1)执行方法: * Object invoke(Object obj, Object... args)

    (2)获取方法名称: * String getName:获取方法名


        public static void main(String[] args) {
            try {
                //1.获取Person的class对象.用第二种方式获取,类名.class
                Class<Person> personClass = Person.class;
                //2.获取无参成员方法
                Method eat = personClass.getMethod("eat");
                Person person=new Person();
                //3.方法对象执行方法 方法对象.invoke(类对象,参数列表)
                Object invoke = eat.invoke(person);
                System.out.println(invoke);
    
                //4 获取有参成员方法 class类对象.getMethod(方法名,参数类对象.class)
                Method getFood = personClass.getMethod("getFood", String.class);
                getFood.invoke(person,"小米粥");

    切记 getMethods方法获取的方法数组,会包含其父类的方法,本例子中person默认继承父类object,因此会有object方法在其中数组。

    image

    获取成员方法的方法名:

          遍历得到的方法数组的某一个值.getName()即可

    image

    案例:写一个假框架,在不改任何该类的代码情况下,帮我创建任意类的对象,并且执行任何方法

    思路:

    1.将需要创建的对象的全类名和需求执行的方法定义在配置文件中

    2.在程序中加载配置文件

    3.使用反射技术来加载类文件进内存

    4.创建对象

    5.执行方法

    public class ReflectDemoFour {
        public static void main(String[] args) {
    
            try {
                //1.创建对象,load配置文件,此前学过 properties对象,可以将properties类文件读取进内存,成为集合
                Properties properties = new Properties();
    
                //1.1. 获取字节码文件的类加载器,是这个类加载器将类ReflectDemoFour加载进内存的
                ClassLoader classLoader = ReflectDemoFour.class.getClassLoader();
                //1.2 classloader加载器有两个方法 getResource()直接返回资源路径 和getResourceAsStream(文件名)-返回文件路径的字节流
                URL resource = classLoader.getResource("pro.properties");
                System.out.println(resource);//file:/D:/Code/IDEA/eesy_spring/target/classes/pro.properties
                InputStream resourceAsStream = classLoader.getResourceAsStream("pro.properties");
                //1.3 properties对象的load方法,给予字节流或字符流,我们用上面class目录下的配置文件,也就是classloader加载器
                properties.load(resourceAsStream);//加配置文件进入内存
    
                //2 获取配置文件中定义的数据
                String className = properties.getProperty("className");//我们要加载类的文件名
                String methodName = properties.getProperty("methodName");//我们要加载类的方法
    
    
                //3.加载该类进内存,获取class类对象,有了类对象,就可以创建对象
                Class<?> aClass = Class.forName(className);
                //3.1 创建对象
                Object obj = aClass.newInstance();
                //3.2 获取方法对象,名字已经从配置文件中获取到
                Method method = aClass.getMethod(methodName);
    
                //4.执行方法
                method.invoke(obj);
            } catch (IOException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        }
    }

    如此 我们只要改配置文件 pro.properties文件里面的配置消息接口

    image




    3.注解
         * 概念:说明程序的。给计算机看的
         * 注释:用文字描述程序的。给程序员看的

        * 定义:注解(Annotation),也叫元数据。一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。
         * 概念描述:
             * JDK1.5之后的新特性
             * 说明程序的
             * 使用注解:@注解名称
            
        
    ****** * 功能作用分类:
             ①编写文档:通过代码里标识的注解生成文档【生成文档doc文档】

    image1619334943(1)
             ②代码分析:通过代码里标识的注解对代码进行分析【使用反射】
             ③编译检查:通过代码里标识的注解让编译器能够实现基本的编译检查【Override 检查是否是重写 】


    ******(1)JDK中预定义的一些注解
             * @Override    :检测被该注解标注的方法是否是继承自父类(接口)的
             * @Deprecated:该注解标注的内容,表示已过时

    image
             * @SuppressWarnings:压制警告
                 * 一般传递参数all  @SuppressWarnings("all"),也有在类上加这个注解的。

    image

    ******(2)自定义注解

    image
             * 格式:元注解+public @interface 注解名称
                 元注解
                 public @interface 注解名称{
                     属性列表;
                 }

            * 本质:注解本质上就是一个接口,该接口默认继承Annotation接口
                 * public interface MyAnno extends java.lang.annotation.Annotation {}

            * 属性:接口中的抽象方法,也就是自定义注解中可以定义的成员方法。
                 * 要求:
                     1. 属性的返回值有下列取值(不能是void,不能是某个类类型
                         * 基本数据类型   * String   * 枚举   * 注解    * 以上类型的数组

    image

                    2. 定义了属性,在使用时需要给属性赋值(其实就是给抽象方法赋值,因此我们把注解里面的抽象方法称之为属性,多个属性值,逗号隔开

    image1619336225(1)
    (1. 如果定义属性时,使用default关键字给属性默认初始化值,则使用注解时,可以不进行属性的赋值。

    image
    ( 2. 如果只有一个属性需要赋值,并且属性的名称是value,则value可以省略,直接定义值即可。

    image

    1619336423(1)

    枚举赋值image

    注解类型:image

    (3. 数组赋值时,值使用{}包裹。如果数组中只有一个值,则{}可以省略
            
    image
             * 元注解:用于描述注解的注解,还是注解(下面四个是常用的)

    image
                 * @Target:描述注解能够作用的位置
                     * ElementType取值: * TYPE:可以作用于类上;  * METHOD:可以作用于方法上;      * FIELD:可以作用于成员变量上,下为源码

    1619336841(1)1619336848(1)
    image

    * @Retention:描述注解被保留的阶段
                     * @Retention(RetentionPolicy.RUNTIME):当前被描述的注解,会保留到class字节码文件中,并被JVM读取到;SOURCE(源码阶段),我们一般是runtime选择。如果是class不会虚拟机读取到,如果是source是连字节码文件都不会存在了。

    imageimage
              * @Documented:描述注解是否被抽取到api文档中(有就显示注解,没有就不显示注解) javadoc输出文档
              * @Inherited:描述注解是否被子类自动继承

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface AnonotationTest {
        //抽象方法
        public abstract String name();
    }
    



    ******(3)在程序使用(解析)注解:获取注解中定义的属性值

    image
             1. 获取注解定义的位置的对象  (Class,Method,Field)
             2. 获取指定的注解
                 * getAnnotation(Class)
                 //其实就是在内存中生成了一个该注解接口的子类实现对象

                        public class ProImpl implements Pro{
                             public String className(){
                                 return "cn.itcast.annotation.Demo1";
                             }
                             public String methodName(){
                                 return "show";
                             }
                         }
             3. 调用注解中的抽象方法获取配置的属性值,下面就拿到值了

    image

    com.itheima.annotation.DemoOne
    show

    如果注解加载在方法上,方法也有getAnonotation获取注解属性

    image

    注解与反射两种不同形式的伪框架

    image

    ******案例-简单的测试注解框架

    public class TestCheck {
        public static void main(String[] args) throws IOException {
    
            //1.创建计算器对象
            Calculator calculator = new Calculator();
            //2.获取字节码文件对象
            Class<? extends Calculator> calculatorClass = calculator.getClass();
            //3.通过字节码文件对象,获取所有注解的方法
            Method[] methods = calculatorClass.getMethods();
            int number=0;//出现异常的次数
            BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("bug.txt"));
            //4.判断方法,是否有check注解,执行方法
            for (Method method : methods) {
                boolean annotationPresent = method.isAnnotationPresent(Check.class);
                if (annotationPresent==true){
                    try {
                        Object invoke = method.invoke(calculator);
                    } catch (Exception e) {
                        //记录文件信息
                        number++;
                        bufferedWriter.write("1: "+method.getName()+"方法出异常了");
                        bufferedWriter.newLine();
                        //类对象可以通过getName或者getSimpleName取得剪短类名
                        bufferedWriter.write("2: 异常的名称"+e.getCause().getClass().getSimpleName());
                        bufferedWriter.newLine();
                        bufferedWriter.write("3: 异常的原因"+e.getCause().getMessage());
                        bufferedWriter.newLine();
                        bufferedWriter.write("---------------");
                        bufferedWriter.newLine();
    
                    }
                }
            }
            bufferedWriter.write("总结;本次测试,一共出现"+number+"次异常");
            bufferedWriter.close();
        }
    
    
    }
    
    package com.itheima.annotation.demo;
    
    public class Calculator {
    
        @Check
        public void add(){
            System.out.println("1+1="+(1+1));
        }
    
        @Check
        public void sub(){
            System.out.println("1-1="+(1-1));
        }
    
        @Check
        public void mul(){
            System.out.println("1*0="+(1*0));
        }
    
        @Check
        public void div(){
            System.out.println("1/0="+(1/0));
        }
        public void show(){
            System.out.println("1+1="+(1+1));
        }
    }
    
    package com.itheima.annotation.demo;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Check {
    }
    


    4.mysql

    ************mysql目录结构-安装目录和数据目录

    安装目录下 bin data  include lib share等文件夹

    其中bin有很多exe命令文件,此前我们是将bin目录放在环境变量中,因此当我们cmd控制台交互时,其实就是运行mysql.exe文件命令、

    data是数据目录

    include是放置一些c语言的头目录

    lib是相当于运行时需要的各类支持包文件

    share放置一些mysql运行错误信息

    最为重要的ini文件:未来设置数据库可能要找到它  my.ini

    image

    数据目录:

    各个文件夹其实是一个数据库

    各个文件夹内.frm文件是表

    各个表其实是各种记录数据存储在里面

    1619344045(1)

    4.1. sql概念和基本语法

           sql全程 structured query language 结构化查询语言,定义了操作关系型数据库的语言规则。每一种数据库略微有差异。

    cmd中 登录sql  ->mysql -uroot  -proot

    通用语法:

    *1. sql是单行,每行以分号;结尾。建议空格提高可读性

    *2. cmd中:show databases; 查看mysql里有多少数据库

    *3. mysql中不区分大小写,建议关键字大写

    *4.  -- 单行注释内容  # 单行注释内容   /*多行注释内容*/


    SQL分类语句:CREATE 创建 RETRIEVE 查询 Upudate 修改 Delete删除

    DDL:数据库定义语言:create  drop  alter    建库建表建列

    DML:数据库操作语言:insert delete update 增删改

    DQL:数据库查询语言:select where等           查询

    DCL:数据库控制语言:grant revoke

    image

    ***show databases; 出现中其中performance_schema是性能方面,test为空的,我们一般就用mysql里面

    ***show create database mysql;  可以看见创建mysql默认字符集 utf-8

    (1)DDL:数据库定义语言-DDL创建

    ***create database db1;创建数据库db1;

    ***create database if not db1;如果不存在db1,则创建,不会报错

    ***create database db3 character set gbk ;创建db3,且字符集设为gbk

    create table 表名 (

        列名1 数据类型1,

       ......

       列名n  数据类型n


    ); 创建某个表,括号内给字段和字段类型

    sql数据类型:

    imageimage

    create table 表1 like 表2;复制一个表1,参考表2 ;

    -------------DDL修改

    alter database 数据库名称 character set 字符集;修改数据库字符集;

    alter table 表名 rename to 新表名;修改表名

    show create table 表名;查看表的字符集和字段

    alter table 表名 character set utf-8;修改表的字符集

    alter table 表名 add 列名 数据类型;添加表一列

    alter table 表名 change 列名1 列名2 列名2数据类型;修改表某一列名

    alter table 表名 modify 列名1 列名1数据类型;修改某一列数据类型

    alter table 表名 drop 列名;删除某一列;

    -------------DDL删除

    drop database db1;删除数据库名称;

    drop database if exists 数据库名称;若数据库存在,则删除;

    drop table 表名 ;

    drop table if exists 表名;删除某一表,若存在


    --------------DDL查询

    select database();查询当前正在使用的数据库;

    use db1;使用数据库db1;

    show tables;查询某个数据库下有多少个表

    desc 表名;查询表结构

    **********************DML 数据库操作语言 增删改表中数据

    ————————DML添加数据

    基本语法

    *insert into 表名(列名1,列名2,列名3) values(值1,值2,值3);

    列名和值一一对应

    如果表名后不定义列名,则默认给所有列添加值;

    除了数字类型,其他类型要用引号包裹着;日期也要横杠区分 引号包裹



    ————————DML删除表中的数据

    * delete from 表名 [ where 条件]

    例如 delete from stu where id=1;

    若不加where ,则删除所有数据;

    delete from 表名;删除表记录,一条一条删,效率低

    truncate table 表名:删除表,再创建一个一模一样的空表,效率比上面高


    ————————DML修改数据

    update 表名 set 列名1=值1,列名2=值2...... [ where 条件]

    update student set age=3 where id=3;当id=3,修改其年龄为3;

    update student set 列名X=值X;不加条件,则所有这个列都改为值X



    ********************DQL 查询语句

    **********基本查询  多字段查询-去重-计算列-判断null-起别名

    select * from  表名; 查询某表全部数据,*代表所有列的简化写法

    select  列名1,列名2 ,...列名n  from 表名; 查询某表的几列字段数据(未出现列名的则不会显示)

    select DISTINCT 列名 from 表名;查询某列,自动清除重复

    select DISTINCT 列名1 ,列名2 from 表名;查询某两列,自动清除两列一样的情况下才重复;


    select 列名1,列名2,列名3,列名2+列名3 from 表名:查询某表,并计算列名2和列名3之和显示出来。

    select 列名1,列名2,列名3,列名2+IFNULL(列名3 ,0)from 表名:查询某表,并计算列名2和列名3之和显示出来(若遇到null ,设为0,否则+null是null,不是我们想要的接口)。


    select 列名1,列名2,列名3,列名2+IFNULL(列名3 ,0) as 总分from 表名:查询某表,并计算列名2和列名3之和显示出来(若遇到null ,设为0,否则+null是null,不是我们想要的接口)。起别名用as  或者空格加中文也行

    image


    **********条件查询

    where 条件  其中条件涉及运算符如下:

    1619400277(1)

    1619400533(1)

    1619400550(1)

    -- 查询年龄大于20岁

    SELECT * FROM student WHERE age > 20;

    SELECT * FROM student WHERE age >= 20;


    -- 查询年龄等于20岁

    SELECT * FROM student WHERE age = 20;


    -- 查询年龄不等于20岁

    SELECT * FROM student WHERE age != 20; SELECT * FROM student WHERE age <> 20;


    -- 查询年龄大于等于20 小于等于30

    SELECT * FROM student WHERE age >= 20 && age <=30;

    SELECT * FROM student WHERE age >= 20 AND age <=30;

    SELECT * FROM student WHERE age BETWEEN 20 AND 30;


    -- 查询年龄22岁,18岁,25岁的信息 OR关键字  IN 关键字


    SELECT * FROM student WHERE age = 22 OR age = 18 OR age = 25

    SELECT * FROM student WHERE age IN (22,18,25);


    -- 查询英语成绩为null                   IS NULL 是NULL关键字

    SELECT * FROM student WHERE english = NULL; -- 不对的。null值不能使用 = (!=) 判断

    SELECT * FROM student WHERE english IS NULL;


    -- 查询英语成绩不为null             IS NOT NULL 不为NULL关键字

    SELECT * FROM student WHERE english IS NOT NULL;


    ***********模糊查询   like模糊查询 配合%和_两种占位符

    _下划线代表任意单个字符 %百分号代表任意个字符

    -- 查询姓马的有哪些? like         like 与%占位符的模糊查询

    SELECT * FROM student WHERE NAME LIKE '马%';


    -- 查询姓名第二个字是化的人     like 与%占位符的模糊查询

    SELECT * FROM student WHERE NAME LIKE "_化%";


    -- 查询姓名是3个字的人              like 与_下划线数量的模糊查询

    SELECT * FROM student WHERE NAME LIKE '___';


    -- 查询姓名中包含德的人            like 与%占位符的模糊查询

    SELECT * FROM student WHERE NAME LIKE '%德%';



    ************DQL排序查询  默认升序,不给排序方式就升序 ASC 

                                                     降序 DESC

    语法: order by 排序字句

               order by 排序字段1 排序方式1,排序字段2 排序方式2

    image

    多个字段排序,后面第二排序条件是前面第一排序字段是一样的时候才作用

    image

    ************DQL聚合查询  COUNT  MAX MIN SUM  AVG

    聚合意思是:将一列数据作为一个整体,进行纵向计算。

    select COUNT(列名) from student;计算某一列数量,结果是单行单列,切记是排除非空的数据

    image





    ************DQL分组查询 group by  having

    语法:分组查询中select后面只能是分组字段以及聚合函数,其他无意义。

    select ExpertSex AS 性别,count(*) as 总计 from expert_base_info GROUP BY ExpertSex;

    image

    select ExpertSex AS 性别,count(*) as 人数,SUM(ExpertSex) as 总计 from expert_base_info GROUP BY ExpertSex;

    image

    where条件筛选和分组查询结合使用。

    image

    复杂分组和分组后继续删选,人数大于2的才进行显示  having

    image

    where在分组钱进行限定,如果不满足条件,则不参与分组

    having在分组之后进行限定,如果不满足结果,则不会被查询出来

    where后不可跟聚合函数判断,而having可以进行聚合函数判断

    image

    ************DQL分页查询 limit 开始的索引,每页显示的条数。每个sql不一样。


    image


    *************约束-对表中的数据进行限定,保证数据正确性,有效性和完整性

    (非空约束)not null

              创建表时,设置非空image

             删除表设置的非空 image

              给老表添加非空image


    (唯一约束) unique 某一列值不能重复,需要唯一,唯一约束可有唯一null

             创建表时,设置唯一image

             删除表设置的唯一  alter table stu drop index phone_number;

              给老表添加唯一 alter table stu modify phone varchar(20) unique;

    (主键约束)primary key-非空且唯一 一张表只能有一个主键,唯一标识

             创建表时,设置主键 image

             删除表主键约束    alter table 表名 drop primary key;

             给老表添加主键 alter table 表名 modify 列名 数据类型 primary key;




    (主键自增长)某列是数值类型  auto_increment 自动增长

    insert into 表名 values(null,123)--自动增加给null即可,若给数字就下次在此数字上加一,它只以上一行记录为准加1

    image

    删除自增长 alter table 表名 modify 列名 列数据类型;

    添加老表自增长 alter table 表名 modify 列名 列数据类型 auto_increment;


    (外键约束)foreign key

    create table emp(
         id INT(20) PRIMARY KEY,
             NAME VARCHAR(30),       
             age INT(20),
             dep_name VARCHAR(30),
             dep_location VARCHAR(30)
            
    );


    SELECT * FROM emp;
    ALTER table emp CHARACTER set utf8;
    alter table emp change name name varchar(255) character set utf8;
    alter table emp change dep_name dep_name varchar(255) character set utf8;
    alter table emp change dep_location dep_location varchar(255) character set utf8;

    INSERT INTO emp (id,NAME,age,dep_name,dep_location) VALUES(1,'123',20,'研发部','广州');
    INSERT INTO emp (id,NAME,age,dep_name,dep_location) VALUES(2,'李四',20,'研发部','广州');
    INSERT INTO emp (id,NAME,age,dep_name,dep_location) VALUES(3,'王五',20,'研发部','广州');
    INSERT INTO emp (id,NAME,age,dep_name,dep_location) VALUES(4,'赵六',20,'销售部','深圳');
    INSERT INTO emp (id,NAME,age,dep_name,dep_location) VALUES(5,'大王',20,'销售部','深圳');
    INSERT INTO emp (id,NAME,age,dep_name,dep_location) VALUES(6,'小王',20,'销售部','深圳');
    INSERT INTO emp (id,NAME,age,dep_name,dep_location) VALUES(7,'二王',20,'销售部','深圳');

    image

    1619487599

    image

    CONSTRAINT 外键名称 FOREIGN KEY (外键列名称) REFERENCES 主表名称(主表列名称)


    (外键约束-级联操作)

    image


    *************多表之间的关系与设计数据库要求

    image

    image

    imageimage

    多对多关系实现 需要借助第三张中间表,中间表至少包含两个字段,这两个字段作为第三张表的外键,分别指向两张表的主键,当然需要用到联合主键,保证中间表两个字段联合唯一。PRIMARY KEY(rid,uid)

    一对一关系实现 需要在任意一方添加唯一的外键指向另外一方的主键

    一对多关系实现 需要在多的一方建立外键,指向一的一方主键,不需要唯一

    ------------案例

    1619491406(1)


    *************数据库设计范式

    1619491995(1)

    1619492392(1)

    image

    image

    也就是说 传递依赖要解决,就是一对多必须处理


    **************数据库备份与还原

    命令行 备份:mysqldump -uroot -proot 数据库名称 > 保存的路径

               还原:source 路径+数据库名称;

    **************多表查询

    --------内连接--隐式内连接where条件 / 显示内连接 inner join 表名2 on 条件

    SELECT * FROM emp,dept WHERE emp.dept_id= dept.id

    1619495941(1)

    SELECT emp.name,emp.gender,dept.name FROM emp,dept WHERE emp.dept_id= dept.id

    1619495968(1)

    全部字段:SELECT * FROM emp INNER JOIN dept ON emp.dept_id = dept.id;

    指定字段:SELECT emp.id,emp.`name`,dept.`name` FROM emp INNER JOIN dept ON emp.dept_id = dept.id

    image

    -------------外连接 --左外连接和右外连接

    左外连接

    select 字段列表 from 表1 left outer join 表2 on 条件

    SELECT emp.id,emp.`name`,dept.`name` FROM emp left JOIN dept on emp.dept_id=dept.id

    image

    右外连接 也就是右边表全部数据和左边表交集部分

    SELECT emp.id,emp.`name`,dept.`name` FROM emp right JOIN dept on emp.dept_id=dept.id


    -------------子查询

    查询中嵌套查询,称嵌套查询为子查询

    SELECT * FROM emp WHERE emp.salary=(select MAX(salary) FROM emp)

    *****子查询结果是单行单列

    子查询作为判断条件,查询结果

    image



    *****子查询结果是多行单列

    image

    *****子查询结果是多行多列

    image

    image



    **************事务




    **************DCL





    5.JDBC








  • 相关阅读:
    [转载]spring使用PropertyPlaceholderConfigurer加载properties文件处理中文乱码
    [转载]使用@value注解注入properties配置信息
    [JAVA]使用HttpURLConnection下载文件
    [转载]在Java代码运行时获取当前和调用者的行号,方法名,类名,文件名
    [转载]linux下使用tar命令
    暂时解决java.lang.IllegalStateException: It is invalid to call isReady() when the response has not been put into non-blocking mode *
    oracle使用imp导入数据覆盖(overwirte)原有表数据
    线性基
    Matching Problem 暴力
    Alternative Accounts 贪心匹配
  • 原文地址:https://www.cnblogs.com/rango0550/p/14694573.html
Copyright © 2011-2022 走看看