package StartWeb;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
import java.util.Properties;
/**
* @author 耿世伟
* @version 1.0
* 软件通俗讲 数据+程序
*
* 1. 系统软件--驱动程序 C/C++
*
* 2. C/S 架构软件 client客户端 server服务端 LOL
* C/C++ C# QT等
*
* 3. B/S 架构软件 拼多多
* 前端 html css js 等
* 后端 java 等
*
* 4. 移动端 Android安卓/苹果 小程序
*
* 5. win10商店 UWP C#
*/
/*public class Web01 {
// javaWeb 语言完成服务器端程序开发
// 黑盒测试:不需要写代码,给输入值,看程序是否达到预期的值
// 白盒测试 需要写 代码,关注程序具体的执行流程
@Before//用于资源申请
public void start(){
System.out.println("@Before在测试方法之前执行");
}
@Test
public void testAdd(){
int number1=5;
int number2=5;
int result=number1+number2;
//断言 第一个预测值 第二个程序结果值
assert(10==result);
System.out.println("我被执行了");
}
@After//释放资源方法
public void close(){
System.out.println("@After在测试方法后执行");
}
}*/
/* Java代码在计算机中的三个阶段
源代码阶段 .class Class.forName("全类名")
通过类加载器(Classloader) 到 Class对象阶段 类名.class
将成员变量封装到 Filed[] fields
构造方法 Constructor[] cons
成员方法 Method[] methods
创建对象--->Runtime运行阶段 对象 .getClass()
new person...等等
##反射: 框架设计的灵魂
框架:半成品软件 可以在框架的基础上进行软件开发,简化代码
反射:将类的各个组成部分封装为其他对象,这就是反射机制 好处:可以在程序中运行,可以解耦,提高程序扩展性
获取class对象的方式
Class.forName("全类名") 将字节码文件加载到内存,返回Class对象
多用于配置文件 将类名定义在配置文件中 读取文件加载类
类名.class 通过类名的属性class获取
多用于参数的传递
对象 .getClass() getClass方法在object中
多用于对象的获取字节码形式
*/
/*public class Web01 {
public static void main(String[] args) throws Exception {
// 1. Class.forName("全类名") 将字节码文件加载到内存,返回Class对象
Class> cls1 = Class.forName("StartWeb.Person");
System.out.println(cls1);
//2. 类名.class 通过类名的属性class获取
Class cls2 = Person.class;
System.out.println(cls2);
// 3. 对象 .getClass() getClass方法在object中
Person person = new Person();
Class extends Person> cls3 = person.getClass();
System.out.println(cls3);
//比较三个对象
System.out.println(cls1==cls2);//true
System.out.println(cls1==cls3);//true
//同一字节码文件(*.class)在程序运行过程中,只会加载一次,不论通过哪一种方式获取class对象都是同一个
}
}*/
/*public class Web01 {
public static void main(String[] args) throws Exception {
// 0. 获取Person的class对象
Class personClass = Person.class;
//1. getFields() 获取所有public修饰的成员变量
Field[] fields = personClass.getFields();
for (Field field :fields) {
System.out.println(field);
}
System.out.println("-------------");
//指定名称的public修饰的成员变量
Field name = personClass.getField("name");
//获取成员变量a的值
Person person = new Person();
Object value=name.get(person);
System.out.println(value);
//设置name的值
name.set(person,"小飞棍来喽");
System.out.println(person);
System.out.println("-------------");
// getDeclaredFields 获取所有的成员变量 不考虑修饰符
Field[] declaredFields = personClass.getDeclaredFields();
for (Field df :declaredFields) {
System.out.println(df);
}
Field price = personClass.getDeclaredField("price");
// 忽略访问修饰符的安全检查
price.setAccessible(true);//暴力反射
Object o = price.get(person);
System.out.println(o);
System.out.println("-------------");
Constructor constructor = personClass.getConstructor(String.class);
System.out.println(constructor);
//创建对象
Object xlh = constructor.newInstance("东北小老虎");
System.out.println(xlh);
System.out.println("-------------");
Constructor constructor1 = personClass.getConstructor();
System.out.println(constructor1);
//创建对象
Object o1 = constructor1.newInstance();
System.out.println(o1);
//指定指定名称的方法
Method play = personClass.getMethod("play");
Person person1 = new Person();
//执行方法
play.invoke(person1);
Method play1 = personClass.getMethod("play", String.class);
play1.invoke(person1,"余淮");
System.out.println("-------------");
//获取所有public修饰的方法
Method[] methods = personClass.getMethods();
for (Method method :methods) {
System.out.println(method);
}
//获取类名
String name1 = personClass.getName();
System.out.println(name1);
}
}*/
/*注解不是程序的一部分 而是一个标签
注解 : JDK1.5之后出现的新属性 说明解释程序的 注解形式 @注解名称
JDK预定义的一些注解 @override是否重写 @Deprecated已过时 @SuppressWarnings抑制警告
自定义注解格式 元注解
public @interface 注解名称("all")
注解本质是一个接口
属性:接口可以定义的成员方法(抽象方法) 要求:属性的返回类型 基本数据类型,String,枚举,注解,以上类型数组
@Target注解所能作用的位置
ElementType.ANNOTATION_TYPE, 可以用于类上
ElementType.METHOD, 可以作用于方法上
ElementType.FIELD 可以作用于成员变量上
@Retention描述注解被保留的阶段
@Retention(RetentionPolicy.RUNTIME)当前被描述的注解 会保留的class字节码文件中 并被JVM所读取
@Documented 描述注解是否抽取到api文档中
@Inherited 描述注解是否被子类继承
*/
/* @SuppressWarnings("all")
public class Web01 extends Person{
@Override
public void play(){
}
@Deprecated
public void eat(){
}
@ZhuShi(one=2,value=10,st2={"eee","aaaa"},zhushi = @zhuShi,number=Numbers.number1)
public void say(){
}
@Check
public void add(){//加法
System.out.println("1+0="+(1+0));
}
@Check
public void sub(){//减法
System.out.println("1+0="+(1-0));
}
@Check
public void mul(){//乘法
System.out.println("1+0="+(1*0));
}
@Check
public void div(){//除法
System.out.println("1+0="+(1/0));
}
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface Check{
}
class TestCheck{
public static void main(String[] args) throws Exception {
Web01 web01 = new Web01();//创建对象
Class cls=web01.getClass();//获取字节码文件对象
Method[] methods = cls.getMethods();//获取所有方法
int number=0;//出现异常次数
BufferedWriter bufferedWriter=new BufferedWriter(new FileWriter("bug.txt"));
for(Method method:methods){
//判断方法上是否有check
if(method.isAnnotationPresent(Check.class)){
try {
method.invoke(web01);
} catch (Exception e) {
number++;
bufferedWriter.write(method.getName()+"方法出现异常了");
bufferedWriter.newLine();
bufferedWriter.write("异常名称"+e.getCause().getClass().getSimpleName());
bufferedWriter.newLine();
bufferedWriter.write("异常原因"+e.getCause().getMessage());
bufferedWriter.newLine();
bufferedWriter.write("----------");
bufferedWriter.newLine();
}
}
}
bufferedWriter.write("本次测试一共出现"+number+"异常");
bufferedWriter.flush();
bufferedWriter.close();
}
}*/
/*
数据库(用于管理和存储数据的仓库) 英文单词 DataBase 简称 DB 其实数据库就是一个文件系统
MySQL服务启动 cmd->services.msc 打开服务
cmd-> net stop mysql 停止mysql / net start mysql启动mysql
MySQL登录 mysql -uroot -p密码
mysql -h(他人ip地址) -uroot -p密码 连接他人的数据库
mysql --host=ip --user=root --password=密码
MySQL退出 exit / quit
MySQL数据目录 数据库(文件夹) 表(文件)
SQl就是定义了操作所有关系型数据库的规则。每一种数据库操作方式存在不一样的地方,称为‘方言’
MySQL数据库SQL语句不区分大小写,建议使用大写
3种注释
-- 注释内容 或 #注释内容(mysql特有)
多行注释 反斜杠* *反斜杠 /
SQL分类 DDL(操作数据库和表) DQL(查询表中数据) DML(增删改表中数据) DCL(客户端授权)
DDL操作数据库和表(CRUD)
1.操作数据库
C创建:
create database 数据库名称----创建数据库
create database if not exists 数据库名称----创建数据库,判断不存在再创建
create database 数据库名称 character set 字符集名---创建数据库,并指定字符集
R查询:
show databases---查询所有数据库名称
show create database 数据库名称---查询某个数据库
U修改:
alter database 数据库名称 character set 字符集名称---修改数据库字符集
D删除
drop database 数据库名称---删除数据库
drop database if exists 数据库名称---判断数据库存在,存在再删除
使用数据库
select database()---查询当前正在使用的数据库名称
use 数据库名称---使用数据库
2.操作表
C创建
create table 表名(列名1 数据类型1,
列名2,数据类型2
...
列名n,数据类型n);
数据库类型:int , double , date日期(只包含年月日yyyy-MM-dd)
datetime日期(只包含年月日时分秒yyyy-MM-dd HH:mm:ss)
timestamp时间戳类型(包含年月日时分秒yyyy-MM-dd HH:mm:ss)如果不给这个字段赋值,或赋空值,则默认使用当前的系统时间
varchar字符串
R查询
show tables---查询某个数据库所有表
desc 表名---查询表结构
U修改
alter table 表名 rename to 新的表名---修改表名
alter table 表名 character set 字符集名称---修改表的字符集
alter table 表名 add 列名 数据类型---添加一列
alter table 表名 change 列名 新列别 新数据类型---修改列名称 类型
alter table 表名 modify 列名 新数据类型---修改列名称 类型
alter table 表名 drop 列名---删除列
D删除
drop table 表名
drop table if exists 表名
客户端图形化工具 SQLYog / Navicat
DML增删改表中数据
添加数据 insert into 表名(列名1,列名2,...列名n,) values (值1,值2,...值n) 如果表名后不定义列名,则默认给所有列添加值
除了数字类型,其他类型需要使用单引号(单双都可以)引起来
删除数据 delete from 表名[where 条件]
如果不加条件,则删除表中所有记录
truncate table 表名---推荐使用,效率更高,先删除表,然后再创建一张一样的表
修改数据 update 表名 set 列名1=值1,列名2=值2,...[where条件]
如果不加任何条件,则会将表中所有记录全部修改
DQL查询表的记录
select * from 表名
基础查询 1.多个字段查询 select 字段名1,字段名2...from 表名 如果查询所有字段,则用*来替代字段列表
2.去除重复 distinct
3. null参与运算则计算结果为null ifnull(表达式1,表达式2)表达式1为null,则返回表达式2的值
4. as起别名 as也可以省略
条件查询 1.where子句后跟条件
2. 运算符 between...and in(集合) like模糊查询 _单个任意字符 , %任意多个字符
%耿% 包含姓名中包含耿的人 is null and或&& or或|| not或!
DQL查询语句
1.排序查询 order by 排序字段1 排序方式1 , 排序字段2 排序方式2... ASC升序默认的 DESC降序
如果有多个排序条件,则当前边的条件值一样时,才会判断第二条件
select count(isnull(englis,0)) from student;
2.聚合函数 将一列的数据作为一个整体,进行纵向的计算
count 计算个数 一般选择非空的列:主键 count(*)
max 计算最大值
min 计算最小值
sum 计算和
avg 计算平均数
聚合函数的计算,排除null值 解决方法ifnull函数
3.分组查询 group by 分组字段
分组之后查询的字段:分组字段,聚合字段
where和having的区别:where在分组之前进行限定,如果不满足这条件,不进行分组;having在分组之后进行限定,如果不满足条件,则不会被查询出来
where后面不可以跟聚合函数,having可以进行聚合函数的判断
4.分页查询 limit 开始的索引,每页查询的条数
公式: (当前的页数 - 1 ) * 每页查询的条数 limit是一个MySQL方言
约束:对表中的数据进行限定,保证数据的正确性,有效性和完整性
1.非空约束 not null
创建表时添加约束 / 创建表后添加约束 alter table student modify name varchar(20) not null;
删除name的非空约束 alter table student modify name varchar(20);
2.唯一约束 unique某一列的值不能重复 唯一约束可以有null值,但是只有一条记录为null
创建表时添加唯一约束 / 创建表后添加约束 alter table student modify name varchar(20) unique;
删除唯一约束 alter table student drop index name
3.主键约束 primary key 非空且唯一/一张表只能有一个字段为主键/主键就是表中记录的唯一标识
在创建表时添加约束 / 创建表后添加约束 alter table student modify id int primary key;
删除主键 alter table student drop primary key;
添加自动增长 alter table student modify id int auto_increment;
添加自动增长 alter table student modify id int;
4.外键约束 foreign key 让表产生关系 从而保证数据的正确性
在创建时,添加外键 creat table表名(
...
外键列
constraint 外键名称 foreign key(外键列名称) references 主表名称(主列表名称))
创建表后,添加外键 alter table 表名 add constraint 外键名称 foreign key(外键列名称) references 主表名称(主列表名称)
删除外键 alter table 表名 drop foreign key 外键名称
5.级联操作
语法 alter table 表名 add constraint 外键名称 foreign key(外键列名称) references 主表名称(主列表名称) on update cascade on delete cascade
级联更新: on update cascade 级联删除: on delete cascade
数据库的设计:
一对一(一个人只有一个身份证,一个身份证只能对应一个人) 实现方式:需要借助第三张表 中间至少包含两个字段,这两个字段作为第三张的外键,分别只想两张表的主键
一对多(一个部门有多个员工,一个员工只能有一个部门) 实现方式:可以在任何一方添加唯一的外键指向另一方的主键
多对多(一个学生可以选择多门课程,一个课程也有多个学生) 实现方式:在多的一方建立外键,指向一对一的主键
数据库设计的范式:
第一式范(1NF) 每一列都是不可分割的原子数据项
第二式范(1NF) 在1NF的基础上,非码属性必须完全依赖于码(消除非主属性对主码的部分函数依赖)
函数依赖 如果通过A属性的值,可以确定唯一的B属性,则称B依赖于A 学号--->姓名
完全函数依赖 如果A是一个属性组,则B属性值得确定需要依赖A属性组的中所有的属性值 学号,课程名称--->分数
部分函数依赖 如果A是一个属性组,则B属性值得确定需要依赖A属性组的中某一些的属性值 学号,课程名称--->姓名
传递函数依赖 A->B B->A 如果通过A属性的值,可以确定唯一B属性的值,在通过B属性的值可以确定唯一C属性的值,则称C传递函数依赖于A
码:如果在一张表中,一个属性或属性组,被其他所有属性所完全依赖,则称这个属性(属性组)为该表的码
主属性 码属性组中的所有属性 非主属性:除码属性组的属性
第三式范(1NF) 在2NF基础上,消除了传递依赖
数据库的备份和还原
备份: mysqldump -u用户名 -p密码 数据库名称 > 保存的路径
还原: 登录数据库
创建数据库
使用数据库 use
执行文件 source 文件路径
笛卡尔积:有两个集合AB,取这两个集合的所有组成情况(A*B) 要完成多表查询,需要取消无用数据
多表查询的分类:
内连接查询 隐式内连接:使用where条件消除无用数据 显示内连接: select 字段列表 from 表名1 [inner] join 表名2 on 条件
外连接查询 左外连接 select 字段列表 from 表1 left [outer] join 表2 on 条件 查询的是左表所有数据以及其交集部分
右外连接 select 字段列表 from 表一 right [outer] join 表2 on 条件 查询的是右表所有数据以及其交集部分
子查询 查询中嵌套查询,称嵌套查询为子查询
子查询的结果是单行单列的:子查询可以作为条件,使用运算符去判断 > >= < <= =
子查询的结果是多行单列的:子查询可以作为条件,使用运算符in来判断
子查询的结果是多行多列的:子查询可以作为一张虚拟表
事务的基本介绍 如果一个多个步骤的业务操作,被事务管理,那么这些操作要么同时成功,要么同时生效
操作 开启事务 start transaction 回滚 rollback 提交commit
mysql数据库中事务默认自动提交(一条dml增删改语句会自动提交一次事务) 手动提交Oracle数据库默认是手动提交事务 需要先开启事务,再提交
查看事务的默认提交方式 select @@autocommit; ---1 代表自动提交 ---- 0 代表手动提交
修改默认提交方式 set @@autocommit = 0
事务的四大特征: 原子性(是不可分割的最小操作单位,要么同时成功,要么同时失败);持久性(当事务提交或回滚后,数据会持久化保存数据)
隔离性(多个事务之间,相互独立); 一致性(事务操作后,数据总量不变)
事务的隔离级别 多个事务之间隔离的,相互独立的.但是如果多个事务操作同一批数据,则会引发一些问题,设置不同的隔离级别就可以解决这些问题
存在问题 脏读:一个事务,读取到另有一个事务没有提交的数据 不可重复读:在同一事物中,两次读取的数据不一样 幻读:一个事务操作dml数据表中所有记录,另一个事务添加了一条数据,则第一个事务查询不到自己的修改
1.read uncommitted 读未提交 产生的问题 :脏读,不可重复读,幻读
2.read committed(Oracle默认) 读已提交 产生的问题:不可重复读,幻读
3.repeatable read(MySQl默认) 可重复读 产生问题:幻读
4.serializable 串行化 可以解决所有问题
隔离级别从小到大安全性越来越高,但是效率越来越低
数据库查询隔离级别 select @@tx_isolation
数据库设置隔离级别 set global transaction isolation level 级别字符串
DCL:管理用户,授权 DBA(数据库管理员)
添加用户: create user '用户名'@'主机名' identified by '密码';
删除用户: drop user '用户名'@'主机名'
修改用户密码: update user set password = password('新密码') where user = '用户名'
set password for '用户名'@'主机名'= password('新密码')
mysql中忘记root用户和密码
1. cmd->net stop mysql 停止mysql服务 需要管理员运行cmd
2. 使用无验证方式启动mysql服务: mysqld --skip-grant-tables
3. 打开新的cmd窗口,直接输入mysql命令,敲回车。就可以登陆成功
4. use mysql; update user set password =password('你的新密码')where user ='root'
5. 关闭两个窗口
6. 打开任务管理器,手动结束mysqld.exe进程
7.启动mysql服务
8.使用新密码登录
查询用户
切换到mysql数据库 use mysql 查询user表 select *from user 速配符: % 表示可以在任意主机使用用户登录数据库
权限管理 查询权限 show grants for '用户名'@'主机名' 授予权限 grant 权限列表 on 数据库名.表名 to '用户名'@'主机名'
撤销权限 revoke 权限列表 on 数据库名.表名 from '用户名'@'主机名'
*/
/*
JDBC java数据库的连接,java语言操作数据库 本质:其实是官方(sun公司)定义的一套操作所有关系型数据库的规则,即接口
各个数据库厂商实现这套接口,提供数据库驱动jar包
*/
/*public class Web01 {
public static void main(String[] args) throws Exception {
//1.导入驱动jar包
//2.注册驱动
Class> aClass = Class.forName("com.mysql.jdbc.Driver");
//3.获取数据库连接对象
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/db3", "root", "123456");
//4.定义sql语句
String sql="update account set number = 10 where id=1";
//获取执行sql对象 Statement
Statement statement = connection.createStatement();
//执行sql
int count=statement.executeUpdate(sql);
//处理结果
System.out.println(count);
//释放资源
statement.close();
connection.close();
}
}*/