MySQL day08
数据库(DataBase,DB):指长期保存在计算机的存储设备上,按照一定规则组织起来,可以被各种用户或应用共享的数据集合。(7文件系统)
数据库管理系统(DataBase Management System,DBMS):指一种操作和管理数据库的大型软件,用于建立、使用和维护数据库,对数据库进行统一管理和控制,以保证数据库的安全性和完整性。用户通过数据库管理系统访问数据库中的数据。
数据库软件应该为数据库管理系统,数据库是通过数据库管理系统创建和操作的。
数据库:存储、维护和管理数据的集合。
1登录Mysql: mysql -u root -p abc
2* 卸载
1.停止mysql服务 net stop mysql 启动mysql服务 net start mysql
2.卸载mysql
3.找到mysql 安装目录下的 my.ini datadir="C:/ProgramData/MySQL/MySQL Server 5.5/Data/"
3* 修改密码
运行cmd
* 安装成功了打开cmd --> mysql -uroot -p你的密码
* 修改mysql root用户密码
1) 停止mysql服务 运行输入services.msc 停止mysql服务
或者 cmd --> net stop mysql
2) 在cmd下 输入 mysqld --skip-grant-tables 启动服务器 光标不动 (不要关闭该窗口)
3) 新打开cmd 输入mysql -u root -p 不需要密码
use mysql;
update user set password=password('abc') WHERE User='root';
4) 关闭两个cmd窗口 在任务管理器结束mysqld 进程
5) 在服务管理页面 重启mysql 服务
密码修改完成
数据库中一行记录与对象之间的关系。 列:字段 行:一条记录(实体) 这样就很方便用java语言获取数据
public class User{ private int id; private String name; private int age; }
三、sql概述 SQL:Structure Query Language。(结构化查询语言)
4、Sql的分类
DDL**(Data Definition Language):数据定义语言,用来定义数据库对象:库、表、列等; CREATE create、 ALTER alter、DROP drop
DML***(Data Manipulation Language):数据操作语言,用来定义数据库记录(数据); INSERT insert、 UPDATE update、 DELETE delete
DCL(Data Control Language):数据控制语言,用来定义访问权限和安全级别;
DQL*****(Data Query Language):数据查询语言,用来查询记录(数据)。
1库--操作4
1增3 创建 create 语法 create database 数据库名 [character set 字符集][collate 校对规则]
(database/databases 关键字只在对数据库的操作时见到)
create database mydb1;
Create database mydb2 character set gbk;
Create database mydb3 character set gbk collate gbk_chinese_ci;
2删1 drop
前面创建的mydb3数据库 Drop database mydb3;
3改1 这里改动的是字符集 alter
查看服务器中的数据库,并把mydb2的字符集修改为utf8; alter database mydb2 character set utf8;
4查4 show 4
1查看当前数据库服务器中的所有数据库show databases;
2查看前面创建的mydb2数据库的定义信息:查数据库创建语句 Show create database mydb2;
3查看当前使用的数据库 语法select database();
5切换数据库use mydb2;
2表--操作4
在创建表之间一定要指定数据库. use 数据库名 最后一个字段不加 逗号
*语法:
create table 表名(
字段1 字段类型,
字段2 字段类型,
...
字段n 字段类型
);
1 常用数据类型:10
int:整型
float:浮点型:float(5,2)--> 999.99, -999.99 表示浮点型数长度为5 小数位为2 一般不需要这样指定长度。
double:浮点型,例如double(5,2)表示最多5位,其中必须有2位小数,即最大值为999.99;
char:固定长度字符串类型; char(10) 'abc ' 申请的速度快 但是费内存
varchar:可变长度字符串类型;varchar(10) 'abc' 这个与char相比较 比如给定的长度是10 但是就用了5 那5个就会不分配 省内存
text:字符串类型;
blob:字节类型;
date:日期类型,格式为:yyyy-MM-dd;
time:时间类型,格式为:hh:mm:ss
timestamp:时间戳类型 yyyy-MM-dd hh:mm:ss 会自动赋值
datetime:日期时间类型 yyyy-MM-dd hh:mm:ss-
decimal(7,2), 数的长度是7,有两位是小数点
2 约束种类4
1 not null; 非空
2 unique;唯一约束, 后面的数据不能和前面重复
3 primary key;主键约束(非空+唯一); id:作为数据的唯一标识,通常给id int类型设置主键约束,auto_increment null
4 auto_increment;自动增长列 ,一定是和主键一起使用的。
3 增1
2.1.创建表 对表结构的操作(table/tables关键字只会出现在对表结构的操作sql语句中)
不能创建同名称的表 创建表的时候必须有字段 没字段就是一个空表 没有意义
删除表 要是删除表的最后一个字段 只能用drop删除 用删除列的方式不能删除表的最后一个字段 那样那个表就是一个空表了 没有意义
create table student(
id int primary key auto_increment,
name varchar(10),
score double,
address varchar(10)
);
添加主建约束的方式
第一种添加方式:第一种添加方式:此种方式优势在于,可以创建联合主键
CREATE TABLE student(Id int primary key,Name varchar(50));
第二种添加方式:
CREATE TABLE student(id int, Name varchar(50), Primary key(id) );
CREATE TABLE student(id int,Name varchar(50),Primary key(id,name));
第三种添加方式:
CREATE TABLE student(Id int,Name varchar(50)); ALTER TABLE student ADD PRIMARY KEY (id);
创建 索引
普通索引 添加INDEX
ALTER TABLE `table_name` ADD INDEX index_name ( `column` ) 这是修改然后加上索引
直接通过create index的方式
CREATE FULLTEXT INDEX ft_email_name ON `student` (`name`)
也可以在创建索引的时候指定索引的长度:
CREATE FULLTEXT INDEX ft_email_name ON `student` (`name`(20)) 直接创建索引
主键索引 添加PRIMARY KEY
ALTER TABLE `table_name` ADD PRIMARY KEY ( `column` )
唯一索引 添加UNIQUE
ALTER TABLE `table_name` ADD UNIQUE ( `column` )
全文索引 添加FULLTEXT
ALTER TABLE `table_name` ADD FULLTEXT ( `column`)
如何添加多列索引
ALTER TABLE `table_name` ADD INDEX index_name ( `column1`, `column2`, `column3` )
4 删1
1 删除表 drop table 表名;
5 改4 add change大 modify小 rename
1增加列 alter table 表名 add 字段名 类型(长度) 约束;
2修改字段 名称 类型 约束。alter table 表名 change 旧字段名 新字段名 类型 约束; 换成同一个名字也可以
3修改列的类型和约束 alter table 表名 modify 字段名 类型 约束;
4删除列 alter table 表名 drop 字段名;
5 修改表名 rename table 旧表名 to 新表名
6 查3
1 查看当前数据库下的所有表show tables; 显示所有的表名字
2 查看当前数据库某个表的结构 desc 表名; 显示表中 所有的字段 和属性
3 查看employee的表结构 show create table employee
3 数据--操作4 增改都不出现table
1增2
1增加数据 insert into 表名(字段1,字段2,字段3) values(值1,值2,值3);
2 insert into 表名 values(值1,值2,值3,值4);有几个字段就有几个值,如果不想给字段赋值,也要写空
注意:
- 没有赋值的列,系统自动赋为null
- 列名与列值的类型、个数、顺序要一一对应。
- 值不要超出列定义的长度。
- 如果插入空值,请使用null
- 插入的日期和字符串,使用引号括起来
2删2 delete where
1 delete from star;删除数据(一次至少删除一条数据,不能删除某条数据的某个字段) delete from 表名 [where 条件];不写条件表示将所有数据全部删除 表结构还在;删除后的数据可以找回
2 trancate 表名;删除表,trancate table star;并新建一张一样结构和名字的该表。
区别 - DELETE 删除表中的数据,表结构还在;删除后的数据可以找回
- TRUNCATE 删除是把表直接DROP掉,然后再创建一个同样的新表。删除的数据不能找回。执行速度比DELETE快。
3改1 update set where
1更新数据 update 表名 set 字段1=值1,字段2=值2 [where 条件];不写条件表示将所有数据字段1的值改成值1,字段2的值改成值2
可以写成 字段1= 字段1+2000; 可以是+-*/ 但是不能是+= 前面的类型只能是数 要是字符串只显示后面的数值
日期查询
定义和用法
DATE_FORMAT() 函数用于以不同的格式显示日期/时间数据。
语法
DATE_FORMAT(date,format)
date 参数是合法的日期。format 规定日期/时间的输出格式。
可以使用的格式有:
格式 | 描述 |
%a | 缩写星期名 |
%b | 缩写月名 |
%c | 月,数值 |
%D | 带有英文前缀的月中的天 |
%d | 月的天,数值(00-31) |
%e | 月的天,数值(0-31) |
%f | 微秒 |
%H | 小时 (00-23) |
%h | 小时 (01-12) |
%I | 小时 (01-12) |
%i | 分钟,数值(00-59) |
%j | 年的天 (001-366) |
%k | 小时 (0-23) |
%l | 小时 (1-12) |
%M | 月名 |
%m | 月,数值(00-12) |
%p | AM 或 PM |
%r | 时间,12-小时(hh:mm:ss AM 或 PM) |
%S | 秒(00-59) |
%s | 秒(00-59) |
%T | 时间, 24-小时 (hh:mm:ss) |
%U | 周 (00-53) 星期日是一周的第一天 |
%u | 周 (00-53) 星期一是一周的第一天 |
%V | 周 (01-53) 星期日是一周的第一天,与 %X 使用 |
%v | 周 (01-53) 星期一是一周的第一天,与 %x 使用 |
%W | 星期名 |
%w | 周的天 (0=星期日, 6=星期六) |
%X | 年,其中的星期日是周的第一天,4 位,与 %V 使用 |
%x | 年,其中的星期一是周的第一天,4 位,与 %v 使用 |
%Y | 年,4 位 |
%y | 年,2 位 |
实例
下面的脚本使用 DATE_FORMAT() 函数来显示不同的格式。我们可以使用 NOW() 来获得当前的日期/时
将数据库中存放的年月日时分秒字符串如20150119221048转换为2015-01-19 22:10:48
[sql] view plain copy print?
1. select seq_no,show_mode,dev_id,dev_type,dev_attr,content_attr,
2. content_path,file_name,date_format(start_time, '%Y-%m-%d %H:%i:%s'),date_format(end_time, '%Y-%m-%d %H:%i:%s'),
3. regular_time,order_level,operator_level,order_state from order_execute_info
4. where dev_type = '0011' order by dev_id asc;
4查11 select from where like
注意: 聚合函数前面不能有字段名,除非是用于分组的字段名 聚合函数不能用在 where后面
语法:先后顺序select [列名,列名] [*] [聚合函数][distinct 字段] from 表名 [WHERE --> group by -->having--> order by]
SQL UNION 操作符
UNION 操作符用于合并两个或多个 SELECT 语句的结果集。
请注意,UNION 内部的 SELECT 语句必须拥有相同数量的列。列也必须拥有相似的数据类型。同时,每条 SELECT 语句中的列的顺序必须相同。
SQL UNION 语法
SELECT column_name(s) FROM table_name1
UNION
SELECT column_name(s) FROM table_name2
注释:默认地,UNION 操作符选取不同的值。如果允许重复的值,请使用 UNION ALL。
SQL UNION ALL 语法
SELECT column_name(s) FROM table_name1
UNION ALL
SELECT column_name(s) FROM table_name2
另外,UNION 结果集中的列名总是等于 UNION 中第一个 SELECT 语句中的列名。
使用 UNION 命令
实例
列出所有在中国和美国的不同的雇员名:
SELECT E_Name FROM Employees_China
UNION
SELECT E_Name FROM Employees_USA
UNION ALL
UNION ALL 命令和 UNION 命令几乎是等效的,不过 UNION ALL 命令会列出所有的值。
字段1 表示显示那个字段
顺序: select...from...where...group by...having...order by
from 表名 [where 条件]----->[group by 字段]----->[having 条件(分组后的条件)]----->[order by];
先分组 分组后聚合函数统计每组的数量
有分组 字段哪里就不能写*号
1 查询所有的列的记录 select * from 表名;
2 查询某张表特定列的记录 select 字段名1,字段名2 from 表名;
3 去重查询 (distinct 字段) select distinct 字段名 from 表名; 去重字段名只能写一个 要是,字段名2 后面的字段只是显示出来不具有去重原理
这是筛选某个字段重复 去除重复记录(两行或两行以上记录中系列的上的数据都相同) 上面可以多个字段,查询多个字段的值不同时重复
例如- 把年龄重复的给筛选 要查询的字段的数据一模一样才能去重
4 别名查询 (字段 as 别名, as可以省略) select 字段名1 as 姓名 from 表名; 可以写多个 但是必须带引号
只是为了展示得更容易看懂一点,其实没啥作用- 查询明星名称和价格,明星价格通过别名‘身价’来显示
5 运算查询(+,-,*,/等) select 字段名+10 from 表名; - 把明星名称,
和明星年龄+10查询出来 要是字符串+10 就只显示后面的10 没有意义运算查询字段字段之间是可以的 显示要求的新字段
6 条件查询7都是在where后面用的
l 注意 between...and...: 包含临界值 eg: between 3000 and 6000相当于: 3000<=price<=6000
l 1 In 2 between and 3 is null is not null 4 and 5 or 6 not 7通配符 like ’%_’
l - 查询id在1,5,10,15范围内的明星 select * from star where id in(1,5,10,15)
7 模糊查询,like和通配符一起使用: %;多位(0~n)_; 一位
8 排序; order by 列名 asc(默认升序可以不写) desc(降序) 排序语句放在查询语句的最后面!
1 Order by price 直接升序 order by price asc, age; 2先升序 如果价格一样 按照age升序 3 order by asc, age desc; 先升序如果价格一样按照 age 降序
9 聚合函数 (聚合函数前不能有字段名,如果一定要有,那么该字段名只能是用来分组的字段名)聚合函数是用来做纵向运算的函数
如果前面有字段了只显示第一个字段的值 后面显示筛选值, 后面可以有 as “最大值”
1. count(*|字段);统计指定列不为NULL的记录行数 ,
2. 如果要统计表中的总记录数,那么count( *|不能为空的字段名)
3. sum();计算指定列的数值和,如果指定列类型不是数值类型,那么计算结果为0
4. max();筛选指定列的最大值,如果指定列是字符串类型,那么使用字符串排序运算 abc的排序
5. min();筛选指定列的最小值,如果指定列是字符串类型,那么使用字符串排序运算 如果有2个最小值一样 就显示出来第一个
6. avg();计算指定列的平均值,如果指定列类型不是数值类型,那么计算结果为0
10 分组查询,单独使用group by,只显示各个组的第一条数据()
- group by结合group_concat()使用,可以展示每一组的数据集合,group_concat()中不能写*
- select type,group_concat(name) from start group by type;分组查询select后面一定要跟上分组的字段名
解释 type 表示显示分组后 第一个name字段的 type group_concat(name) 多显示组 这组字段为group_concat(name) 把所有人的姓名显示出来
查询所有的明星,按照type分组
select * from star group by type; //只显示每组中的第一条信息
select type,group_concat(*) from star group by type; //错误的写法
Select name from star group by type // 显示每组中的第一个姓名
select type,group_concat(name) from star group by type; //显示每组中每个人的姓名
- group by结合聚合函数使用(聚合函数前写得字段名必须是用于分组的字段名) 用聚合函数都是用于数理统计的数, 字段类型都是数据类型
- 统计每一组的数据个数 select type,count(*) from product group by type;
- 统计每一组的数据的总价格 select type,sum(price) from product group by type;
- 统计每一组的数据中价格最小的那个 select type,min(price) from product group by type;
- 根据明星类别分组,统计不同明星类别的个数
- 根据明星类别分组,统计不同明星类别的总价格
11 分组后筛选(having)
- 根据明星类别分组,统计不同明星类别的个数,并且该明星类别数量大于2的
注意:
- having是分组后筛选
where和having的区别
- 1.having是在分组后对数据进行过滤.where是在分组前对数据进行过滤
- 2.having后面可以使用聚合函数(统计函数)where后面不可以使用聚合函数
- 3.having后面加的条件一定要与分组有关。
- 4.WHERE是分组前记录的条件,如果某行记录没有满足WHERE子句的条件,那么这行记录不会参加分组;而HAVING是对分组后数据的约束。
自己 Select *, price>3000 from star1; 查询 身价大于3000的 后面会加一行 前面加的这个price>3000 是自加字段 这是一个boolean值 数据都显示的boolea值
比如:
一般条件放到 where后面 需要分组后的条件放到 having后面
select type,count(*) from star group by type having count(*)>2;
分组后统计 每组的长度大于2
select type,count(*) from star where count(*)>2 group by type;
Where后面不能加聚合函数 这个错误
select type,count(*) from star where age>30 group by type;
先把大于30岁的筛选出来再分组
select type,count(*) from star group by type having age>30;
自己理解 这个是年龄>30岁和这个分组没有关系 相当于冲突了 这个错误 一般后面跟聚合函数 与分组有关的条件
这样加的条件就和后面的没有关系了
小知识:
在mysql中,字符串类型和日期类型都要用单引号括起来。'tom' '2015-09-04'
空值:null
语法:
SELECT selection_list /*要查询的列名称*/
FROM table_list /*要查询的表名称*/
WHERE condition /*行条件*/
GROUP BY grouping_columns /*对结果分组*/
HAVING condition /*分组后的行条件*/
ORDER BY sorting_columns /*对结果分组*/
LIMIT offset_start, row_count /*结果限定*/
4 数据的完整性3
作用:保证用户输入的数据保存到数据库中是正确的。确保数据的完整性 = 在创建表时给表中添加约束
完整性的分类:> 实体完整性 > 域完整性 > 引用完整性
1、实体完整性
实体:即表中的一行(一条记录)代表一个实体(entity) 实体完整性的作用:标识每一行数据不重复。
约束类型: 主键约束(primary key) 唯一约束(unique) 自动增长列(auto_increment)
给主键添加自动增长的数值,列只能是整数类型,但是如果删除之前增长的序号,后面再添加的时候序号不会重新开始,而是会接着被删除的那一列的序号
CREATE TABLE student(Id int primary key auto_increment,Name varchar(50));
INSERT INTO student(name) values(‘tom’);
2、域完整性
域完整性的作用:限制此单元格的数据正确,不对照此列的其它单元格比较域代表当前单元格
域完整性约束:数据类型 非空约束(not null) 默认值约束(default) Check约束(mysql不支持) check();
1.1 数据类型:(数值类型、日期类型、字符串类型)1.2 非空约束:not null
1.3 默认值约束 default
CREATE TABLE student(Id int pirmary key,Name varchar(50) not null,Sex varchar(10) default ‘男’);
insert into student1 values(1,'tom','女');
insert into student1 values(2,'jerry',default);
3、引用完整性 添加外键
表和表之间存在一种关系,但是这个关系需要谁来维护和约束?
1外键约束外键作用: 保证引用完整性,也就是说数据的准确
注意 外键列的类型一定要和参照的主键的类型一致
l 1 省略外键名字 系统会自动为外键起名字 - alter table 表 add [constraint 外键名] foreign key(字段) references 表(字段);
l 2 给外键起一个名字 alter table product add constraint fk_p2c foreign KEY (p_pno) references category(c_cno);
l 3 删除外键去除关系 alter table product drop foreign key fk_p2c;
l 3 要是没有写外键名字 就要到数据库操作软件里面去找(资料) 外键的名字 然后删除
l 3 创建数据库的时候外键的名字不能相同
- 给商品表添加外键 alter table product add foreign key(cno) references category(cid);
1一对多(掌握) 在多的一方创建一个字段作为外键,指向一的一方主键
2多对多(掌握) 新建一张第三方表,至少包含两个字段,都作为外键,分别指向各自的主键
3一对一(了解) 先当做一对多,在外键字段添加唯一约束。
5多表查询6
1 交叉查询 若干表没有条件的连接在一起
select a.*,b.* from a,b ;或者 select *from a,b;- 交叉查询其实是一种错误.数据有很多无用数据,叫笛卡尔积.
- 假设集合A={a,b},集合B={0,1,2},则两个集合的笛卡尔积为{(a,0),(a,1),(a,2),(b,0),(b,1),(b,2)}。可以扩展到多个集合的情况。
- 交叉查询产生这样的结果并不是我们想要的,那么怎么去除错误的,不想要的记录呢,当然是通过条件过滤。通常要查询的多个表之间都存在关联关系,那么就通过关联关系去除笛卡尔积。
2 内连接查询(重点)
1 隐式内连接select a.*,b.* from a,b where 连接条件 或者:select * from a, b where 连接条件
2 显示内连接select a.*,b.* from a [inner] join b on 连接条件或者:select *from a [inner] join b on 连接条件 where 其它条件
- 使用主外键关系做为条件来去除无用信息.抓住主外键的关系,用主外键作为连接条件 b表里面的外键=a表里面主键
- 显示里面的,on只能用主外键关联作为条件,如果还有其它条件,后面加where
3 外连接(重点)
1左外连接 以join左边的表为主表,展示主表的所有数据,根据条件查询连接右边表的数据,若满足条件则展示,若不满足则以null显示
select a.*,b.* from a left [outer] join b on 条件 或者: select *from a表 left [outer] join b表 on 条件
2右外连接 以join右边的表为主表,展示它的所有数据,根据条件查询join左边表的数据,若满足则展示,若不满足则以null显示
select a.*,b.* from a right [outer] join b on 条件 或者: select *from 表a right [outer] join 表b on 条件
4 子查询
- 一个select语句中包含另一个完整的select语句。
- 子查询就是嵌套查询,即SELECT中包含SELECT,如果一条语句中存在两个,或两个以上SELECT,那么就是子查询语句了。
1步骤解析 子查询这个iPhone 必须是唯一 否则产生错误, 子查询可以和 内外连接一起使用
- 第一步:查询Iphone5s的商品价格select price from product where pname = 'Iphone5';
- 第二步:查询价格高iPhone5s的商品信息 select *from product where price >(第一步语句作为条件)
2 例子
- 查询和方便面是同一类别的商品信息 SELECT *from product where cno = (SELECT cno from Product where pname ='方便面') and pname <> '方便面';
- 查询类别是手机数码的所有商品信息 select *from product where cno = (SELECT cid FROM category where cname ='手机数码');
5 联合查询(了解)
- 合并结果集就是把两个select语句的查询结果合并到一起
1语法- union:去除重复记录,例如:SELECT * FROM t1 UNION SELECT * FROM t2
- union all:不去除重复记录,例如:SELECT * FROM t1 UNION ALL SELECT * FROM t2
6 分页查询(掌握)
Limit优点 查到需要多少页数的数据后 就不再向后查询
- limit a,b; - a:从哪里开始(从0开始计数的) 偏移量 - b:一页显示数据的数量 固定值 前端或者安卓,ios
a = (curPage-1)*b;// curPage当前页数
一页显示3条数据: 第1页: a = 0; b = 3;
第2页: a = 3; b = 3;
第3页:a = 6; b = 3;
第四页:a=9,b=3.
8 JDBC的概念 day10
学习目的 ; 1自己创建jdbcUtils 2用dbcp创建 dbcpUtils 3用C3p0创建 C3P0Utils 4直接使用框架DBUtils 操作数据库
在上面建的类都是 有这三个方法 1注册驱动 2获得链接 5关闭资源
*单一职责、开放封闭、依赖倒置、迪米特法则、里氏替换、接口隔离
1 什么是JDBC - JDBC:java database connectivity sun公司为了简化和统一java连接数据库,定义的一套规范(API)
2 JDBC和数据库驱动的关系 - 接口(JDBC)与实现(驱动jar包)的关系
1开发第一个JDBC程序`开发步骤
① - 注册驱动(要引入驱动jar包)
1 registerDriver(Driver driver) ;注册驱动,Driver类中包含一个静态代码块
翻阅源码发现,通过API的方式注册驱动,Driver会new两次,所有推荐这种写法: Class.forName("com.mysql.jdbc.Driver");
② - 获得连接
1.2 getConnection(String url, String user, String password) ;与数据库建立连接
Jdbc:mysql://localhost:3306/web06_1; jdbc;协议 mysql:子协议 localhost:主机名 3306:端口号 web06_1:数据库名 eg:http://www.baidu.com
③ - 创建执行sql语句的对象
- 接口的实现在数据库驱动中。所有与数据库交互都是基于连接对象的。
2.1createStatement() ;创建执行sql语句对象
2.2prepareStatement(String sql) ;创建预编译执行sql语句的对象 .setInt(1,1) 设置第一个问号 setString(2,”李四”)设置第二个问号 setnull(3,null) 设置第三个问号为null
④ - 执行sql语句,处理结果
.java.sql.Statement接口
- 接口的实现在数据库驱动中
- 操作sql语句,并返回相应结果对象
1 Statement; 执行sql语句对象
- ResultSet executeQuery(String sql) 根据查询语句返回结果集。只能执行select语句。
- int executeUpdate(String sql) 根据执行的DML(insert update delete)语句,返回受影响的行数。
- boolean execute(String sql) 此方法可以执行任意sql语句。返回boolean值,表示是否返回的是ResultSet结果集。仅当执行select语句,且有返回结果时返回true, 其它语句都返回false;
2 得到结果集 java.sql.ResultSet接口 封装结果集,查询结果表的对象 用循环while 得到结果
- 提供一个游标,默认游 指向结果集第一行之前。 把所有查询结果放到这个盒子里面 这是个集合或者什么 - 调用一次next(),游标向下移动一行。
- 提供一些get方法。
4.2ResultSet接口常用API
- boolean next() ;将光标从当前位置向下移动一行
- int getInt(int colIndex)以int形式获取ResultSet结果集当前行指定列号值
- int getInt(String colLabel)以int形式获取ResultSet结果集当前行指定列名值
- float getFloat(int colIndex)以float形式获取ResultSet结果集当前行指定列号值
- float getFloat(String colLabel)以float形式获取ResultSet结果集当前行指定列名值
- String getString(int colIndex)以String 形式获取ResultSet结果集当前行指定列号值
- String getString(String colLabel)以String形式获取ResultSet结果集当前行指定列名值
- Date getDate(int columnIndex); 以Date 形式获取ResultSet结果集当前行指定列号值
- Date getDate(String columnName);以Date形式获取ResultSet结果集当前行指定列名值
⑤ - 关闭资源
- void close()关闭ResultSet 对象
2单元测试介绍
1. 介绍:JUnit是一个Java语言的单元测试框架。属于第三方工具,一般情况下需要导入jar包,不过,多数Java开发环境 已经集成了JUnit作为单元测试工具
2. 编写测试类,简单理解可以用于取代java的main方法
3. 在测试类方法上添加注解@Test
4. 注解修饰的方法要求:public void 方法名() {…} ,方法名自定义建议test开头,没有参数。
5 添加eclipse中集成的Junit库,鼠标点击“@Test”,使用快捷键“ctrl + 1”,点击“Add Junit …”
6 使用:选中方法右键,执行当前方法;选中类名右键,执行类中所有方法(方法必须标记@Test)
7 常见使用错误,如果没有添加“@Test”,使用“Junit Test”进行运行,将抛异常
1 @Test 一定要写,并且就是@Test 2方法一定要是public 3不要返回值
3增强版本
1注册驱动加强
静态代码块 只要改类加载(改类种有语句运行,就运行这个)
1修改发现源码也是注册驱动这是这个代码 防止驱动开两次 就用反射 DriverManager.registerDriver(new Driver()); Class.forName("com.mysql.jdbc.Driver");
2执行sql语句的加强
2发现用Statement执行sql代码的时候 当输入的有 or id=1 就能正常通过 说明这个可以重改你的sql代码
String str = "select * from star1 where name='"+username+"'and price='"+password+"'";
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery(str);
ResultSet resultSet = statement.executeQuery(str);
prepareStatement这个类extend Statement 类 这个首先把sql代码预编译 每个问号都是占位符 用户不能修改sql语句 这连个都是接口
String str = "select * from star1 where name= ? and price= ?";
PreparedStatement prepareStatement = connection.prepareStatement(str);
prepareStatement.setString(1, username);
prepareStatement.setInt(2, 5000);
ResultSet resultSet = prepareStatement.executeQuery();
3硬编码读取配置文件
1用字节流 2用类加载器 都是读到properties对象种 3种是直接从包下得到资源包 都是key value的形式
在静态块中来读流,读取配置文件中的数据
Properties properties = new Properties();
将数据加载进properties对象
1第一种读取配置文件的方法加载到properties中 (只能在java工程中用,对于web工程路径要改变)
FileInputStream in = new FileInputStream(new File("src/jdbcconfig.properties"));
2 第二种读取配置文件的方法 获取类的加载器只能用于获取src下面的文件
ClassLoader classLoader = JDBCUtil.class.getClassLoader();
InputStream in = classLoader.getResourceAsStream("jdbcconfig.properties"); //得到资源把资源转化成流
properties.load(in); //从输入流中读取到properties里面
要从properties对象中获取数据
url = properties.getProperty("url");
user = properties.getProperty("user");
password = properties.getProperty("password");
driverStr = properties.getProperty("driverStr");
3第三种读取配置文件的方法 只能用于获取src下面的 以.properties结尾的文件
ResourceBundle bundle = ResourceBundle.getBundle("jdbcconfig");
url = bundle.getString("url");
user = bundle.getString("user");
password = bundle.getString("password");
driverStr = bundle.getString("driverStr");
9 JDBC连接池
1.为什么使用连接池重写工具类
- Connection对象在JDBC使用的时候就会去创建一个对象,使用结束以后就会将这个对象给销毁了.每次创建和销毁对象都是耗时操作.需要使用连接池对其进行优化.程序初始化的时候,初始化多个连接,将多个连接放入到池(集合)中.每次获取的时候,都可以直接从连接池中进行获取.使用结束以后,将连接归还到池中.
.0队列和堆栈的区别
- 队列:先进先出,从头部移出数据,从尾部添加数据。吃了拉出来 - 堆栈:后进先出,从尾部添加数据,从尾部移出数据。吃了吐出来
1装饰着
1 编写连接池条件:1.装饰者和被装饰者实现的是同一个接口(或者继承了同一个类) 2.装饰者里面要拿到被装饰者类的引用
自己理解: 同一个父亲 1里面一个子类有全套的实现方法 2另一个子类改变第一个子类的某个方法 达到不同的效果
2 装饰着的理解: 把类1中的参数传到 类2中(这种传递的是引用类型,是实参,两个类公用的同一个参数,无论那个类里面对这个参数进行更改,这两个类都的参数都更改)
3 传参问题 直接匿名函数有参构造传值, 2个功能 1向集合里面添加对象, 2匿名对象传对象, 3匿名对象传 本身增加的集合
现在传输的是个实际参数 是地址值 不管前后加了多少 我那个类里面就有多少. 目的只是传输的地址值 不是传输的数量
4 使用连接池的步骤编码
//声明一个连接池,存放连接
static LinkedList<Connection> pool = new LinkedList<>();
//类加载完毕,池子中就会有5个连接
static{
for(int i=0;i<5;i++){
try {
pool.add(new MyConnection(JDBCUtil.getConnection(), pool));
} catch (SQLException e) {
e.printStackTrace();
}
}
}
5 编写连接池遇到的问题
- 如果新建了connection,用完之后怎么判别是原池子中的connection(需要放回去),还是新建的connection(需要销毁)。
解决办法(自定义一个Connection,重写close方法)
- 继承 条件:可以控制父类的构造
- 装饰者模式 目的:改写已存在的类的某个方法或某些方法,装饰设计模式(包装模式)
1. 编写一个类实现一个接口,为被包装类
2. 编写一个类,实现与被包装类相同的接口。(具备相同的行为)
3. 定义一个被包装类类型的变量。
4. 定义构造方法,把被包装类类的对象注入,给被包装类变量赋值。
5. 对于不需要改写的方法,调用被包装类类原有的方法。
6. 对于需要改写的方法,写自己的代码。
- 动态代理
2 datasource接口概述
- Java为数据库连接池提供了公共的接口:javax.sql.DataSource,各个厂商(用户)需要让自己的连接池实现这个接口。这样应用程序可以方便的切换不同厂商的连接池! - 常见的连接池:DBCP、C3P0。 自己写用DriverManager 自己创建链接 用连接池就用DataSource
3 DBCP 增删改查
1使用步骤 总共有3个类组成
1测试执行sql语句类
2 自己创建的DBCPUtil类 用于创建链接 得到连接池 关闭资源
3 DBCPUtil jar包导入两个
:Apache推出的Database Connection Pool 核心API: - basicDatasource - basicDatasourceFactory
2老师使用步骤
1- 添加jar包 commons-dbcp-1.4.jar commons-pool-1.5.6.jar
2- 添加配置文件到src目录
3- 编写数据源工具类
4.1通过配置文件来编写public class DBCPUtils {
static DataSource ds;
static { //只需要初始化一次
try {
Properties properties = new Properties();
ClassLoader classLoader = DBCPUtil.class.getClassLoader();
InputStream in = classLoader.getResourceAsStream("dbcpconfig.properties");
properties.load(in);
//得到dbcp对象
ds= BasicDataSourceFactory.createDataSource(properties);
} catch (xception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// 创建连接
public static Connection getConnection() throws SQLException {
return ds.getConnection;
}
// 释放资源
public static void release(ResultSet resultSet, Statement statement, Connection connection) {
}
4.2 通过硬编码来表写(不需要配置文件.了解一下)
DataSource basicDataSource = new BasicDataSource();
basicDataSource.setDriverClassName("com.mysql.jdbc.Driver");
basicDataSource.setUrl("jdbc:mysql://localhost:3306/day01_1");
basicDataSource.setUsername("root");
basicDataSource.setPassword("123456");
4 C3P0 增删改查
开源免费的连接池!目前使用它的开源项目有:Spring、Hibernate等。使用第三方工具需要导入jar包,c3p0使用时还需要添加配置文件c3p0-config.xml
只要创建对象 就自动读取配置文件
1使用步骤 4
1- 添加jar包
2- 编写配置文件c3p0-config.xml,放在src中(注:文件名一定不要写错)
3. 通过配置文件来编写 创建c3p0对象 对象自动会寻找读取配置文件 3创建对象
public class C3P0Utils {
//1创建一个连接池对象 自动链接里面的c3p0-config.xml文件
static DataSource ds = new ComboPooledDataSource();
//2从池中获得一个连接
public static Connection getConnection() throws SQLException{
return ds.getConnection();
}
//3释放资源
public static void closeAll(ResultSet rs,Statement stmt,Connection conn){
}
3 通过硬编码来编写(不需要配置文件.了解一下)
DataSource cpds = new ComboPooledDataSource();
cpds.setDriverClass("com.mysql.jdbc.Driver"); // loads the jdbc driver
cpds.setJdbcUrl("jdbc:mysql://localhost:3306/day01_1");
cpds.setUser("root");
cpds.setPassword("ai1996");
5 DBCP与C3P0区别优缺点
: dbcp线程池不能自动获取配置文件 要用上面3种方法读取 C3P0能自动读取 C3P0更强大
6 DBUtils完成CRUD
1 概述
1. DBUtils是java编程中的数据库操作实用工具,小巧简单实用。 第一个操作数据库框架(jar),
2. DBUtils封装了对JDBC的操作,简化了JDBC操作,可以少写代码。
3. Dbutils三个核心功能介绍
QueryRunner中提供对sql语句操作的API. update(), query()
ResultSetHandler接口,用于定义select操作后,怎样封装结果集.
DbUtils类,它就是一个工具类,定义了关闭资源与事务处理的方法
3.2QueryRunner核心类
- QueryRunner(DataSource ds) ,提供数据源(连接池),DBUtils底层自动维护连接connection
- update(String sql, Object... params) ,执行更新数据 insert update delete 参数就是一个数组,参数个数取决于语句中?的个数
- query(String sql, ResultSetHandler<T> rsh, Object... params) ,执行查询 select
- batch(sql, object[][] params) 批量添加数据 把数据写到二维数组中 每个一维数组 为每一行数据--update是只增加一个数据
3.3ResultSetHandler结果集处理类
Handler类型说明
ArrayHandler 将结果集中的第一条记录封装到一个Object[]数组中,数组中的每一个元素就是这条记录中的每一个字段的值
ArrayListHandler 将结果集中的每一条记录都封装到一个Object[]数组中,将这些数组在封装到List集合中。
BeanHandler 将结果集中第一条记录封装到一个指定的javaBean中。
BeanListHandler 将结果集中每一条记录封装到指定的javaBean中,将这些javaBean在封装到List集合中
ColumnListHandler 将结果集中指定的列的字段值,封装到一个List集合中
KeyedHandler将结果集中每一条记录封装到Map<String,Object>,在将这个map集合做为另一个Map的value,另一个Map集合的key是指定的字段的值。
MapHandler 将结果集中第一条记录封装到了Map<String,Object>集合中,key就是字段名称,value就是字段值
MapListHandler 将结果集中每一条记录封装到了Map<String,Object>集合中,key就是字段名称,value就是字段值,在将这些Map封装到List集合中。
ScalarHandler 它是用于单个数据。例如select count(*) from 表操作。
2使用步骤
1获取线程池对象(c3p0,dbcp)创建对象
2 获取dbutils对象 创建dbutils对象 直接把线程池传递过去
3 写sql语句 底层用prepareStatement查询 String sql = "select nickname from user where id=?"; Object[] param = {7};
4 用dbutils对象的方法 操作数据库
1当更新时 用update 返回int类型 受影响的行数
l 1 new beanListHardler<>(User.class) 查多列 就是集合(不管这个列里面有多少个数据)
l 2 New beanHardler<>(User.class) 查一列 就是一个对象接收
l 3 New ScalarHardler() 查一个数据 用obje查询 ct 变量接收
注意当你写的查询语句 是多列 一列 一个 可以分别使用上面三个查询语句 并接受 从大到小都没有错 当查询多列用一个变量接收就只得到一个
10 Xml和反射
1 XML文档声明
Web.xml中servlet标签和servlet-mapping标签中的servlet-name值应该一致,否则启动服务器会抛出异常
1.文档声明必须为<?xml开头,以?>结束;<?xml version="1.0" encoding="UTF-8"?> 2.文档声明必须从文档的0行0列位置开始;
3.文档声明只有三个属性:
a)versioin:指定XML文档版本。必须属性,因为我们不会选择1.1,只会选择1.0;
b)encoding:指定当前文档的编码。可选属性,默认值是utf-8;
c)standalone:指定文档独立性。可选属性,默认值为yes,表示当前文档是独立文档。如果为no表示当前文档不是独立的文档,会依赖外部文件。
2元素 <servlet>
1.元素是XML文档中最重要的组成部分,2.元素体:元素体可以是元素,也可以是文本,例如:<b><a>你好</a></b>
3.空元素:空元素只有开始标签,而没有结束标签,但元素必须自己闭合,例如:<c/>
4.元素命名:
a)区分大小写
b)不能使用空格,不能使用冒号:
c)不建议以XML、xml、Xml开头
6.良好的XML文档,必须有一个根元素。
3 属性
<web-app version="2.5">
1.属性是元素的一部分,它必须出现在元素的开始标签中
2.属性的定义格式:属性名=属性值,其中属性值必须使用单引或双引
3.一个元素可以有0~N个属性,但一个元素中不能出现同名属性
4.属性名不能使用空格、冒号等特殊字符,且必须以字母开头
l注释 XML的注释与HTML相同,即以“<!--”开始,以“-->”结束。注释内容会被XML解析器忽略!
l转义字符 XML中的转义字符与HTML一样。
因为很多符号已经被XML文档结构所使用,所以在元素体或属性值中想使用这些符号就必须使用转义字符,例如:“<”、“>”、“’”、“””、“&”。
l5 转译多个 CDATA区<![CDATA[任意内容]]>
3 DTD重点要求
开发中,我们很少自己编写DTD约束文档,通常情况我们都是通过框架提供的DTD约束文档,编写对应的XML文档。常见框架使用DTD约束有:struts2、hibernate等。 通过提供的DTD“web-app_2_3.dtd”编写XML
4元素声明
空格 表示有没有都可以
定义元素语法:<!ELEMENT 元素名 元素描述>
元素名:自定义
元素描述包括:符号和数据类型
常见符号:? * + () | ,
常见类型:#PCDATA 表示内容是文档,不能是子标签
5属性声明
属性的语法:
<!ATTLIST 元素名
属性名 属性类型 约束
属性名 属性类型 约束
...
>
元素名:属性必须是给元素添加,所有必须先确定元素名
属性名:自定义
属性类型:ID、CDATA、枚举 …
ID : ID类型的属性用来标识元素的唯一性
CDATA:文本类型
枚举:(e1 | e2 | ...) 多选一
约束:
#REQUIRED:说明属性是必须的;
#IMPLIED:说明属性是可选的;
l实例
<!ATTLIST web-app version CDATA #IMPLIED>
给web-app元素添加 version属性,属性值必须是文本,且可选。
<web-app version="2.3"> 和 <web-app> 都符号约束
6 Schema约束
1.2.3.1什么是Schema
Schema是新的XML文档约束;
Schema要比DTD强大很多,是DTD 替代者;
Schema本身也是XML文档,但Schema文档的扩展名为xsd,而不是xml。
Schema 功能更强大,数据类型更完善
Schema 支持名称空间
2 DOM4j框架使用步骤
1获取单个和多个标签
SAXReader reader =new SAXReader(); //1得到dom4j的对象
Document read = reader.read("src/book.xml");//2根据对象 读取xml到dom中
Element root = read.getRootElement(); //3得到根目录 String name = root.getName(); //获取跟目录的名字
1得到多个子标签
List<Element> list = root.elements(); //4得到父目录下的所有子标签 封装到List集合里面 可以遍历出来
Iterator iterator = root.elementIterator(); //4得到根目录下的所有子目录迭代器
Iterator iterator = root.elementIterator("书"); 得到根目录下所有的书 子标签
2得到一个多级子标签
Element element = (Element) root.selectSingleNode("/书架/书[2]/作者"); 得到一个多级子标签
3得到多个多级标签
List<Element> list = root.selectNodes("书/书名"); //所有根目录下的 书/书名 都得到
List<Element> list = root.selectNodes("//书/书名"); //得到所有目录下的 书/书名 标签
2操作属性
1获取属性值 根据属性名 获取属性值
Attribute attribute = element.attribute("出版社"); //获取属性名
String value = attribute.getValue();//获取属性值
Object data = attribute.getData();
3操作文本
1获取文本 element2.getText()
String text = root.element("报纸").element("新闻").getText(); //从多级标签中 得到文本
String elementText = element.elementText("书名"); 从标签 直接得到文本
3 反射
作用
- 在运行时判断任意一个对象所属的类
- 在运行时构造任意一个类的对象
- 在运行时判断任意一个类所具有的成员变量和方法
- 在运行时调用任意一个对象的方法。通过反射甚至可以调用到private方法。
- 生成动态代理
1 获得字节码的3种
1种方式 * 第一种获取类的字节码对象方式 使用object里面的getClass()方法
* 通过对象名.getClass()获取 不常用 你都不知道对象名是什么 怎么建对象 能建对象也就不用用反射了
Person p = new Person();
Class clazz = p.getClass(); //获取到正在运行的类的字节码对象\
2种方式 * 通过类名.class获取
Class clazz = Person.class;
3种方式 通过Class类的静态方法.forName(包名.类名); * 应用: 加载数据库驱动的时 * 推荐使用:常用
Class clazz = Class.forName("java.lang.String");
2 获取构造方法3
打印出来的构造方法 都是实体的全限定名称 修饰符+ 全类名+参数列表(全称)1 public reflect.Student(java.lang.String,int) 2 public reflect.Student()
1获取所有构造方法 这都是你利用Class里面的方法
//第一步:获取到类的字节码对象
Class clazz = Class.forName("com.heima.domain.Person");
//第二步:调用getConstructors获取类字节码对象的所有构造方法
Constructor<Student>[] cons = clazz.getConstructors();
//第三步:遍历构造方法数组
for(Constructor con : cons) {
//System.out.println(con);
System.out.println("构造方法名:" + con.getName());
2 获取单个构造方法 这都是你利用Class里面的方法 有参数
//第一步:获取类的字节码对象
Class clazz = Class.forName("com.heima.domain.Person");
//第二步:获取有参数构造方法
Constructor<Student> con = clazz.getConstructor(String.class,int.class,char.class);
//第三步:创建对象
Object obj = con.newInstance("超哥",18,'男');
//第四步:向下转型
Person p = (Person)obj;
System.out.println(p.getName());
3 获取无参数的构造方法 无参数
//第一步:获取类的字节码对象
Class clazz = Class.forName("com.heima.domain.Person");
//第二步:获取构造方法
Constructor<Student> con = clazz.getConstructor(); //不传参数代表获取该类的无参数构造方法
//第三步:使用构造方法对象创建一个对象
Object obj = con.newInstance();
//第四步:向下转型
Person p = (Person)obj;
p.eat(); p.sleep();
4- public Constructor[] getDeclaredConstructors() - 返回此 Class 对象表示的类声明的所有构造方法,包括私有构造方法。
5- public Constructor<T> getDeclaredConstructor(Class... parameterTypes) - 返回此 Class 对象所表示的类的指定构造方法。
3 获取对象 操作对象3
1 使用构造方法对象创建一个有参对象 无惨对象 Student student = constructor.newInstance("张三",28);
2通过字节码文件对象创建独享 这个只能用字节码对象创建无惨的 对象 对于有参的对象都必须用 构造函数去创建
Student student = clazz.newInstance();
4 获取成员变量 操作成员变量3
打印所有的 成员变量 打印出来都是全包名 修饰符+全类型+全包名 public java.lang.String com.itheima.reflect.Student.name
对于设置成员变量值 可以先判断成员变量是什么类型 再设置什么类型的值 判断
1得到所有公共成员变量Field[] field=clazz.getFields() - public Field[] getFields() - 返回此Class 对象所表示的实体的所有 成员变量包括继承的。 1得到所有包括私有- public Field[] getDeclaredFields() - 返回此 Class 对象所表示的实体的所有属性,包括私有属性,但不包括继承父类的属性。
2得到成员变量的名- public String getName() - 返回此 Class 对象所表示的实体的全限定名称。
l 对于构造方法对象.getName() 得到全类名 reflect.Student 2对于成员变量 只有名字
3得到成员变量值 Field[] fields = clazz.getFields(); Object object = field.get(student);
4设置变量值 field.set(student,"李四");
- public String getSimpleName() - 返回此 Class 对象所表示的实体的全限定名称。
5获取方法 操作方法4
1得到所有的公有方法- public Method[] getMethods() - 返回此 Class 对象所表示的实体的所有公共属性,包括父类的。
1得到所有的方法包括私有- public Method[] getDeclaredMethods() - 返回此 Class 对象表示的实体的所有方法,包括私有方法,但不包括继承父类的方法。
1获取指定公有方法- public Method getMethod(String name, Class... parameterTypes) - 返回此 Class 对象所表示的实体的指定公共成员方法,- name 指定方法名称,parameterTypes指定方法参数类型 字节码文件类型 例如 Method method = clazz.getMethod("sayHello", String.class,int.class);
1获取指定私有方法 方法名为study Method method2 = clazz.getDeclaredMethod("study");
2调用方法 method2.invoke(clazz.newInstance()); 对于调用的是静态的方法 括号里面可以写(null) 静态方法调用不用对象
3去除方法的私有权限调用方法method2.setAccessible(true);然后调用方法 method2.invoke(clazz.newInstance());
4得到方法名method.getName if (method.getName().equals("show"))
- public Class[] getInterfaces() - 确定此 Class 对象所表示的类实现的接口。
后面几个几乎用不到
- public Class<? super T> getSuperclass() - 返回此 Class 对象所表示的实体的超类的 Class。
- public Package getPackage() - 获取此类的包。 【String [Package].getName()】
- public int getModifiers() - 返回此类或接口以整数编码的 Java 语言修饰符。
【String Modifier.toString(int)】
- public boolean isArray() - 判定此 Class 对象是否表示一个数组类。
- public Class<?> getComponentType() - 返回表示数组组件类型的 Class。
成员变量(Field)获取和设置
- get(Object o); - 得到具体对象的该属性的值
- set(Object o, Object value); - 设置具体对象的该属性的值
方法(Method)调用 - invoke(Object o,Object... args) - o是调用该方法的对象,args是调用该方法时传入的参数