反射
1.什么是反射?
反射是一开始并不知道要初始化的是什么类,无法使用new
来实例化创建对象,主要是通过JDK提供的反射API来实现,在运行时才知道要操作的是什么类,并且可以获取到类的完整构造以及调用对应的方法,这就是反射
2.反射的作用
在加载类的时候----编译后Class(类对象),它里面通过创建对象 让程序之间解耦;
3.Class字节码文件获取方式
方式1:任意Java对象的getClass()
方式2:任意Java类型的class属性
方式3:Class.forName("类或者接口的全限定名称") ;
4.通过反射获取构造器Constructor并创建对象
private 类名(String xx,int xx){....}
//获取当前类的字节码文件对象
Class clazz = Class.forName("类的全限定名称") ;
//获取指定的构造方法所在的Constrcutor类对象--->
//Constructor con = clazz.getConstructor() ;//无参构造方法 公共的
//创建当前类实例
//Object obj = con.newInstance() ;
Constructor myCon = clazz.getDeclaredConstructor(String.class,int.class) ;
//私有的构造方法-->抑制Java语言检查功能
myCon.setAccessiable(true) ;
Object obj = myCon.newInstance() ;
5.通过反射获取成员方法Method类对象并调用方法
//获取当前类的字节码文件对象
Class clazz = Class.forName("类的全限定名称") ;
//如果当前构造方法是无参的,而且是公共的
//直接使用Class--->public T newIntance() :创建当前类实例
Object obj = clazz.newInstance() ;
//通过字节码文件对象获取当前类的成员方法所在的类对象Method
Method m = clazz.getDeclaredMethod("方法名",参数类型的class属性) ;
//如果方法私有的,需要取消Java语言检查
m.setAccessiable(true) ;
//调用方法
Object returObj = m.invoke(obj,实际参数) ;//如果本身方法有返回值,则返回,如果没有返回值,不用返回
6.代理设计模式
核心思想:让代理角色帮助真实角色完成一件事情(对我们业务方法进行增强)
静态代理
代理角色和真实角色需要实现同一个接口
动态代理
jdk动态代理
里面需要前提有一个接口
java.lang.reflect.Proxy提供了创建动态代理类和实例的静态方法
public static Object newProxyInstance(
ClassLoader loader, //参数1:当前接口对象的类加载器
Class<?>[] interfaces, //参数2:代理实现接口列表字节码文件对象的数组
InvocationHandler h //参数3:代理实例 调用处理程序实现的接口
) throws IllegalArgumentException
7.设计模式:是一种设计思想(优化增强)
1)创建型设计模式--->对象的创建 (使用比较多的)
常见的单例设计模式,简单工厂--静态方法工厂模式,工厂方法模式
构建者(Builder)..
2)结构型设计模式:构造一个对象(行为,属性)---->代理,装饰者,适配器...
代理设计模式(Proxy)
适配器模式(Adapter)
桥接模式(Bridge)
装饰者设计模式(Decorator)
3)行为型设计模式
将多个类或者对象相互协作,共同完成单个对类或者对象无法单独完成的任务!
解释器
模板方法模式
观察者设计模式
8.单例设计模式 始终在内存中始终只有一个对象! 饿汉式和懒汉式
/*单例设计模式:
在内存中始终只有当前类的一个实例!(只有一个对象)
饿汉式和懒汉式
饿汉式:不会出现问题的单例设计模式
1)构造方法私有化
2)类一加载,成员位置---私有的静态实例变量(立即创建一个对象)
3)对外提供一个静态的公共的访问方法,返回值是当前类本身
*/
// Runtime本身就是一个饿汉式
public Student{
private static Student s = new Student() ;
private Student(){}
public static Student getStudent(){
return s ;
}
}
/*
懒汉式 :可能出现安全问题的单例设计模式 (懒加载/延迟加载)
一个用户有100账户,一对多的关系
1)构造方法私有化
2)在类的成员位置,声明一个静态类变量,当前类本身
3)提供对外的公共访问方法,返回值当前类本身,需要对当前变量进行判断,如果为null,在创建
*/
public Student{
private static Student s ;
private Student(){}
public synchronized static Student getStudent(){
if(s ==null){
s = new Student() ;
}
return s ;
}
}
数据库
1.DDL语句 建库 ,查询库的信息,删除库,修改库的字符集
-- 创建库
create database if not exists 库名;
create database 库名;
-- 查询库的信息
show create database 库名;
-- 删除库
drop database if exists 库名 ;
drop database 库名;
-- 修改的字符集
alter database 库名 default character set 字符集格式;
2.DDL语句建表,修改库中的字段名称以及字段类型,删除表
-- 创建表
create table 表名(
字段名称1 字段类型1,
字段名称2 字段类型2,
...
字段名称n 字段类型n
) ;
-- 修改表的字段名称
alter table 表名 change 旧字段名称 新字段名称 以前的数据类型;
-- 修改表的字段类型
alter table 表名 modify 字段名称 新的数据类型;
-- 删除
drop table if exists 表名;
drop table 表名;
-- 查询表结构
desc 表名;
3.DML语句: 插入数据,修改数据,删除数据
-- 插入数据
-- 插入全表,一次插入多条
insert into 表名 values(值1,值2,....值n),(值1,值2,....值n),...() ;
-- 插入部分字段,一次插入多条
insert into 表名(字段名称1,字段名称2,部分字段....) values(值1,值2,部分值),(值1,值2,部分值...),();
-- 修改数据---按照条件修改
update 表名 set 字段名称1 =值1,字段名称2 = 值2 where 字段名称 = 值;
-- 删除:按照条件删除
delete from 表名 where 字段名称 = 值;
4.delete from 表名和truncate table 表名的区别?
前者:仅仅是删除全表数据
表的结构还在,如果表中主键自增长的字段,不会影响这个自增主键的值,下一次插入数据,依然在上一次删除的最后一个自增长主键的值继续自增;
后者:删除表的全部数据,同时删除了表,然后创建一张空表
直接影响了自增长主键的值,下一次插入数据,从1开始继续自增
5.查询指定字段并指定别名
select
字段名称1 as 别名名称1,
字段名称2 as 别名名词2,
...
from
表名;
6.条件查询
语法(运算步骤):
select 查询列表;(3) from 表名;(1) where 筛选条件;(2)
分类:
1.按条件表达式筛选
条件运算符:> < = <>(!=) >= <=
2.按逻辑表达式筛选
逻辑运算符:and(&&) or(||) not(!)
3.模糊查询
like , between and , in , is null
一,按条件表达式筛选、
查询工资>1200的员工信息;
SELECT * FROM employees WHERE salary>12000;
二、逻辑运算符筛选
nd(&&) or(||) not(!)
用于:需要多个条件表达式来进行判断时;
三、模糊查询
1.like(查找含有某种特殊的范围)
特点:一般和通配符搭配使用,可以判断字符型和数值型;
通配符:
'% '为任意多个字符,也包含0字符;
'_ '为任意单个字符;
案例1:查询表中包含了字符a的列表信息
select * from 表 where 筛选条件 like ‘%a%’;
案例2: 查询表中中第二个字符为_的列表信息;
select 查询列表 from 表 where 筛选条件 like ‘_\_%’;
转译字符 mysql中'\'为自带的转译字符,将特殊字符转换为普通字符;我们也可以通过自己来自定义转译字符,但需要后面用ESCAPE 关键字来进行说明;
select 查询列表 from 表 where 筛选条件 like ‘_$_%’ ESCAPE ‘$’;
2.between and(查询某范围的)
between 100 and 120 == >=100 and <=120;
①使用between and 可以提高语句的简洁度;
②包含两个临界值;
③两个临界值位置不能交换;案例1: 查询员工编号在100到120之间的员工信息
select * from 员工表 where 员工id列表 between 100 and 120;
3.in(查询包含某一类的)
说明:判断某字段的值是否属于in列表中的某一项;
特点:
①使用in可以提高语句的简洁度;
②in列表的值类型必须一致或者兼容;
③in列表不能使用通配符;案例1:查询员工的工种编号是IT_PROG、AD_VP、AD_PRES中的一个员工名和工种编号;
select 查询员工名列表,查询工种编号列表 from 员工表 where 工种编号列表
in('IT_PROG','AD_VP','AD_PRES');
4.is null(判断是否为null值)
注意:=或者<>不能用于判断null值;
用于:is null 或者 is not null 用于判断null值,可读性较高;
补充:isnull函数,用于:判断某字段或表达式是否为null,是返回1,否返回0;
5.安全等于 :<=>
说明:可读性较小,既可以判断null值,也可以判断普通数值;
3.排序查询
语法:select 查询列表
from 表
[where 筛选条件]
order by 排序列表 asc(升序)|desc(降序);
特点:
1. 如果不写默认是升序;
2. order by 子句中可以支持单个字段,多个字段,表达式,别名,函数进行排序
3.order BY 子句一般放在查询语句的最后面,进行查询最后的排序。(limit子句除外)
7.关于group by和having的区别
having:
在满足where以及group by之后查询的结果集中,进行过滤(帅选)声明;having后面可以使用聚合函数
group by后面 使用分组字段或者表达式--->后面不能使用聚合函数,where必须放在group by之前
where...group by...having...
数据库约束
约束用户操作数据库的一种行为(非法行为)
常见的六大数据库约束:
1.主键约束(primary key)
特点:主键修饰的字段,非空且唯一,一张表中只能有一个主键
添加主键的语法:
方式1:
CREATE TABLE student(
NAME VARCHAR(10) PRIMARY KEY,
age INT
);
方式2:
CREATE TABLE student(
NAME VARCHAR(10),
age INT,
PRIMARY KEY(NAME)
);
2.非空约束:not null
使用方法跟主键一样,用not null约束的字段不能为null值,必须给定具体的数据
3.自增长约束:auto_increment
使用方法跟主键一样。如果是整数型字段,添加自增长约束后,还需要配合主键约束一起使用。
CREATE TABLE student(
sid INT AUTO_INCREMENT PRIMARY KEY,
NAME VARCHAR(20),
)
4.非负约束:unsigned
使用方法跟主键一样;添加非负约束后,取值范围将发生变化,例如int范围是-128~127,添加非负约束后将变成0-255
5.唯一约束:unique
不允许重复,使用方法跟主键一样,限定不了空值,要想限定,还要添加非空约束
CREATE TABLE student(
NAME VARCHAR(20) UNIQUE NOT NULL,
age INT UNIQUE NOT NULL
)
6.外键约束:alter table
多表名称 add foreign key(外键名称) references 一表名称(主键);其中,多表指关系中的多方,一表指关系中的一方,外键名称自定义,一般为一表名称_id,主要用于多表之间联系。添加外键约束后,主表不能删除从表中已引用的数据,从表不能添加主表中不存在的数据。
添加外键约束后,如何删除主表中的数据:
方式1:级联删除:ALTER TABLE orders ADD FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE;
方式二: 先删除多表中的数据,再删除主表中的数据
数据库的三大范式
表和表的关系问题
一对多
用户和订单的关系
一个用户可以有多个订单,
某个订单从属于某个用户
员工和部门的关系
一个部门有多个员工
一个员工属于某个部门的多对多
订单表和商品表
一个订单包含多个商品
一个商品被多个订单包含
学生表和选课表
一个学生可以选多个课程
一个课程被多个学生选择
-- 一对一是一种特例
人和身份证
一个人对应一个身份证
一个身份证从属于某个人的
人和电话...
-- 多表关系---设计一个库,满足数据库的范式(就是数据库设计的一种规范要求)
1NF:第一范式数据库表中每一列是不能在拆分的原子性!(最基本的要求)
(表中每一个列是单独的,不能在拆分)
2NF:第二范式
在满足1NF基础上,
1)一张描述一件事情
2)非主键字段必须完全依赖于主键字段
3NF:第三范式
在满足2NF基础上
非主键字段中间不能产生传递依赖
A字段--->依赖B字段--->依赖于C字段 A字段--->依赖C字段
学生表
学生id 学生的姓名 学生其他信息 学院id 学生所在的学院 系主
学生表和选课
多表查询 笛卡尔乘积
内连接
隐式内连接:where条件---多去使用这种查!
select
字段列表
from
表名1,表名2...表名n
where
这些表之间的连接条件;显示内连接 (inner可以省略) join
select
字段列表
from 表名1
(inner) join
表名2
on 连接条件
外连接
左外连接(通用)
-- 将A表(左表)的和B表(右表)的交集以及A表(左表)中所有数据全部查询!
select
字段列表
from
左表名
left (outer) join -- outer可以省略
-- righter (outer) join 可以右外连接
表名2
on
连接条件;
子查询:select 嵌套 select....
情况1 单行单例的数据
情况2 多行多列
情况3: 通过两个表的关系---查询出结果集---->当做"虚表"在和其他之间关联查询!
数据库的事务
1. 什么是数据库事务(Transaction)
在一个业务中执行多个sql(多张表的sql),这多个sql句要么同时执行成功,
要么同时执行失败!
3. 事务特点 ACID (关系型数据库传统事务)
原子性,一致性,隔离性,持久性!
原子性:在使用事务管理的时候,执行多个sql增删改,要么同时执行成功,要么同时失败
一致性:高并发的时候,需要保证事务多次读写,保证数据一致性!
隔离性事务和事务是独立的,相互不影响!
举例
购物车业务--->购物车表和购物车项表同时添加数据
订单业务---->订单表和订单项表同时添加数据
持久性:事务一旦提交,对数据的影响是永久性,即使关机了,数据还是要更新的!
3. 事务的隔离级别
四个级别:从小到大,安全性---从低到高,效率性:从高到低!
read uncommitted :读未提交
read committed :读已提交
repeatable read :可重复读 (mysql的默认隔离级别)
serializable : 串行话
SELECT @@tx_isolation; -- 查看隔离级别:5.7以及5.7以前
select trasaction_isolation; mysql8.0以后的查看事务的隔离级别
4.设置隔离级别
set global transaction isoloation level 级别的名称;
第一种级别read uncommitted:
读未提交 会造成问题"脏读" "脏读":是事务管理最严重的问题:一个事务读取到另一个没有提交的事务!
第二种级别:read committed;读已提交 有效防止脏读,出现了一个问题"不可重复读" 事务(当前本身这个事务提交)多次读取另一个提交事务的前后到的数据不一致!
mysql的默认级别 repeatable read
可重复读,有效脏读,不可重复读,出现幻读!(一般有更新操作影响了数据)
最高级别:serializable:串行话 (一个事务读取到另一个没提交事务,数据查不到的,这个必须提交,才能操作数据!)