Day27

1.UDP发送端可以不断键盘录入数据,接收端不断展示数据,发送端
可以自定义结束条件

发送端

public class UdpSend {public static void main(String[] args) {//UDP发送端可以不断键盘录入数据//创建发送端的socketDatagramSocket ds = null ;try {ds = new DatagramSocket() ;//键盘录入可以使用BufferedReader--->读一行BufferedReader br = new BufferedReader(new InputStreamReader(System.in)) ;String line = null ;//一次读一行内容System.out.println("请您输一个数据");while((line=br.readLine())!=null){if("over".equals(line)){break;}//创建数据报包,将数据存储在数据包中DatagramPacket dp = new DatagramPacket(line.getBytes(),line.getBytes().length,InetAddress.getByName("10.35.162.121"),6666) ;//发送数据报包ds.send(dp) ;}} catch (IOException e) {e.printStackTrace();}finally {if(ds!=null){ds.close() ;}}}
}

接收端

package com.qf.udp_test_01;import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;/*** @author 高圆圆* @date 2022/11/28 10:09* 接收端不断展示数据------->接收端模拟真实,不需要关闭*/
public class UdpReceive {public static void main(String[] args) {try {//创建接收端的Socket对象DatagramSocket ds = new DatagramSocket(6666) ;while(true){//创建一个接收容器//自定义一个字节数组缓冲区byte[] buffer = new byte[1024] ;int bufferLength =  buffer.length ;DatagramPacket dp = new DatagramPacket(buffer,bufferLength) ;//接收数据容器ds.receive(dp) ;//解析接收容器中真实内容byte[] bytes = dp.getData();int length = dp.getLength();//每次0开始读取字节数---转成StringString receiveMsg = new String(bytes,0,length) ;//获取ip地址字符串String ip = dp.getAddress().getHostAddress() ;//展示数据System.out.println("data from-->"+ip+",conent is :"+receiveMsg);}} catch (IOException e) {e.printStackTrace();}}
}

2.TCP客户端和服务器端的代码实现

客户端

public class TcpClientDemo {public static void main(String[] args) throws IOException {//1)创建客户端的Socket对象,指定ip和端口//Socket(String host, int port)Socket socket = new Socket("10.35.162.121",1888) ;//2)获取客户端通道内容字节输出流对象,写数据//public OutputStream getOutputStream()OutputStream outputStream = socket.getOutputStream();outputStream.write("hello,TCP我来了".getBytes());//客户端获取通道字节输入流对象,读服务器端的反馈的数据InputStream in = socket.getInputStream();byte[] bytes = new byte[1024] ;int length = in.read(bytes);String fkMsg = new String(bytes,0,length) ;System.out.println(fkMsg);//3)释放资源outputStream.close();}
}

服务端

public class TcpServerDemo {public static void main(String[] args) throws IOException {//1)创建服务器端的Socket对象//public ServerSocket(int port)ServerSocket ss = new ServerSocket(1888) ;System.out.println("服务器正在等待客户端连接请求...");//2)监听客户端的连接// public Socket accept()throws IOExceptionSocket socket = ss.accept();//阻塞式方法,没有客户端连接,一直等待System.out.println("客户端已连接");//3)获取监听到的客户端的通道内的字节输入流对象,读数据//public InputStream getInputStream()InputStream inputStream = socket.getInputStream();//一次读取一个字节数组byte[] bytes = new byte[1024] ;int length = inputStream.read(bytes);//转换成StringString receiveMsg =  new String(bytes,0,length) ;//获取ip地址对象,同时ip地址字符串形式// public InetAddress getInetAddress()String ip = socket.getInetAddress().getHostAddress();System.out.println("data from --->"+ip+",content is-->"+receiveMsg);//服务器端反馈给客户端数据//服务器端可以获取监听客户端通道内字节输出流,写数据OutputStream out = socket.getOutputStream();out.write("我这边已经收到数据!".getBytes());//        * 4)释放服务器端的资源ss.close();}
}

3.TCP的应用

3.1 TCP方式,客户端可以不断键盘录入数据,服务器端不断展示数据

public class TcpClient {public static void main(String[] args) throws IOException {//1)创建客户端SocketSocket socket  = new Socket("10.35.162.121",8888) ;//2)可以创建BufferedReader 一次读取一行,录入数据BufferedReader br=  new BufferedReader(new InputStreamReader(System.in)) ;//获取通道字节输出流对象,写数据--->字节输出流---->包装字符流OutputStream out = socket.getOutputStream();//可以使用字符流把上面的通道内的字节数出流包装BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(out)) ;String line = null ;while((line=br.readLine())!=null){/*if("886".equals(line)){break;}*///录入一行,给封装到通过的字符流写一行进去bw.write(line) ;bw.newLine();bw.flush();}socket.close();}
}
public class TcpServer {public static void main(String[] args) throws IOException {//创建服务器端的SocketServerSocket ss = new ServerSocket(8888) ;System.out.println("服务器正在等待连接");// int i= 0 ;while (true){//监听多个客户端了解//   i++;//监听客户端连接Socket socket = ss.accept();//  System.out.println("第"+i+"个客户端已连接");//获取监听客户端所在的通道内的字节输入流InputStream in = socket.getInputStream();//将桶内的字节输入流封装成字符流读BufferedReader br = new BufferedReader(new InputStreamReader(in)) ;//一次读取一行String line = null ;while((line=br.readLine())!=null){if("886".equals(line)){break;}System.out.println(line) ;//展示数据}}//模拟真实场景,服务器端不关}
}

3.2 TCP客户端的读取文本文件(将文本文件写入通道中),服务器端复制文本文件到指定路径中(将文本文件写入指定文件中)

public class TcpClientTest {public static void main(String[] args) throws IOException {//创建客户端的Socket对象Socket s = new Socket("10.35.162.121",2222) ;//创建字符缓冲输入流对象BufferedReader br = new BufferedReader(new FileReader("UdpReceive.java")) ;//获取客户端通道的字节输出流---->包装成BufferedWriter:字符缓冲输出流BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream())) ;//每次从.java文件读取一行,给通道流的流中写一行String line = null ;while((line=br.readLine())!=null){bw.write(line) ;bw.newLine();bw.flush();}System.out.println("文件读完,发送过去了...");//释放资源br.close();s.close();}
}
public class TcpServerTest {public static void main(String[] args) throws IOException {//创建服务器端的Socket对象ServerSocket ss = new ServerSocket(2222) ;//监听客户端连接Socket s = ss.accept();//获取监听客户端所在的通道内字节输入流对象---->包装成字符缓冲输入流BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream())) ;//将监听客户端的通道内的字节流(已经被包装了字符缓冲输入流)的内容----通过的字符缓冲输出流写入到文件中BufferedWriter bw = new BufferedWriter(new FileWriter("D:\\EE_2211\\day27_code_resource\\copy.java")) ;//一次读取一行,写一行到文件中String line = null ;while((line=br.readLine())!=null){bw.write(line);bw.newLine();bw.flush();}System.out.println("复制完毕");//释放资源bw.close();ss.close();}
}

4. 反射获取构造器并创建当前类实例

什么是反射?
       编译某个类的时候---->获取这个类的字节码文件,然后去加载,调用里面的成员方法,访问成员变量,
       通过构造方法创建对象!
 
  编译过程:
       对这个类的属性/成员/构造其进行校验---->类加载器(负责类的加载过程)
               BoostrapClassLoader:启动类加载器,负责java核心库,rt.jar
 
  如何获取一个类的字节码文件?
  java.lang.Class:代表正在运行的java类或者接口,通过静态方法
  public static Class forName(String classname):
  参数:代表就是当前类或者接口的全限定名称 (包名.类名)
  String---->全限定名称 java.lang.String
  Person---->自定义的---->全限定名称:com.qf.reflect_06.Perso
  通过反射方式获取类的字节码文件之后,创建当前类对象!
 
  之前的写法:考虑运行的代码 类名 对象名  = new 类名() ;
 
  1)获取类的字节码文件对象
  2)获取类的Constructor所在的构造器对象
  3)通过它创建当前类实例

反射获取成员方法并调用

public class ReflectDemo4 {public static void main(String[] args) throws Exception {//之前的写法// Person p = new Person();//p.show() ;System.out.println("----------------------------------");//反射的写法//1)获取类的字节码文件对象Class clazz = Class.forName("com.qf.reflect_06.Person") ;//2)通过无参构造器创建器Constructor创建当前类实例//如果你这个类没有提供任何构造方法(系统提供无参)或者无参构造方法是公共的---->此时可以直接使用Class类的newInstacne()创建当前类实例//等价于下面这个写法Object obj = clazz.newInstance();System.out.println(obj);//System.out.println(obj);/*Constructor con = clazz.getConstructor();Object obj = con.newInstance() ;*/// System.out.println(obj);// Method getMethods() ;//获取本类中所有的成员的method// Method getDeclaredMethods() ;//获取本类中所有的成员的method以及父类的Object//3)获取指定的成员方法所在的Method类对象// public Method getDeclaredMethod(String name, Class<?>... parameterTypes)获取指定的成员方的method类对象// public Method getMethod(String name, Class<?>... parameterTypes):获取指定的公共的成员方法的Method对象//第一个参数都是方法名//第二个参数是可变参数,方法的形式参数类型的Class(字节码文件对象)Method method = clazz.getMethod("show");//方法本身就是空参System.out.println(method);//调用方法,Method类---提供的invoke//public Object invoke(Object obj, Object... args)//第一个参数:当前类实例//第二个参数:给方法的形式参数赋的实际参数//调用方法到时候将指定的方法实际参数作用在当前类实例上method.invoke(obj) ; //本身这个方法没有返回值,单独调用System.out.println("----------------------------------------------------------");/*** 反射调用这个* private void method(String str){*         System.out.println(str);*     }*/Method m1 = clazz.getDeclaredMethod("method", String.class);// System.out.println(m1);//private void com.qf.reflect_06.Person.method(java.lang.String)//私有方法取消Java语言检查m1.setAccessible(true) ;m1.invoke(obj,"hello,高圆圆") ;}
}

Day28

1 单例设计模式

单例设计模式:
      始终在内存中始终只有一个对象!
 
  饿汉式和懒汉式
 
  饿汉式: 单例设计模式中最安全的一种设计模式!(不会出现线程安全问题!)
 
  jdk提供了一个Runtime:是和计算机运行环境相关的类(典型的单例设计模式)
  public class Runtime {
      private static Runtime currentRuntime = new Runtime();
 
 public static Runtime getRuntime(){
  return currentRuntime;
  }

private Runtime(){}

}
       1)在类的成员位置提供静态实例变量
       2)当前类一定是具体类,构造方法私有化
       3)对外提供公共的静态方法,返回这个实例!(返回值就是当期类本身)

public class SinglePatternDemo {public static void main(String[] args) throws IOException {//创建学生对象//Student s1 = new Student() ;//Student s2 = new Student() ;//System.out.println(s1==s2) ;//上面---外界类中直接创建对象!每次都可以new,不合适!// Student.s = null ;//让对象变成null,外界还依然可以修改的实例!//不让你修改,此时这个静态实例变量---->加入私有Student s1 = Student.getStudent();Student s2 = Student.getStudent();System.out.println(s1==s2) ;System.out.println("-----------------------------------------------------") ;//创建和应用运行环境类对象Runtime runtime = Runtime.getRuntime();//成员方法:打开qq//runtime.exec("qq") ;// runtime.exec("mspaint") ;//打开画图板//runtime.exec("shutdown -t 3600 -s");//runtime.exec("shutdown -a");//public int availableProcessors() 获取处理器数量int i = runtime.availableProcessors();System.out.println(i);}
}

懒汉式是可能出现安全问题的一种单例模式
 
  特点:
   1)当前这个类构造方法私有化
   2)成员位置---提供了静态当前的类变量(此处只是声明了当前类型的一个变量)
   3)提供一个静态的成员方法,返回值是当前类本身,   (安全方法)
           场景:按需加载或者延迟加载,需要用的时候才去创建对象

public class SinglePatternDemo2 {public static void main(String[] args) {Teacher t1 = Teacher.getInstance();Teacher t2 = Teacher.getInstance();System.out.println(t1==t2);}
}

Day29

1 什么是数据库

数据库就是存储数据的一种仓库!
早期存储数据---->临时变量(局部变量)---->随着方法调用而存在,随着方法调用结束而消失
后面-------->成员变量(非静态) ----->随着方法对象的创建而存在,随着对象的创建完毕等待垃圾回收器回收而消失
容器---->数组---->长度固定(弊端)
--->StringBuffer用完毕等待回收
--->集合---->长度可变,它可以存储任意引用类型数据,使用完毕---->也要被回收掉
--->IO流---->永久存储,但是IO流的太耗时了
数据库存储数据--->
1)存储空间非常大,可以存储百万条,千万条甚至上亿条数据,用户可以对数据库中数据进行新增,查询,更新,删除等操作
2)数据独立性高
3)实现数据共享
4)减少数据的冗余度
5)通过数据库里面"事务"--->实现数据的一致性以及维护性!

2 市面上常见的数据库

数据库分为两大类:
关系型数据库--->MySQL,SqlServer,Oracle,SQLite,MariaDB(和mysql是同一个数据库引擎)
sqlServer,oracle:收费
Oracle-->中大型公司使用居多--->金融方面互联网公司oracle
Mysql--->免费产品----> 中小型公司使用居多
非关系型数据库--->Redis,Memcache,MongoDb,HBase
redis:后面讲(做数据缓存用的)

3 mysql基础语法

DDL语句:数据库定义语句
创建库,删除库,查询库,修改库字符集
创建表,删除表,查询表的结构,修改表相关的语法

DML语句:数据库操作语句
插入数据
删除表中的数据
修改的表的数据
查询表相关--------------语法很多(数据库玩的就查询)
基本查询
高级查询
使用图形界面化工具:sqlYog或者navicat

Day30

1.MySQL的DQL语句---->数据库查询语句(带条件查询分类)

-- mysql基本查询
-- 如果两个数据int类型字段求和的时候,如果某个字段是null,结果是null
--  mysql的ifnull(字段名称,预期值) 函数-- 需求:查询学生的姓名以及学生的总成绩
SELECT NAME '姓名',(math+english) '总成绩'
FROMstudent2;SELECT NAME '姓名',(math+IFNULL(english,0)) '总成绩'
FROMstudent2;   -- 需求:查询年龄是20或者年龄是18或者年龄是45的学生所有信息
-- where条件可以使用 or 或者java语言||,in(值1,值2.....)
SELECT *
FROMstudent2
WHERE age = 20 OR age = 18 OR age = 45 ;-- 另一种写法
SELECT *
FROMstudent2
WHERE age = 20 || age = 18 || age = 45 ;
-- 另一种写法:in(值1,值2.....)
SELECT *
FROMstudent2
WHERE age IN (20, 18, 45) ;-- 查询某个字段为null的信息---->is null
-- 查询字段不为null---->is not null
-- 需求:查询英语成是null的学生的所有信息
/*
select *
fromstudent2
where english = null;
*/
SELECT *
FROMstudent2
WHERE english IS NOT NULL ;-- 查询某个字段不等于某个值 ---使用!=或者mysql的 <>
-- 需求:查询年龄不是20岁的学生所有信息
SELECT *
FROMstudent2
WHERE age != 20 ;-- 另一种写法SELECT *
FROMstudent2
WHERE age <> 20 ;

模糊查询

-- 模糊查询mysql中所有的带有character字符集
SHOW VARIABLES LIKE '%character%' ;-- DQL之模糊条件查询  --- 关键字 like
-- 语法 select 字段列表 from 表名 where 字段名称 like '%xx%'
/*%:代表任意多个字符  (开发中使用居多)_:代表任意一个字符'字符%'  '%字符%'  也可以
*/
-- 需求:查询学生中所有姓马的学生信息SELECT
*
FROM
student2
WHERE
NAME LIKE '%马%'-- 查询学生的姓名是三个字符的人的信息
SELECT *
FROMstudent2
WHERE NAME LIKE '___' ;

聚合查询

-- DQL之聚合查询 --->结果是单行单例的
/*
COUNT(字段名称) ---->使用最多  统计表的记录
    count里面 字段名称:一般非业务字段 (id:一般主键字段)
    如果字段某个值是null,不会统计
    
max(列名称):求最大值
min(列名称):求最小值    
avg(列名称):求当前列的平均值
sum(列名称):求当前这列的总和

聚合查询

 -- 聚合函数---完成sql语句嵌套 (单表操作/多表都可以)-- x + y = 20 ; x = 5 --->代入-- 查询数学成绩大于数学平均分的学生信息!
-- 1)查询出数学成绩的平均分
-- select avg(math) from student2; -- 79.5000
-- 2)查询数学成绩大于79.5000的学生信息
/*
select *
fromstudent2
where math > 79.5000 ;
*/

排序查询

-- DQL语句之排序查询 order by
-- 单独使用order by
-- select 字段列表 from 表名  order by  字段名称 排序规则;
/*排序规则:默认asc ,升序排序desc  降序
如果有条件where,还有order by,where在前面满足条件,才排序!
*/
-- 插入一个学生
INSERT INTO student2 VALUES(9,'文章',35,'男','西安',73,98) ;
-- 针对某个字段排序
-- 需求:数学成绩升序排序
SELECT *
FROMstudent2
ORDER BY  math ASC ; -- asc可以省略不写
-- 需求:数学成绩大于70的学生按照降序排序
SELECT *
FROMstudent2
WHERE math > 70
ORDER BY math DESC ;
-- 同时多个条件排序
-- 需求:学生的数学成绩升序,英语成绩降序
SELECT *
FROMstudent2
ORDER BY math ASC,-- 先按照数学排english DESC ;

分组查询

-- DQL语句之分组查询 group by/*注意:1)分组查询里面可以select 查询分组字段 2)分组group by后面不能使用聚合函数*/-- 单独使用-- select 字段列表 from 表名 group by 分组字段名称;-- 需求:按照性别分组,查询数学成绩的平均分 (显示的查出分组字段)
SELECT sex '性别',AVG(math) '数学平均分'
FROMstudent2
GROUP BY sex ;-- 如果分组查询带where条件,
-- 需求:按照性别分组,查询数学成绩平均分,
-- 条件:学生数学成绩大于70的人参与分组
/*where条件和group by,where条件的在group by的前面group by的后面不能使用where,先满足where条件,才参与分组!
*/
/*
select sex '性别',avg(math) '数学平均分'
fromstudent2
group by sex
where math > 70 ;
*/
SELECT sex '性别',AVG(math) '数学平均分'
FROMstudent2
WHERE math > 70
GROUP BY sex ;

筛选

-- 筛选having
/*注意having的后面可以跟聚合函数,having在group by ,where是gruop by的前面;*/-- 需求:按照性别分组,查询数学成绩平均分,
-- 条件:学生数学成绩大于70的人参与分组,同时筛选出人数大于2的一组!
SELECT sex '性别',AVG(math) '数学平均分',COUNT(id) total
FROMstudent2
WHERE math > 70
GROUP BY sex
HAVING total  > 2 ;

分页查询

- 分页查询limit
-- select 字段列表 from 表名 limit 起始行数,每页显示的条数;
-- 起始行数= (当前页码数-1)*每页显示的条数;
-- 每页显示2条,
-- 查询第一页的数据
SELECT * FROM student2 LIMIT 0,2 ;
--  查询第二页的数据
SELECT * FROM student2 LIMIT 2,2 ;
-- 查询第三页的数据
SELECT * FROM student2 LIMIT 4,2 ;
-- 查询第四页的数据
SELECT * FROM student2 LIMIT 6,2 ; -- 查询第五页的数据
SELECT * FROM student2 LIMIT 8,2 ; -- select 字段列表 from 表名 limit 值;
SELECT * FROM student2 LIMIT 3 ;-- 如果复合查询:有where条件,还有limit,where在limit前面
SELECT * FROM student2 WHERE id > 2 LIMIT 4;-- 查询全表student2
SELECT * FROM student2;  

2.约束

-- 约束   
-- 约束用户操作数据库的一种行为(非法行为)
-- 默认约束 default
-- 非空约束 not null
-- 唯一约束 unqiue
-- 主键约束 primary key
-- 自增长约束 auto_increment
-- 外键约束 foreign key
-- 级联操作cascade

-- 默认约束default

-- 创建一张表
CREATE TABLE test1(id INT, -- 编号NAME VARCHAR(10), -- 姓名age INT, -- 年龄gender VARCHAR(3)  DEFAULT '女' -- 姓名) ;INSERT INTO test1 VALUES(1,'文章',35,'男'),(2,'高圆圆',30,'女') ;-- 插入部分字段INSERT INTO test1(id,NAME,age) VALUES(3,'张佳宁',29) ;-- 没有插入字段的值默认值null,为了防止这种数据出现,可以在创建表的时候-- 加入默认约束default,当没有插入这个字段,默认约束起作用!DROP TABLE test1;
-- 通过sql将默认约束删除
-- 修改表的字段类型
ALTER TABLE test1 MODIFY gender VARCHAR(3)
INSERT INTO test1(id,NAME,age) VALUES(4,'刘亦菲',27) ;
-- sql添加,默认约束
ALTER TABLE test1 MODIFY gender VARCHAR(3) DEFAULT '女' ;

-- 非空约束

-- 非空约束 not null
-- 当前这个值不能为null,不能直接添加数据给一个null
CREATE TABLE test1(id INT,NAME VARCHAR(10) NOT NULL -- 创建表的时候在指定字段后面加入not null
);
INSERT INTO test1 VALUES(1,'张三'),(2,'张三丰') ;
-- insert into test1 values(3,null) ; -- 某个字段值直接插入null值(非法行为)
-- Column 'name' cannot be null  当前这个值不能插入null值-- 将默认约束删除了
-- alter table 表名 modify 字段名称 数据类型;
ALTER TABLE test1 MODIFY NAME VARCHAR(10) ;
-- 添加非空约束
ALTER TABLE test1 MODIFY NAME VARCHAR(10) NOT NULL ;
INSERT INTO test1 VALUES(3,NULL) ;

唯一约束

-- 唯一约束 unqiue (当前这个值不能重复)
-- 限制id字段/有效身份信息(邮箱/手机号/身份证...)
CREATE TABLE test1(id INT ,NAME VARCHAR(10),telephone VARCHAR(11) UNIQUE -- 唯一约束:存在唯一索引inedex
) ;
INSERT INTO test1 VALUES(1,'高圆圆','13366668888'),(2,'王力宏','13322226666') ;
-- 添加手机号码重复
-- INSERT INTO test1 VALUES(3,'文章','13366668888'); -- 手机号重复,防止这些字段重复(有效身份信息,可以在创建表的时候添加唯一约束)
-- -- Duplicate entry '13366668888' for key 'telephone' 这个字段有多个重复值出现-- 删除唯一约束----(删除唯一索引的名称)
-- alter table 表名 drop index 索引名(索引名如果没有起名字默认是列的名称);
ALTER TABLE test1 DROP INDEX telephone ;INSERT INTO test1 VALUES(3,'文章','13366668888');-- 添加唯一约束-- -- alter table 表名--  add constraint(声明)--  唯一约束的索引名称 -- unique(列名);ALTER TABLE test1 ADD CONSTRAINT index_telephone UNIQUE(telephone) ;
-- uplicate entry '13366668888' for key 'index_telephone' DROP TABLE test1;-- 主键约束primary key ---特点非空且唯一
CREATE TABLE test1(id INT PRIMARY KEY , -- 主键约束NAME VARCHAR(10),gender VARCHAR(3)
);
INSERT INTO test1 VALUES(1,'张三','男'),(2,'李四','女') ;INSERT INTO test1 VALUES(NULL,'高圆圆','女') ;
INSERT INTO test1 VALUES(1,'赵又廷','男') ;
-- 上面的sql直接插入null而且id重复,使用primary key (主键索引)-- 通过sql删除主键
-- alter table 表名 drop primary key ;
ALTER TABLE test1 DROP PRIMARY KEY ;-- 通过sql添加主键
-- alter table 表名 add primary key (列名称) ;
ALTER TABLE test1 ADD PRIMARY KEY(id) ;-- 自增长约束 auto_increment
-- 一般自增长约束都是在主键字段上,保证唯一
-- 指定插入数据的值,下次在之前的值上继续自增1
DROP TABLE test1;
CREATE TABLE test1(id INT PRIMARY KEY  AUTO_INCREMENT, -- 主键约束 + 自增长NAME VARCHAR(10),gender VARCHAR(3)
);INSERT INTO test1(NAME,gender) VALUES('张三','男'),('李四','女') ;
-- 指定插入id的值
INSERT INTO test1 VALUES(20,'高圆圆','女') ;
UPDATE test1 SET id = 25  WHERE id = 20 ;
-- 自增长主键的值一定插入之后产生的而不是修改!
INSERT INTO test1(NAME,gender) VALUES('赵又廷','男') ;-- mysql自带函数---查找数据库表中最后一次自增主键的值是多少
SELECT LAST_INSERT_ID();SELECT * FROM test1 ;

-- 外键约束 foreign key

CREATE TABLE employee(id INT PRIMARY KEY AUTO_INCREMENT, -- 员工编号NAME VARCHAR(10) ,  -- 员工姓名gender VARCHAR(3) , -- 员工性别dept_name VARCHAR(10) -- 员工所在的部门名称
);
INSERT INTO employee(NAME,gender,dept_name)
VALUES('高圆圆','女','测试部'),
('张佳宁','女','运维部'),
('王宝强','男','开发部'),
('文章','男','开发部'),
('赵又廷','男','运维部') ;/*问题:1)查询员工的所有信息---部门名称字段 冗余度大(重复度高)2)一张表描述了两个事情(员工信息,又有部门信息!)解决方案:将这张表拆分两张表一张表员工信息一张表描述部门信息
*/
DROP TABLE employee;-- 创建一张部门表
CREATE TABLE dept(id INT PRIMARY KEY AUTO_INCREMENT, -- 部门编号NAME VARCHAR(10) -- 部门名称
);
INSERT INTO dept(NAME) VALUES('开发部'),('测试部'),('运维部');
-- 创建一个员工表
CREATE TABLE employee(id INT PRIMARY KEY AUTO_INCREMENT, -- 员工编号NAME VARCHAR(10) , -- 员工姓名gender VARCHAR(3) , -- 性别dept_id INT -- 部门编号
);
INSERT INTO employee(NAME,gender,dept_id)
VALUES('高圆圆','女',2),
('张佳宁','女',3),
('王宝强','男',1),
('文章','男',1),
('赵又廷','男',3) ;-- 插入了一个条数据:没有4号部门,但是依然能插入进去!
-- 防止出现问题,添加外键约束---让两个产生关联关系
INSERT INTO employee(NAME,gender,dept_id) VALUES('张三','男',4) ;-- 创建员工表的时候,同时添加外键约束!
/*
外键作用的表---从表,另一张表:主表创建表的时候添加外键constraint (声明)外键名--->起名字 主表名_从表名_fkforiegn key (从表的字段名称)references -- (关联)主表名(主键字段的名称)
*/
CREATE TABLE employee(id INT PRIMARY KEY AUTO_INCREMENT, -- 编号NAME VARCHAR(10),  -- 姓名gender VARCHAR(3), -- 性别dept_id INT ,-- 部门编号CONSTRAINT -- 声明dept_emp_fk -- 外键名称FOREIGN KEY(dept_id) -- 作用在指定外键字段上REFERENCES -- 关联dept(id) -- 主表的主键字段);-- 有了外键之后,直接修改或者删除主表数据,前提需要让从表的数据跟主表没有关联
-- 这个时候才能修改和删除主表数据!
-- 1)将3号部门的员工删除了
DELETE FROM employee WHERE dept_id = 3 ;-- 2)将3号部门在删除
DELETE FROM dept WHERE id = 3;-- 有外键约束,修改--先修改从表,然后在修改主表-- 将2号部门的员工---将部门编号设置1
UPDATE employee SET dept_id = 1 WHERE id = 1 ;
-- 1)将2号部门的员工 --- 改为部门编号3UPDATE dept SET id = 3 WHERE id =2 ;
UPDATE employee SET dept_id = 3 WHERE id =1;-- sql删除外键约束
-- alter table 表名 drop foreign key 外键名;
ALTER TABLE employee DROP FOREIGN KEY dept_emp_fk ;INSERT INTO employee(NAME,gender,dept_id) VALUES('张三','男',4) ;
-- sql 添加外键约束
-- alter table 表名 add constraint 外键名称 foreign key
-- (从表字段名称) references 主表的(主键字段) ;
ALTER TABLE employee
ADD CONSTRAINT dept_emp_fk
FOREIGN KEY (dept_id)
REFERENCES dept(id) ;

级联操作

-- 级联操作cascade
-- 级联删除/级联修改 on delete cascade /on update casade
-- 当修改/删除主表的数据,从表数据随之改动 -- 将上面这个语句放在外键的后面
-- 添加外键的同时---添加级联修改和级联删除
ALTER TABLE employee
ADD CONSTRAINT dept_emp_fk
FOREIGN KEY (dept_id)
REFERENCES dept(id)
ON UPDATE CASCADE
ON DELETE CASCADE ;-- 直接修改主表数据,
-- 将1号部门改成2号部门,这个时候1号部门的员工,它部门编号变成2
UPDATE dept SET id = 2 WHERE id =1 ;
-- 直接删除主表数据,从表随之变化
-- 将3号部门解散
DELETE FROM dept WHERE id = 3 ;SELECT * FROM dept ;
SELECT * FROM employee ;

Day31

1.数据库表的关系问题----->数据库三大范式(理论)

1NF:第一范式    数据库表中每一列是不能在拆分的原子性!(最基本的要求)
 (表中每一个列是单独的,不能在拆分)
 
 
 2NF:第二范式
        在满足1NF基础上,
        1)一张描述一件事情
        2)非主键字段必须完全依赖于主键字段
        
 3NF:第三范式
        在满足2NF基础上
        非主键字段中间不能产生传递依赖
        A字段--->依赖B字段--->依赖于C字段   A字段--->依赖C字段
        
        学生表
             学生id  学生的姓名  学生其他信息   学院id     学生所在的学院     系主任
 
 
         学生表和选课

2.多表查询(使用最多)

-- 多表查询-- 多张同时查询 /*
笛卡尔乘积
内连接
外连接
子查询:select 嵌套 select....情况1:单行单例的数据情况2  多行多列情况3:通过两个表的关系---查询出结果集---->当做"虚表"在和其他之间关联查询!*/CREATE DATABASE ee_2211_02;-- 设计一个部门表CREATE TABLE dept(id INT PRIMARY KEY AUTO_INCREMENT ,-- 部门编号NAME VARCHAR(10)                   -- 部门名称) ;INSERT INTO dept(NAME) VALUES('开发部'),('市场部'),("销售部") ;-- 设计员工表CREATE TABLE employee(id INT PRIMARY KEY AUTO_INCREMENT, -- 员工编号NAME VARCHAR(10),                  -- 姓名gender VARCHAR(3),                 -- 性别salary DOUBLE,                 -- 工资join_date DATE,                     -- 入职日期dept_id INT ,                      -- 部门编号-- 设置外键CONSTRAINT -- 声明dept_emp_fk  -- 外键名FOREIGN KEY (dept_id) -- 指定外键名作用从表的指定字段上REFERENCES  -- 关联dept(id));INSERT INTO employee(NAME,gender,salary,join_date,dept_id) VALUES('文章','男',12000.0,'2021-11-11',1),('王宝强','男',8000.0,'2022-05-28',1),('高圆圆','女',7000.0,'2021-12-31',2),('张佳','女',8000.0,'2021-10-30',3) ,('马保国','男',3000.0,'2022-10-15',3),('黄晓明','男',15000.0,'2022-9-30',1),('姚笛','女',6000.0,'2021-10-10',3);-- 多表查询语法select 字段列表 from 表名1,表名2;-- 需求:查询员工表和部门表的所有信息
SELECT e.*,d.*
FROMemployee e,dept d ;
/*上面查询的结果不符合实际要求,7个员工,现在出现了21个
这个就是笛卡尔乘积,针对A表的记录 和B的记录数,两个表的记录相乘出现笛卡尔乘积的原因:没有设置连接条件!   针对多表查询1)查询哪张表!2)查询指定表的哪些字段!3)他们表和表之间的关系!
*/
-- 多表查之内连接()
/*隐式内连接:where条件---多去使用这种查!select    字段列表 from 表名1,表名2...表名nwhere    这些表之间的连接条件;
*/
-- 需求:查询员工表和部门表的所有信息
SELECT e.`id` '员工编号',e.`name` '姓名',e.`gender` '性别',e.`salary` '工资',e.`join_date` '入职日期',e.`dept_id` '员工所在的部门',d.id '部门编号',d.`name` '部门名称'
FROMemployee e,dept d
WHERE e.`dept_id` = d.`id` ;-- 内连接---显示内连接   (inner可以省略) join
/*select字段列表from 表名1(inner) join表名2on  连接条件
*/
-- 需求:查询员工的姓名,工资,入职日期以及各他的部门名称信息
SELECT e.`name` '姓名',e.`salary` '工资',e.`join_date` '入职日期',d.`name` '部门名称'
FROMemployee e JOIN dept d ON e.`dept_id` = d.`id` ;-- 插入一个员工
INSERT INTO employee(NAME,gender,salary,join_date)
VALUES('邓超','男',10000.0,'2022-10-20') ; -- 外连接
-- 左外连接(通用)
-- 将A表(左表)的和B表(右表)的交集以及A表(左表)中所有数据全部查询!
/*select 字段列表from左表名left (outer) join    -- outer可以省略   -- righter (outer) join 可以右外连接表名2on连接条件;
*/-- 查询所有的员工信息以及员工所在的部门名称信息,没有部门员工的也得查出来
/*
select e.*,d.`name` '部门名称'
from employee e,dept d
where e.`dept_id` = d.`id` ;*/
SELECT e.*,d.`name` "部门名称"
FROMemployee e LEFT OUTER JOIN dept d    -- outer可以省略ON e.`dept_id` = d.`id` ;-- 多表查询之子查询
-- 就是select去嵌套select
-- 情况1:使用where 后面条件表达式=,<=,>=.... -- 需求:查询员工工资最高的员工信息以及他的部门信息-- 1)查询最高工资是多少
SELECT MAX(salary) FROM employee ; -- 15000
-- 2)是15000的员工信息以及部门门信息
SELECT e.*,d.`name` '部门名称'
FROMemployee e,dept d
WHERE e.`dept_id` = d.`id` AND e.`salary` = 15000 ;-- 上面的sql一步走
SELECT e.*,d.`name` '部门名称'
FROMemployee e,dept d
WHERE e.`dept_id` = d.`id` AND e.`salary` = (SELECT MAX(salary) FROMemployee) ;-- 查询大于平均工资所有员工信息以及部门名称信息
-- 1)平均工资是多少
SELECT AVG(salary) FROM employee ; -- 8625
-- 2)查询员工表中员工工资大于8625的员工信息以及部门名称信息,没有部门的员工必须查(外连接)
SELECT e.*,d.`name` '部门名称'
FROM
employee e,
dept d
WHERE e.`dept_id` = d.`id` AND e.`salary` > 8625;-- 上面sql优化--一步走,查询出没有部门的员工---使用外连接
SELECT e.*,d.`name` '部门名称'
FROMemployee e,dept d
WHERE e.`salary` > (SELECT AVG(salary) FROMemployee) AND e.`dept_id` = d.`id` ;-- 情况2:利用in集合语句 (使用最多)
-- 需求:查询在"市场部"和销售部的员工信息-- 分步走
-- 1)查询市场部和销售部的部门编号SELECT id
FROMdept
WHERE NAME = '市场部' OR NAME = '销售部' ;
-- 2)查询员工表中在2或者3号部门的员工信息以及部门信息
SELECT e.*,d.`name` '部门名称'
FROM employee e,dept d
WHERE e.`dept_id` = d.`id` AND e.`dept_id` IN(2,3) ;-- 一步走
SELECT e.*,d.`name` '部门名称'
FROMemployee e,dept d
WHERE e.`dept_id` = d.`id` AND e.`dept_id` IN (SELECT id FROMdept WHERE NAME = '市场部' OR NAME = '销售部') ;-- 多表查询情况3:
-- 查询某个表的结果集----->
-- 当前"虚表"继续和其他进行关联查询(按照连接条件)
-- 查询入职日期大于"2021-11-11"后入职的员工信息以及部门名称信息-- 分步走
-- 1)查询入职日期大于"2021-11-11"后入职的员工信息
SELECT
*
FROM employee  e
WHERE e.`join_date` > '2021-11-11' ;
-- 2)在1)的结果集的基础上和部门表进行关联查询
SELECT t.name '员工姓名',t.join_date '入职日期',d.`name` '部门名称'
FROM(SELECT * FROMemployee e WHERE e.`join_date` > '2021-11-11')  LEFT JOIN dept d ON  t.dept_id = d.id ;   -- 左外连接,没有员工的部门需要查询-- 另一种写法(不考虑没有部门的员工)
SELECT e.*,d.`name` '部门名称'
FROMemployee e,dept d
WHERE e.`join_date` > '2021-11-11' AND e.`dept_id` = d.`id` ;SELECT * FROM dept  ;SELECT * FROM employee ;

Day32

1 数据库的事务

什么是数据库事务

在一个业务中执行多个sql,这多个sql句要么也同时执行成功,要么同时执行失败

create table account(id int primary key auto_increment,name varchar(10),balance int
);
INSERT INTO account (NAME,balance) VALUES('zhangsan',1000),('lisi',1000);
-- 开启事务
START TRANSACTION ;
update account set balance = balance - 500 where id = 1;
update account set balance = balance + 500 where id = 2;
-- 事务回滚
rollback;
-- 提交事务
commit;
update account set balance  = 1000;
-- 查询账户
select * from account;
-- 事务特点 ACID (关系型数据库传统事务)
-- 原子性,一致性,隔离性,持久性!
/*原子性:在使用事务管理的时候,执行多个sql增删改,要么同时执行成功,要么同时失败一致性:高并发的时候,需要保证事务多次读写,保证数据一致性!隔离性:事务和事务是独立的,相互不影响!举例购物车业务--->购物车表和购物车项表同时添加数据订单业务---->订单表和订单项表同时添加数据持久性:   事务一旦提交,对数据的影响是永久性,即使关机了,数据还是要更新的!           */
-- 事务的隔离级别
/*
四个级别:从小到大,安全性---从低到高,效率性:从高到低!read uncommitted :读未提交   read committed :读已提交repeatable read :可重复读   (mysql的默认隔离级别)serializable : 串行话*/SELECT @@tx_isolation; -- 查看隔离级别:5.7以及5.7以前
--  select trasaction_isolation; mysql8.0以后的查看事务的隔离级别
-- 设置隔离级别
-- set global transaction isoloation level 级别的名称;-- 第一种级别read uncommitted:读未提交 会造成问题"脏读"
-- "脏读":是事务管理最严重的问题:一个事务读取到另一个没有提交的事务!/*第二种级别:read committed; 读已提交  有效防止脏读,出现了一个问题"不可重复读"事务(当前本身这个事务提交)多次读取另一个提交事务的前后到的数据不一致!
*//*
mysql的默认级别 repeatable read 可重复读,有效脏读,不可重复读,出现幻读!(一般有更新操作影响了数据)最高级别:serializable:串行话 (一个事务读取到另一个没提交事务,数据查不到的,这个必须提交,才能操作数据!)
*/

2. jdbc

导入jdbc步骤

七大步骤
   1)导包驱动包
   2)注册驱动--加载驱动类
   3)获取数据库的连接对象java.sql.Connection
   4)准备sql语句
   5)通过Connection连接对象获取数据库的执行对象
   6)执行sql语句
   7)释放资源

public class JdbcDemo{public static void main(String[] args){Class.forName("com.mysql.jdbc.Driver");Connection con = DriverManager.getConnection("jdbc:mysql://lovalhost:3306/ee_2211_02","root","158645"            );//准备sql语句String sql = "insert into account(name,balace) values('人a',1000)";//通过数据库链接对象connection获取数据库的执行对象State stmt = con.createStatement();int count = stmt.executeUpdate(sql);System.out.println("影响"+count+"行");stmt.close();con.close();}
}

Day27~Day32相关推荐

  1. Day32 Web自动化进阶

    系列文章目录 Day01 软件测试基础总结 Day02 测试用例知识点总结(上) Day03 测试用例知识点总结(下) Day04 禅道-从安装到卸载 Day05 MySql的基础使用 Day06 M ...

  2. python从入门到实践_Python编程从入门到实践日记Day32

    Python编程从入门到实践日记Day32 第7章 函数(八) 1.传递任意数量的实参 - 使用任意数量的关键字实参 有时候,需要接受任意数量的实参,但预先不知道传递给函数的会是什么样的信息.在这种情 ...

  3. python学习day32 黏包 struct模块

    为什么会出现黏包问题?  首先只有在TCP协议中才会出现黏包现象 是因为TCP协议是面向流的协议 在发送的数据 传输过程中 有缓存机制 来避免数据丢失 因此 在连续发送小数据的时候 以及接收大小不符的 ...

  4. day27 CRM delete action 嵌入CRM

    课程目录:deleteactionpop up window嵌入crm项目 权限(未讲)学员交作业发邮件 代码路径:https://github.com/liyongsan/git_class/tre ...

  5. day27 MySQL 表的约束与数据库设计

    day27  MySQL 表的约束与数据库设计 第1节 回顾 1.1  数据库入门 1.1.1 SQL 语句的分类: 1) DDL 数据定义语言 2) DML 数据操作语言 3) DQL 数据查询语言 ...

  6. day27作业与总结

    day27作业 from selenium.webdriver import Chrome,ChromeOptions from multiprocessing import Process from ...

  7. day27多进程和多线程总结和作业

    day27多进程和多线程总结和作业 一.什么是线程和进程 1. 什么是进程 - 工厂一个正在运行的应用程序就是一个进程. 每一个进程均运行在其专用且受保护的内存(运行内容)中2. 什么是线程 - 工厂 ...

  8. English Learning - L3 作业打卡 Lesson5 Day32 2023.6.5 周一

    English Learning - L3 作业打卡 Lesson5 Day32 2023.6.5 周一 引言

  9. python 全栈开发,Day32(知识回顾,网络编程基础)

    python 全栈开发,Day32(知识回顾,网络编程基础) 一.知识回顾 正则模块 正则表达式 元字符 :. 匹配除了回车以外的所有字符\w 数字字母下划线\d 数字\n \s \t 回车 空格 和 ...

最新文章

  1. 在shell中变量的赋值有五种方法
  2. 用 Hadoop 进行分布式并行编程, 第 2 部分 程序实例与分析
  3. effective C++ 读书笔记(0-2)
  4. 微软未来五年将把80%资源投入云计算
  5. div+js写弹出框
  6. 知识追踪常见建模方法之IRT项目反应理论
  7. android谷歌地图_Android Google地图:添加天气数据
  8. 操作系统:文件共享的实现方法
  9. 山东工商学院计算机2军训,山东工商学院举行2018级新生开学典礼暨军训动员大会...
  10. vim和emac体验
  11. Mockman-Mock服务工具的安装与使用以及mock的一些扩展
  12. 内存数据库中的索引技术
  13. LDAP 和 LDAP3 的对比、接口调用(1)
  14. 计算机初级操作员试题汇编,计算机初级操作员试卷.doc
  15. 07.第八章、质量管理
  16. MFC实战篇——分页功能
  17. 关于大数据技术的演讲_百度大数据技术开放平台再度亮相
  18. IM后台开发六之群聊接口实现
  19. 洛谷——P2028 龙兄摘苹果
  20. Android视频直播原理详解

热门文章

  1. Linux性能优化:CPU篇
  2. 【JavaScript】转载:JS高端奇淫技巧
  3. android ca,如何在Android设备上安装可信CA证书?
  4. input触发的事件触发流程
  5. 微信打不开第三方二维码或链接的解决办法
  6. 【5G系列】RLC (Radio Link Control )协议详解
  7. 【学习周报】深度学习笔记第六周
  8. qtable sorting enable中文是按照什么顺序_漫威电影:22部电影观影顺序(附ZY)
  9. Pulling is not possible because you have unmerged files.
  10. android底部导航切换实现(md)