JAVA基础
1.基本数据类型 : byte short int long float double char boolean byte char short 平级 int float long double
2.引用数据类型:数组、类、接口
3.语句 if swich do while for 判断固定数量,使用if或switch switch效率相对高 switch(值){
case 值:要执行的代码; break; } break可以省略,省略一直执行到见面break,break用于跳出循环,循环嵌套,break只跳出当前的循环continue:结束这个循环,开始下一个循环 "值" 是byte char short int类型 while, for 如果需要控制循环次数,可以互换for,for循环结束后,变量将在内存释放
4.函数 函数是一种单独的功能体现,可以理解为一种方法 功能:1.定义功能 2.包装代码,提高复用性,一个函数可以多次使用 注:函数只能在函数中调用,函数不能定义 主函数的作用:1。确保类别的独立运行 2.程序入口 3.被jvm调用 重载 :函数名相同,参数不同 重写 :函数名相同,内容不同
5.数组 容器用于存储相同类型的数据,编号从0开始,是包装数据的具体实体 定义方式 int a = new int[5] int a ={0,1,2} int a = new int[]{0,1,2}
//二分搜索法。必须有前提:数组中的元素要有序。 public static int halfSeach_2(int[] arr,int key){ int min,max,mid; max = arr.length—1; mid = (max min)>>1; //(max min)/2; while(arr[mid]!=key){ if(key>arr[mid]){ min = mid 1; }
else if(key<arr[mid]) max = mid — 1; if(max<min) return —1; mid = (max min)>>1; } return mid; } 内存java分5片内存 1.寄存器 2.本地方法区 3.方法区 4.栈 5.堆 栈 后进先出,存储局部变量,即释放 堆 先进先出,存储实体,每个实体都有内存的第一个地址
6.面向对象 特点: 1.简化复杂的事情 2.符合当今人们的思维习惯 3.从执行人到指挥官 面向过程:循序渐进,偏向过程,强调功能行为,循序渐进,用函数逐步实现,使用时依次调用函数。 面向对象:从对象的角度思考,将功能放在不同的对象中,强调某些功能对象,最小的程序单元是类别
7.成员变量和局部变量 成员变量 定义在类中,整个类有效,存在堆内存,随着对象的消失而消失 局部变量 定义在方法、参数、句子上,只在大括号内生效,存在于栈中,大括号结束释放
8.构造函数 对于对象的初始化,名称和类别的名称是相同的,不需要定义返回值类型,也没有具体的返回值。所有类别都需要初始化才能使用。如果一个类别没有定义结构函数(参与结构),它将默认生成一个无参与结构。如果定义了参与结构,则无参与结构将被覆盖。一个类别可以有多个结构函数来反映重载
构造函数何时使用:分析事务,发现事务出生时有一些特征,应在构造函数中定义 构造代码块:初始化时调用所有对象,所有对象共同调用构造代码块,对象每建立一次调用一次
Person p = new Person(); 创建一个对象在内存中做了什么? 1:首先在硬盘上指定位置Person.class将文件加载到内存中。 2:执行main方法在栈内存中开辟main方法空间(压栈-进栈),然后main该方法的栈区分配了变量p。 3:在堆内存中开辟实体空间,分配内存的第一个地址值。 4:在实体空间中分配属性的空间,默认初始化。 5:初始化显示空间中的属性。 6:实体结构代码块初始化。 7:调用实体对应的构造函数,初始化构造函数。 8:赋值首地址p ,p变量引用了实体。(指向对象)
9.面向对象的三个特点:包装、继承、多态 包装:隐藏对象的属性和实现细节,只提供外部访问 优点:安全,重用性高,使用方便
static:静态修饰符用于修饰成员变量和成员函数 特点: 1.共享这个对象,使用它static修饰 2.被static修改后的成员可以直接被类名调用 3.与此类一起加载意味着该对象在类产生时产生 4.存在于方法区中,随类的加载而加载,类的消失而消失 成员变量是对象的独特数据,静态变量是对象的共享数据 静态代码块:定义在类中,可以完成类的初始化,随类加载执行,只执行一次。如果主函数在一个类中,则优于主函数执行。 特点: 1.提高代码复用性 2.让类与类产生关系,提供多态的前提
单继承:一个类只有一个父类 多继承:一个类有多个父类。java中只支持单继承,但接口实际上支持多继承 子类调用父类属性值super关键字,this和super都要放在函数的第一行,两者不能共存。当子类结构函数运行时,父类结构函数将首先运行,因为子类结构函数的第一行将隐藏super句子,子类继承了父类的属性,必须首先初始化父类的对象,如果父类没有参与结构,必须使用子类的构造函数super访问父类中的构造函数 final:用于修饰,方法,变量 修改后的类别不能继承;修改后的方法不能覆盖;修改后的变量只能赋值一次 抽象类 abstract 特点 1.抽象类只定义,必须用关键词修改 2.只注重方法声明,不注重方法的实现 3.不能被实例化,必须通过子类继承该抽象类中的所有抽象方法,该子类才能被实例化 4.抽象类中有构造函数,用于初始化子类 5.非抽象方法可以在抽象类中定义 6.abstract不能和final,private,static共存.
接口 interface 界面中有抽象方法,不能实例化,类似抽象类,类与类之间有继承extends,接口与接口之间的实现 implements界面可以多实现,这是多继承改进的后果,避免了单继承的局限性 接口和接口之间可以继承更多 接口是对外提供的规则,功能的扩展,降低了耦合性
抽象跟踪接口是不断向上提取的结果 区别: 1.抽象只能继承,单继承,接口实现,可以多实现 2.抽象和非抽象方法可以在抽象类中定义,子类可以直接继承和使用。接口中的抽象方法需要子类来实现 3.抽象成员修饰符可自定义,界面为Public
多态 反映:父类引用或接口引用指向自己的子类 Animal a = new Cat(); 好处: 提高程序扩展性 缺点:父类引用指向子类,只能访问父类的方法,不能访问子类的方法,早期不能使用后期的功能,访问的局限性 前提:有关系,继承,实现,通常有覆盖操作
理解:在多态中,子类对象自始至终都在做类型变化。父子,父高,子低。子类对象可以调用父类对象中的方法,但父类对象不能调用子类中的方法,除非父类对象转化为子类,否则需要强化高到低,因为子类中有很多新东西,父类不一定有,低到高不需要强化,因为父类中一定有子类。 如果你想使用子类对象的独特方法,如何判断对象的具体子类型?你可以使用关键字 instanceof ; ///判断对象是否指定的接口或继承了指定的类型格式:<对象 instanceof 类型> ,判断对象是否属于指定类型。Student instanceof Person = true;//st
异常 Throwable:可抛出的 Error:错误,通常是jvm产生的 Exception:异常可有针对性地处理 该系统中的所有类别和对象都有一个独特的特点,即可抛性。 可抛性的体现:这个系统中的类和对象都可以throws和throw操作两个关键字 throw用于抛出异常对象,用于函数中的异常对象 throws用于抛出异常类,后跟类名,用于函数 异常分为编译时检查的异常和操作时的异常,Exception编译时子类异常Excepiton特殊子类RuntimeException其子类运行异常 区别:编译时异常在函数中抛出,必须声明函数,否则编译失败。声明原因时,需要调用者处理异常,运行时异常在函数中抛出。 什么时候try什么时候throws 如果内部可以处理,功能内部异常try,如果不能处理,必须声明调用器理。 常见异常 脚标越界异常(IndexOutOfBoundsException)包括数组、字符串; 空指针异常(NullPointerException) 类型转换异常:ClassCastException 没有这个元素异常:NoSuchElementException 不支持操作异常:UnsupportedOperationException
常见软件包 java.lang 语言 java.awt图形界面开发对象 javax.swing提供所有的windows桌面应用程序包括的控件 java.net 网络编程对象 java.io 操作设备上数据的对象 java.util工具包,时间对象,集合框架 java.applet客户端java小程序多线程
进程:正在进行中的程序。进程是一个应用程序运行时的内存分配空间 线程:进程中的一个程序执行控制单元。一个进程至少有一个线程在运行,如果进程中有多个线程,这就是多线程程序,每个线程在栈区都有各自的执行空间,方法,变量。jvm在启动时,首先有一个主线程负责程序的执行,调用main函数 随机性的原理:因为cpu高速切换,哪个线程获得了cpu执行权,那个线程就执行。 返回当前线程的名称:Thread.currentThread().getName() 线程的名称是由:Thread—编号定义的。编号从0开始。线程要运行的代码都统一存放在了run方法中。线程要运行必须通过start方法开启,启动了线程,让jvm调用run方法
创建线程 1.继承Thread类,子类复写run方法。定义一个类继承Thread类,复写run方法,将要运行的代码写进run方法里,通过创建该子类对象创建线程对象,调用start方法开启线程,执行run方法 2.实现Runnable接口,定义一个类实现Runnable接口,覆盖run方法,通过Thread类创建线程对象,将该实现类的子类对象作为实参传给Thread类的构造函数,调用start方法开启线程,运行run方法 线程的状态 被创建 start() 运行 具备执行资格,具备执行权 冻结 线程释放了执行权 临时阻塞 有执行资格,但没执行权 消亡 stop() 为什么会有Runnable接口 单继承的局限性,如果一个类已经有了父类,那就不能继承Thread类,实现该接口可以避免单继承的局限性,它将线程要执行的任务封装成一个对象
run方法和start方法的区别 程序调用start方法时一个新线程会被创建,并且在run方法中的代码会在新线程上运行,直接调用run方法不会创建新线程,run内部的代码会在当前线程上运行。如果要运行需要消耗大量时间的任务,最好使用start方法,否则调用run方法时主线程会被卡住。一旦一个线程被启动,不能重复调用该thread对象的start方法,调用已启动线程的start方法会报异常,但run方法可以重复调用。
多线程的安全问题 1.多个线程操作共享数据 2.多条语句对共享数据进行运算这些语句在某一时刻被一个线程执行时,还未执行完就被其他线程执行了 解决原理:执行完前不让其他线程执行 解决方法:同步代码块 同步 优点:解决线程安全问题 缺点:降低性能 前提 1.有两个或以上的线程 2.多个线程必须保证使用同一个锁 同步函数和同步代码块 同步代码块使用的锁可以是任意对象,同步函数使用的锁是this,一个类中只能有一个同步时,可以使用同步函数,如果有多个同步,必须使用同步代码块。同步代码块更灵活 常见的javaAPI String字符串一旦被初始化就不能改变 常见的String字符串方法 length();获取长度 char charAt(int index)获取指定位置的字符 int indexOf(int ch)获取指定字符的位置 String substring截取子符串 equals判断是否相同 String[] split分割字符串 String replace(old,new)字符串内容替换 compareTo();参数字符串=该字符串,返回0,小于,返回<0,大于返>0
StringBuffer和StringBuilder 可以对字符串的内容进行修改,是一个可变长度的容器,可以储存任意类型的数据,最后要变成字符串 固定方法 append追加数据到尾部 insert插入数据 delete删除 replace替换 indexOf查找 reverse反转 二者的区别 Buffer线程安全,效率低,Builder不安全,效率高,单线程用Builder,多线程用Buffer
包装类 byte Byte short Shor int Integer long Long float Float double Double char Character Boolean Boolean 除了Character,都有 XXX parseXXX方法
集合框架特点 1.用于储存对象 2.可变长度
和数组的区别 1.数组长度固定,集合可变 2.数组可以储存基本数据类型和引用数据类型(接口,类,数组),集合只能储存引用数据型 3.数组必须保证储存的都是同一数据类型,集合不用 数据结构:就是容器中存储数据的方式。 类型有 线性表(ArryaList)链表(LinkedList)队列(Queue)图(Map)树(Tree)
Collection接口 List:有序,存入和取出顺序一致,元素有索引,可以重复 Set:无序,不可重复 Iterator接口迭代器,是一个接口,用于取集合中的元素
List接口是Collection接口的子接口,最大特点是List的特有方法都有索引有序,元素都有索引,可以重复 1.ArrayList:线程不同步,查找快,增删慢,底层数据结构是数组2.LinkedList:线程不同步,增删快,查找慢,底层数据结构是双链表3.Vector:线程同步,查找增删都慢,底层数据结构是数组 常用方法 add插入一个元素 addAll插入一堆元素 remove删除 indexOf获取指定元素第一次出现的索引为 Object set修改 listIterator获取所有元素,list特有的迭代器List集合支持对元素的增删改查
Set接口 Set接口取出方式只有使用迭代器 1.HashSet:线程不同步,无序,高效,保证唯一性通过元素的HashCode方法结合equals实现。元素的HashCode相同,才使用equals,不同则不用使用 2.LinkedHashSet:有序,是HashSet的子类 3.TreeSet:不同步,底层是二叉树,对Set集合中的元素进行指定顺序的排序 哈希表的原理 1.对对象元素中的关键字进行哈希算法运算,得到哈希值 2.哈希值是这个元素的位置 3.如果元素的哈希值相同,再判断这两个元素是否相同,如果相同,不用重复储存,如果不,向后延伸储存 4.存储哈希值的结构叫哈希表
对于ArrayList,判断元素是否存在或者删除元素,依据equals方法 对于HashSet,依据HashCode和equals
TreeSet 用于对Set集合进行元素的指定顺序排序,排序需要依据元素自身具备的比较性如果元素不具备比较性,运行时会发生ClassCastException异常
所以需要元素实现Comparable接口,强制让元素具备比较性,复写CompareTo方法依据返回值,确定元素的位置,如果返回0,证明该元素存在,不储存,这就是保证唯一性方法判断是,需要分主要条件和次要条件,主要条件相同,再判断次要条件,按照次要条件排序两种排序方式
Comparable Comparetor 1.让元素自身具备比较性,需要元素对象实现Comparable 接口,覆盖compareTo方法 2.让集合自身具备比较性,需要定义一个实现了Comparator接口的比较器,覆盖compare法,将该类对象作为实参传递给TreeSet集合构造函数,第二种方法较为灵活
Map集合 HashTable:线程同步,不可存null,底层哈希表 HashMap:线程不同步,可以存null底层哈希表 TreeMap:可以对map集合中的键进行指定顺序的排序,底层二叉树 Map集合存储和Collection有很大不同 Collection一次存一个元素,Map存一对 Collection是单例结合,Map是双列Map存的是键值对,要保证键的唯一性
Collection 和 Collections的区别: Collections是个java.util下的类,是针对集合类的一个工具类,提供一系列静态方法实现对集合的查找、排序、替换、线程安全化(将非同步的集合转换成同步的)等操作。 Collection是个java.util下的接口,它是各种集合结构的父接口,继承于它的接口要有Set和List,提供了关于集合的一些操作,如插入、删除、判断一个元素是否其成员、遍历。
get请求和post请求的区别 get请求的数据多附加在url之后以?分割URL和传输数据,多个参数用&连接。URL的编码格式时ASCII格式,不是uniclde,所有的非ASCII字符都要编码后再传输 post请求会把请求的数据放置在HTTP请求包的包体中,上面的item=bandsaw就是实际传输的数据 总结就是,get请求的数据会暴露在地址栏中,且传输数据会收到url长度的限制,post不会暴露且不受限制,所以post请求的安全性要比get请求高 后端接受前端参数的三种注解方式 1.@RequestParam注解 作用:将指定的请求参数赋值给方法中的形参 接受形式:get传参请求 属性:value:绑定请求参数名,默认绑定同名形参;required:是否必须,默认true,表示请求中一定要有相应参数,否则报错;defaultValue默认值,表示如果请求中没有接收到该值的默认值 2.@PathVariable注解 1. 作用:接受请求路径中占位符的值 2. 接受形式:get路径请求 3. 属性:value:String形式,绑定请求的参数,默认绑定同名形参 3.@RequestBody注解 1. 作用:接受前端传递的json字符串 2. 接受形式:post请求
增强for循环 for(元素类型 变量名 : 集合/数组){ }
枚举类enum 针对对象的某个属性的值不能任意,必须是固定一组数值中的某一个
常用API Math数学运算工具类 Date日期类月份0-11日期转字符串 formatCalendar日历类
IO流 用于处理设备上的数据分类 1.输入流和输出流(读和写) 2.字节流和字符流 字节流:InputStream OutputStream 字符流:Reader Writer
File类:将文件系统中的文件和文件夹封装成了对象。提供了更多的属性和行为可以对这些件和文件夹进行操作。这些是流对象办不到的,因为流只操作数据。 File类常见方法: 1:创建。 boolean createNewFile():在指定目录下创建文件,如果该文件已存在,则不创建。而对作文件的输出流而言,输出流对象已建立,就会创建文件,如果文件已存在,会覆盖。除续写。 boolean mkdir():创建此抽象路径名指定的目录。 boolean mkdirs():创建多级目录。 2:删除。 boolean delete():删除此抽象路径名表示的文件或目录。 void deleteOnExit():在虚拟机退出时删除。注意:在删除文件夹时,必须保证这个文件夹中没有任何内容,才可以将该文件夹用delete删除。window的删除动作,是从里往外删。注意:java删除文件不走回收站。要慎用。 3:获取. long length():获取文件大小。 String getName():返回由此抽象路径名表示的文件或目录的名称。String getPath():将此抽象路径名转换为一个路径名字符串。 String getAbsolutePath():返回此抽象路径名的绝对路径名字符串。String getParent():返回此抽象路径名父目录的抽象路径名,如果此路径名没有指定父目,则返回 null。 long lastModified():返回此抽象路径名表示的文件最后一次被修改的时间。 File.pathSeparator:返回当前系统默认的路径分隔符,windows默认为 “;”。 File.Separator:返回当前系统默认的目录分隔符,windows默认为 “\”。4:判断: boolean exists():判断文件或者文件夹是否存在。 boolean isDirectory():测试此抽象路径名表示的文件是否是一个目录。boolean isFile():测试此抽象路径名表示的文件是否是一个标准文件。boolean isHidden():测试此抽象路径名指定的文件是否是一个隐藏文件。 boolean isAbsolute():测试此抽象路径名是否为绝对路径名。 5:重命名。 boolean renameTo(File dest):可以实现移动的效果。剪切+重命名。String[] list():列出指定目录下的当前的文件和文件夹的名称。包含隐藏文件。如果调用list方法的File 对象中封装的是一个文件,那么list方法返回数组为null。如果封装对象不存在也会返回null。只有封装的对象存在并且是文件夹时,这个方法才有效。
反射 动态加载一个指定的类,并获得该类中的所有内容,反射技术可以对一个类进行解剖 好处:大大增强了程序的扩展性 基本步骤: 1.获得Class对象,就是获取到指定的名称的字节码文件对象 2.实例化对象,获得类的属性,方法和构造函数 3.访问属性,调用方法,调用构造函数创建对象
如何获取Class对象 1.通过getClasss,但必须要创建该类对象才可以调用 2.静态的属性class,但必须先声明该类 前两种都不利于程序的扩展,因为都需要在程序使用具体的类完成 3.使用Class类中的forName方法指定什么类名,就获取什么类的字节码文件对象,只需要将类名的字符串传入即可 // 1. 根据给定的类名来获得 用于类加载 String classname='xxxxxxxx'; Class clazz = Class.forName(classname); // 2. 如果拿到了对象,不知道是什么类型 用于获得对象的类型Object obj = new Person(); Class clazz1 = obj.getClass();// 获得对象具体的类型 // 3. 如果是明确地获得某个类的Class对象 主要用于传参 Class clazz2 = Person.class;
反射的用法: 1)、需要获得java类的各个组成部分,首先需要获得类的Class对象,获得Class对象的三方式: Class.forName(classname) 用于做类加载 obj.getClass() 用于获得对象的类型 类名.class 用于获得指定的类型,传参用 2)、反射类的成员方法: Class clazz = Person.class; Method method = clazz.getMethod(methodName, new Clas[{paramClazz1,paramClazz2}); method.invoke(); 3)、反射类的构造函数: Constructor con = clazz.getConstructor(new Clas[{paramClazz1,paramClazz2,...}) con.newInstance(params...) 4)、反射类的属性: Field field = clazz.getField(fieldName); field.setAccessible(true); field.setObject(value);
获取了字节码文件对象后,最终都需要创建指定类的对象: 创建对象的两种方式(其实就是对象在进行实例化时的初始化方式):1,调用空参数的构造函数:使用了Class类中的newInstance()方法。2,调用带参数的构造函数:先要获取指定参数列表的构造函数对象,然后通过该构造函数对象的newInstance(实际参数) 进行对象的初始化。 综上所述,第二种方式,必须要先明确具体的构造函数的参数类型,不便于扩展。所以一情况下,被反射的类,内部通常都会提供一个公有的空参数的构造函数
B/S 浏览器/服务器程序 C/S 客户端/服务
MySql
创建表 create table '表名' ( ‘xx’列类型 [属性][索引][注释] )
数值类型 tinyint 非常小的数据 smallint 较小 mediumint中等大小 int 标准中等整数 bigint 较大整数 float 单精度浮点数 double 双精度浮点数 decimal 字符串形式浮点数
字符串类型 char[(M)] 固定长字符串,检索快,费空间 varchar[(M)] 可变字符串 tinytext 微型文本串 text 文本串
日期和时间类 DATE YYYY-MM-DD,日期格式 TIME Hh:mm:ss,时间格式 DATETIME YYYY-MM-DD hh:mm:ss TIMESTAMP YYYYMMDDhhmmss 格式表示的时间戳 YEAR YYYY格式的年份
数据表类型 MyISAM,InnoDB
名称 MyISAM InnoDB 事务 不支持 支持 数据行锁定 不支持 支持 外键 不支持 支持 全文索引 支持 不支持 表空间大小 小 大,约2倍 适用场合 节约空间及响应速度 安全性,事务处理,多用户操作
修改数据库 修改表名 ALTER TABLE 旧 RENAME AS 新 添加字段 ALTER TABLE 表名 ADD字段名 列属性[属性] 修改字段 ALTER TABLE 表名 MODIFY 字段名 列类型[属性] ALTER TABLE 表名 CHANGE 旧 新 列属性[属性] 删除字段 ALTER TABLE 表名 DROP 字段名
删除表 DROP TABLE 表名 如果删除不存在的表会报错 外键 将一个表的值放在第二个表中表示关联,这个值是第一个表的主键,第二个表保存这些值的属性称为外键 foreign key 作用 保持数据一致性,完整性,主要目的是控制储存在外键表中的数据,约束,使两张表形成关联,外键只能引用外表中列的值或空值
删除具有主外键关系的表时,先删子再删主
添加 INSERT INSERT INTO 表名[(字段1,字段2,字段3)] VALUES('值1','值2','值3')
更新 UPDATE
UPDATE 表名 SET column_name= value [,column_name2=value2,...] [WHEREcondition];
删除 DELETE
DELETE FROM 表名 [WHERE condition]; TRUNCATE
清空表数据,结构索引约束不变,比DELETE速度快,但不删除表结构,会重置自增计数器,对事物没有影响 TRUNCATE [TABLE] 表名;
SELECT
SELECT * FROM TABLE
inner/left/right join TABLE2
WHERE 条件
GROUP BY 按照字段分组
HAVING 过滤分组的记录需要满足的次要条件
ORDER BY 排序
LIMIT 分页
DISTINCT 去掉重复结果
SELECT DISTINCT ID FROM TABLE;
模糊查询 IS NULL a IS NULL, a是NULL,为真 IS NOT NULL a IS NOT NULL,a不是NULL,为真 BETWEEN a BETWEEN b AND c,a在b和c之间 LIKE a LIKE b,模糊查询,a匹配b
LIKE '佐%' 查询佐 LIKE '佐_' 查询佐后面有一个字的 LIKE '佐__' 查询佐后面有两个字的 LIKE '%佐%' ,查询名字里有佐字的
IN a IN(b,c,d),a等于bcd中的某一个
连接查询 INNER JOIN 内连接,查交集,表中有至少一个匹配,返回行 LEFT JOIN 左连接,有匹配返回匹配,无匹配返回左表所有行,右表用NULL填充 RIGHT JOIN 右链接,与左连接相反
SELECT s.studentno,studentname,subjectno,StudentResult FROM student s INNER JOIN result r ON r.studentno = s.studentno 排序和分页 ORDER BY 排序 默认按照ASC升序对记录排序,如果想降序使用DESC关键字 ORDER BY 属性名 DESC LIMIT分页 LIMITE [offset,x] 每页显示五条数据 LIMIT 0,5 前面的是第几页开始,后面的是大小规格
子查询 在一个查询里嵌套另一个查询,使用连接查询可以达到相同效果
-- 方法一:使用连接查询 SELECT studentno,r.subjectno,StudentResult FROM result r INNER JOIN `subject` sub ON r.`SubjectNo`=sub.`SubjectNo` WHERE subjectname = '数据库结构-1' ORDER BY studentresult DESC;
-- 方法二:使用子查询(执行顺序:由里及外) SELECT studentno,subjectno,StudentResult FROM result WHERE subjectno=( SELECT subjectno FROM `subject` WHERE subjectname = '数据库结构-1' ) ORDER BY studentresult DESC;
MYSQL 函数
数据函数 SELECT ABS 绝对值 SELECT CEILING 向上取整 SELECT FLOOR 向下取整 SELECT RAND 返回随机数 SELECT SIGN 负数返回-1.正数返回1,0返回0
字符串函数 SELECT CHAR_LENGTH('xxxxxxxxxx') 返回引号里字符串的字数 SELECT CONCAT('A','B','C') 将ABC合并起来 SELECT INSERT('abcd',1,2,'ef') 替换字符串,从规定的位置(1)替换规定的长度 (2) SELECT LOWER('shuilaiqi')小写 SELECT UPPER ('shuilaiqi') 大写 SELECT LEFT('XXXXXXXXXX',5) 从左边截取 SELECT RIGHT('XXXXXXXXXX',5) 从右边截取 SELECT REPLATE('ABCDEFG','CD','ZZ') 替换 SELECT SUBSTR('ABCDEFG',2,3)截取,从开始截取3个 SELECT REVERSE('adcdefg') 反转
日期和时间函数 SELECT CURRENT_DATE(); /*获取当前日期*/ SELECT CURDATE(); /*获取当前日期*/ SELECT NOW(); /*获取当前日期和时间*/ SELECT LOCALTIME(); /*获取当前日期和时间*/ SELECT SYSDATE(); /*获取当前日期和时间*/ -- 获取年月日,时分秒 SELECT YEAR(NOW()); SELECT MONTH(NOW()); SELECT DAY(NOW()); SELECT HOUR(NOW()); SELECT MINUTE(NOW()); SELECT SECOND(NOW()); 聚合函数 COUNT() 返回满足SELECT条件的记录总和数 SELECT COUNT(*/1) 不建议用COUNT(*),会查出来字段为Null,效率低 COUNT(1)不会查出来NULL
SUM() 返回数字字段或表达式列统计,返回一列的和 AVG() 平均值 MAX 返回最大值 MIN返回最小值 SELECT SUM(StudentResult) AS 总和 FROM result; SELECT AVG(StudentResult) AS 平均分 FROM result; SELECT MAX(StudentResult) AS 最高分 FROM result; SELECT MIN(StudentResult) AS 最低分 FROM result; MD5加密 update 表名 set 列名 = md59(列名); INSERT INTO testmd5 VALUES(4,'kuangshen3',md5('123456'));
事务 ACID原则 A 原子性 事务中所有操作要么都完成,要么都不完成,不能停滞在中间某个环节,出现错误则回滚到最初,就像该事务从未执行
C 一致性 事务可以封装改变状态,必须保证始终与系统处于一致,主要特征是保护性和一致性,如果五个账户各有100块,无论这五个账户怎么交易,总金额还是500块
I 隔离性 隔离状态执行事务,两个事务在相同时间执行相同的功能,事务的隔离性将保证每个事务在系统中认为只有一个在使用系统,防止事务操作间混淆
D 持久性 事务完成后,该事务对数据库的更改便持久保存在数据库中,不会被回滚
基本语法 改变自动提交模式,MySQL默认自动提交,使用事务要关闭自动提交 SET autocommit =0; 关闭 SET autocommit =1; 开启
START TRANSACTION 开始一个事务,标记事务起始点 COMMIT 提交事务给数据库 ROLLBACK 回滚事务 SET autocommit =1; 开启自动提交保存点 SAVEPOINT xxxx 设置一个叫xxxx的保存点 ROLLBACK TO SAVEPOINT xxxx 回滚到保存点 RELEASE SAVEPOINT xxxx 删除保存点
CREATE DATABASE `shop`CHARACTER SET utf8 COLLATE utf8_general_ci;
USE `shop`;
CREATE TABLE `account` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(32) NOT NULL,
`cash` DECIMAL(9,2) NOT NULL,
PRIMARY KEY (`id`) ) ENGINE=INNODB DEFAULT CHARSET=utf8
INSERT INTO account (`name`,`cash`)
VALUES('A',2000.00),('B',10000.00)
-- 转账实现
SET autocommit = 0; -- 关闭自动提交
START TRANSACTION; -- 开始一个事务,标记事务的起始点
UPDATE account SET cash=cash-500 WHERE `name`='A';
UPDATE account SET cash=cash+500 WHERE `name`='B';
COMMIT; -- 提交事务
# rollback;
SET autocommit = 1; -- 恢复自动提交
隔离性问题 脏读:一个事务读取并修改了数据,未提交时另一个事务也访问了
丢失修改:一个事务读取数据时,修改了这个数据,另一个事务读取这个数据时也修改了,此时A对数据的修改结果就丢失了
不可重复读:一个事务读取数据时,另一个事务访问并修改了这个数据,第一个事务再次读取这个事务时发现第一次读取和第二次读取的值不一样
幻读:一个事务读取数据时,另一个事务插入了一些输入,导致前一个事务读取数据时凭空出现了一些数据
不可重复读和幻读的区别在于,不可重复读注重值被修改,幻读注重值的添加或删除
默认隔离级别
读取未提交 最低隔离级别,允许读取未提交的数据变更,可能导致脏幻不可重复读
读取已提交 允许读取已提交的数据变更,可能导致幻或不可重复读
可重复读 对同一字段多次读取结果都一样,可能导致幻读
可串行化 最高级别,所有事务一次逐个执行,完全服从ACID的隔离级别
索引 作用 1.提高查询速度 2.确保数据唯一性 3.加速表与表之间的链接,实现表之间参照完整性 4.使用分组和排序子句检索时,显著减少分组和排序的时间 5.全文检索字段进行搜索优化 分类 Primary Key 主键索引 Unique 唯一索引 Index 常规索引 FullText 全文索引
主键索引 特点 最常见的索引类型 确保数据记录的唯一性 确定特定数据记录在数据库中的位置
唯一索引 作用 避免同一个表中某数据列中的值重复 与主键索引的区别 主键索引只能有一个,唯一索引可能有多个 CREATE TABLE `Grade`( `GradeID` INT(11) AUTO_INCREMENT PRIMARYKEY, `GradeName` VARCHAR(32) NOT NULL UNIQUE -- 或 UNIQUE KEY `GradeID` (`GradeID`) ) 常规索引 作用 快速定位特定数据 注意 index和key关键字都可以设置常规索引 应该加在查找条件的字段 不宜添加太多,影响数据增删改操作
ALTER TABLE '表名' ADD INDEX '索引名' ('列名1','列名2');
全文索引 作用 快速定位特定数据 注意 MySQL 5.6 以前的版本,只有 MyISAM 存储引擎支持全文索引; MySQL 5.6 及以后的版本,MyISAM 和 InnoDB 存储引擎均支持全文索引 只能用于CHAR,VARCHAR,TEXT类型的列 适合大型数据集 索引准则 1.不是越多越好 2.不要对经常变动的数据加索引 3.小数据表不要加索引 4.索引一般加在查找条件字段
三大范式 第一范式 确保每列的原子性,即每列都不可再分 第二范式 首先满足第一范式,其实要求每个表只描述一件事 第三范式 首先满足一二范式,除了主键以外其他列都不传递依赖于主键列 连接池 数据库连接池负责分配,管理和释放数据库链接,它允许应用程序重复使用一个现有的数据库链接,而不是重新建立一个。 数据库连接池在初始化时将创建一定数量的数据库连接放在连接池中,数量由最小数据库链接数来设定,无论是否被使用吗,都将一直保证至少有这么多连接数量。连接池的最大数据库连接数限定了这个连接池能占有的最大链接数,当应用程序向连接池请求的链接数超过最大数,会被加入到等待队列里。
最小连接数:时连接池一直保持的数据库链接,如果应用程序对数据库连接的使用量不大,将会有大量数据库连接资源被浪费 最大连接数:连接池能申请的最大链接数,如果数据库链接请求超过次数,后面的数据库链接请求将被加入到等待队列,影响后续操作 开源数据库连接池,通常把DataSource的实现,称之为数据源,数据源中都包含了数据库连接池的实现
DBCP,C3P0,在使用了数据库连接池后,项目实际开发就不需要编写连接数据库的代码,直接从数据源中获得数据库的链接
DBCP数据源,使用需要添加Commons-dbcp.jar 连接池的实现 Commons-pool.jar依赖 C3P0 使用较多,DBCP没有自动回收空闲连接的功能C3P0有 SQL优化 1.查询语句中减少select * 2.尽量减少子查询,改用连接查询 3.减少in 或 not in,使用 exist,not exist 4.尽量避免where子句中使用!=,会将引擎放弃使用索引而进行全表扫描 5.尽量避免where子句中对字段进行null判断 MySQL中的锁 表级锁:开销小,加锁快,不会死锁,发生锁冲突的概率最高,并发度最低 行级锁:开销大,加锁慢,会出现死锁,发生锁冲突的概率最低,并发度最高 页面锁:开销和加锁时间趋于表行之间,会出现死锁,并发度一般 char和varchar 二者在存储和检索方面有所不同 char长度固定为创建表声明的长度,1-255,当char被储存时,会被用空格填充到特定长度检索char需删除尾随空格 MySQL优化顺序 1.sql语句及索引的优化 2.数据库表结构 3.系统配置 4.硬件 乐观锁 一个用户读取数据时,别人不会写自己所读的数据,悲观锁时觉得对方会读自己所读的数据,所以先对要读取的数据加锁
MyBatis
CRUD操作 namespace 配置文件中的namespace中的名称为对应Mapper接口或Dao接口的完整报名,必须一致
Select Select是mybatis最常用标签之一 id 1. 命名空间唯一的标识符 2. 接口中的方法名与映射文件中的SQL语句ID一一对应 parameterType 1. 传入SQL语句的参数类型 resultType
<select id=”selectById” resultType=”com.zyq.wife”>
select * from user where id= #{id}
insert
标签与select差不多
<insert id=“addUser” parameterType=”com.xxx”>
insert into user (id,name) values (#{id},#{name})
</insert>
update
标签跟select差不多
<update id=”updateUser” parameterType=”com.xxx”>
update user set name=#{name} from user where id =#{id}
</update>
delete
<delete id=”updateUser” parameterType=”com.xxx”>
delete from user where id=#{id}
</delete>
对象工厂 Mybatis每次创建结果对象的实例时,都会使用对象工厂实例来完成。 生命周期和作用域
开始————SqlSessionFactoryBuilder(通过xml文件或配置文件生成SqlSessionFactory)————SqlSessionFactory————SqlSession ————SQL Mapper————结束 SqlSessionFactoryBuilder的作用在于创建SqlSessionFactory,创建成功就是去作用,所以只存在创建SqlSessionFactory的方法中,最佳作用域是方法作用域 SqlSessionFactory可以被认为是一个数据库连接池,作用是创建Sqlssioin接口对象,生命周期存在于整个MyBatis应用中,一旦创建,就要长期保存,直至不再使用Mybatis应用,它占据数据库连接资源,创建过多不利于对数据库资源控制,所以应该作为一个单例,在应用中被共享,所以最佳作用域是应用作用域 SqlSession相当于一个数据库连接,用户可以在一个事务里执行多条SQL,通过它的commit,rollback提交或回滚,它应该存活在一个业务请求中,处理完整个请求后,应该关闭该连接,归还给SqlSessionFactory,最佳作用域是请求或方法作用域
ResultMap 当实体类设置的属性值与数据库对不上时,会出现查询出空值的问题 例如,在一个实体类中,设置了name,和password属性,但在数据库中,列名是name和pwd,password和pwd并不能对上,所以查询不到
解决方法 1. 起别名 select name,pwd as password from user where ….. 2. 使用结果集映射 ResultMap
<resultMap id =”UserMap” type=”user”>
<result column=“name” property = “name”/>
<result column=“pwd” property = “password”/>
</resultMap>
<select id=”selectById” resultMap=”UserMap” >
……….
</select>
使用注解开发 关于接口的理解 接口从更深层次的理解,应该是定义(规范,约束)与实现(名实分离)的分离 接口的本身反映了系统设计人员对系统的抽象理解 接口应有两类,第一类是对一个个体的抽象,可对应为一个抽象体 第二类是对一个个体某一方面的抽象,即形成一个抽象面 一个个体有可能有多个抽象面,抽象体与抽象面是有区别的
面向对象指考虑问题时,以对象为单位,考虑它的属性及方法 面向过程指考虑问题时,以一个具体的流程为单位考虑它的实现 接口设计与非接口设计是针对复用技术而言的,与面向过程(对象)不是一个问题,更多的体现是对系统整体的架构 具体注解不在这写了,很简单
关于@Param 该注解用于给方法参数起个名字,使用原则如下 1. 在方法只接受一个参数的情况下,可以不使用 2. 在方法接受多个参数的情况下,建议一定使用 3. 如果参数是JavaBean,不能使用 4. 只有在参数只有一个,且是JavaBean时,一定不能使用该注解
#与$的区别 #相当于给前端传入的数据加上‘’符号,可以有效防止SQL注入,#{}会被解析成一个参数占位符,$相当于直接把传入的数据接上去 例如前端传了一个1 where id= #{id} 等效于 where id =’1’ where id=${id} 等效于 where id=1
多对一和一对多的处理 多对一 多个学生对应一个老师,对于学生,这就是多对一
按查询嵌套处理 需求:获得所有学生及其对应老师的信息 1. 获取所有学生的信息 2. 根据学生信息中关联的老师的ID,获得该老师的信息 如何完成 1. 做一个结果集映射StudentTeacher 2. 映射的类型为Student 3. 学生中老师的属性是teacher,关联tid
<select id =”getStudents” resultMap=”StudentTeacher”>
select * from student
</select>
<resultMap id=”StudentTeahcer” type=”Student”>
<!--association关联属性 property属性名 javaType属性类
</resultMap>
<select id=”getTeacher” resultType=”teacher”>
select * from teacher where id =#{id}
</select>
按结果嵌套处理
<select id=”getStudents2” resultMap=”StudentTeacher2”>
select s.id sid,s.name sname,t.name tname from student s,
teacher t
where s.tid = t.id
</select>
<resultMap id=”StudentTeacher2” type=”Student”>
<id property=”id” column=”sid” />
<result property=”name” column=”sname”/>
<association property=”teacher” javaType=”Teacher”>
<result property=”name” column=”tname”/>
</association>
</resultMap>
按照查询进行嵌套处理类似SQL中的子查询 按照结果进行嵌套处理类似SQL中的关联查询
一对多的处理 一个老师有多个学生,对于老师就是一对多的现象 思路 1. 从学生表和老师表中查出学生的id,姓名,老师的姓名 2. 从查询出来的结果做映射集 3. 集合用collection,JavaType和ofType都是用来指定对象类型的,JavaType用来指定pojo中属性的类型,ofType用来指定映射到List集合属性中的pojo类型
按照查询嵌套处理
<select id =”getTeacher2” resultMap=”TeacherStudent2”>
select * from teacher where id =#{id}
</select>
<resultMap id=”TeacherStudent2” type=”Teacher”>
这里的column是一对多的外键
<collection property=”students” javaType=”ArrayList”
offType=”Student” column=”id” select=”getStudentByTId”/>
<select id=”getStudentByTId” resu