当前位置:网站首页>mysql阶段总结
mysql阶段总结
2022-08-02 03:22:00 【小茹想睡觉】
目录
6.2、如何控制事务 - COMMIT / ROLLBACK
11、String、StringBuffer与StringBuilder之间区别
11.2、StringBuffer和StringBuilder类 ——StringBuffer、StringBuilder字符串变量
1.命令行连接
net start mysql -- 启动数据库
net stop mysql -- 终止数据库
mysql -u root -p -- 连接数据库
update mysql.user set authentication_string=password('******')where user ='root' and Host='localhost'; -- 修改用户密码
flush privileges; -- 刷新权限
-------------------------------------
-- 所有的语句都使用;结尾
show databases; -- 查看所有的数据库
mysql> use school -- 切换数据库 use 数据库名
Database changed
show tables; -- 查看数据库中的所有表
describe student; -- 显示数据库中的所有表
create database westos; -- 创建一个数据库
exit; -- 退出 2.操作数据库
2.1、创建数据库
具体用法

格式

创建表的语句
show create databases school -- 查看创建数据库表的语句 show create table student -- 查看student数据表的定义语句 desc student -- 显示表的结构 -- 创建表 create table student(id int(10),name varchar(30)); -- 删除表 drop table student; -- 修改表名 alter table student(旧表名) rename as student1(新表名) -- 增加表的字段 alter table student1 add age int(3) -- 修改表的字段
2.2 、数据表的类型
-- 关于数据库引擎
2.3、操作数据表
修改

删除
-- 删除表(如果存在再删除) drop table if exists student1
所有的创建和删除操作尽量加上判断,以免报错~


3、MySQL语言(全部记住)
3.1、数据库的意义
数据存储,数据管理
DML 语言:数据操作语言
3.2、插入(添加)
-- 插入语句(添加)
-- insert into 表名([字段名1,字段名2,字段名3])values('值1'),('值2'),('.....');
insert into `student`(`name`) values ('张三');
--由于主键自增我们可以省略(如果不写表的字段,它就会一一匹配)
insert into `student` values('李四')
-- 一般写插入语句,我们一定要数据和字段一一对应!
-- 插入多个字段
insert into `student`(`name`)
values('张三'),('李四')
insert into `student`(`name`) values ('张三')
insert into `student`(`name`,`pwd`,`sex`) values ('张三','aaaaa','男')
insert into `student`(`name`,`pwd`,`sex`)
values('李四','aaaaa','男'),('王五','aaaaa','男') -- 使用这个方法可以一次插入多个字段
3.3、修改
update 修改谁(条件) set 原来的值 = 新值
-- 修改学院名字,带了简介 update student set name = '狂神' where id = 1; -- 如果不指定条件的情况下,会改动所有表! update `student` set `name` = '位晓茹' -- 修改多个属性,逗号隔开 update `student` set `name`='小茹',`email` = 'aaaaa' where id = 1; -- 通过多个条件定位数据 update `student` set column_name = value,[column_name = value,....]where [条件] -- value ,可以是一个具体的值也可以是一个变量
操作符(指定条范围)

3.4、删除
delete 命令
-- 删除数据(避免这样写,会全部删除) delete from `student`; -- 删除指定数据 delete from `student` where id = 1;
truncate 命令
作用: 完全清空一个数据库表,表的结构和索引约束不会变
delete 与 truncate 的区别
相同点:都能删除一个表中的所有数据,不会删除表的结构
不同:
truncate 会重新设置自增列 计数器会归零
truncate不会影响事务
delete 不会影响自增(也就是删除所有数据后,再次添加数据,仍从上次自增开始增加
使用delete删除会出现的一些问题;
delete 删除,重启数据库,现象
InnoDB 自增列会重新从1开始(因为InnoDB是存在内存当中的,断电即失)
MyISAM 继续从上一个自增量开始(因为是存在于文件当中的,不会丢失)
3.5、DQL 查询数据
4、DQL 查询数据
4.1指定查询字段
-- 查询全部的学生
select * from student
-- 查询指定字段
select `name` from student
-- 别名,给查询结果换一个名字 AS 可以给字段起别名,也可以给表起别名
select `name` as 姓名 from student
-- 函数 Concat(a,b) (可以将姓名与查询结果显示在另一个表格内)
select concat('姓名:',name) as 新名字 from student
去重 distinct
作用: 去除查询结果中出现的重复性数据,只显示一条
select vetsion() -- 查询系统版本
数据库的列(表达式)
SELECT VERSION(); -- 查询系统版本(函数) select 100*3-1 as 计算结果; -- 用来计算 (表达式) select @@auto_increment_increment -- 查询自增的步长 (变量) -- 可用这些表达式对查询结果做一些修改
select语法(非常重要)
SELECT[ALL | DISTINCT] {* | table.* [table.filed1[as alias1],[table.filed2[as alias]][,....]]} from table_name [as table_alias] [left | right |inner join table_name2] -- 联合查询 [where ...] -- 指定结果需要满足的条件 [group by ...] -- 指定结果按照哪几个字段来分组 [having] -- 过滤分组的记录必须满足的次要条件 [order by ...] -- 指定查询记录按一个或多个条件排序 [limit {[offset,]row_count | row_countoffset offset}] -- 指定查询的记录从哪条至哪条 **注:[]括号代表可选的,{}括号代表必选的**顺序很重要
select 去重 要查询的字段 from表(注意:表和字段可以取别名)
xxx join 要连接的表 on 等值判断
where(具体的值,子查询语句)
Group By(通过哪个字段来分组)
Having(过滤分组后的信息,条件和where是一样的,位置不同)
Order By .. (通过哪个字段排序 [升序|降序]
Limit startIndex,pagesize
查询:跨表,跨数据库……
4.2、 where 条件子句
模糊查询 like
-- ========================= 模糊查询 ================= -- 查询姓刘的同学 -- like结合 %(代表0到任意个字符) 下划线_(一个字符) select
具体查询 in
联表查询
7种连接查询

在使用联表查询的时候on与where的区别
1.在使用left join的时候,on与where的区别
on条件是在生成临时表时使用的条件,它不管on中的条件是否为真,都会返回左表中的记录
where条件是在临时表生成好后,再对临时表进行过滤的条件。这时已经没有left join的含义(必须返回左边表的记录
MySQL 中 on与where筛选条件的区别 - 101欢欢鱼 - 博客园 参考链接,比较通俗易懂
-- join (连接的表)on (判断的条件)连接查询
-- where 等值查询
自连接
所谓自连接就是自己和自己的表连接
子查询(由里及外)
子查询就是在一个查询中插入另一个查询
子查询与嵌套查询
使用
select小结
5、MySQL函数
官方文档:MySQL :: MySQL 5.7 Reference Manual :: 12.1 Built-In Function and Operator Reference
5.1常用函数
-- ======================= 常用函数 ======================
-- 数学运算
SELECT ABS(-8) -- 绝对值
select CEILING(7.123) -- 向上取整 结果为8
SELECT FLOOR(7.123) -- 向下取整 结果为7
SELECT RAND() -- 返回一个0~1之间的随机数
SELECT SIGN(0) -- 返回一个数的符号 0-0 负数返回-1 ,正数返回1
-- 字符串函数
SELECT CHAR_LENGTH('我可是真能划水') -- 字符串长度
SELECT CONCAT('这','是','拼接字符串') -- 拼接字符串
SELECT INSERT('我爱编程',3,1,'干饭') -- 查询 3代表从某个位置开始替换,1代表替换几个字符串长度
SELECT LOWER('ADSFdfdFDFDFD') -- 转小写字母
SELECT UPPER('fgsgdsdf') -- 转大写字母
SELECT INSTR('WeiXiaoru','i') -- 返回第一次出现字符串的索引
SELECT REPLACE('坚持就一定能够成功','坚持','努力') -- 替换指定的字符串
SELECT SUBSTR('坚持就一定能够成功',5,3) -- 返回指定的子字符串 5代表从哪个字符串开始,3代表截取几个字符
SELECT SUBSTRING('坚持就一定能够成功',5,9) -- 返回指定的子字符串
SELECT REVERSE('坚持就能成功') -- 反转字符串
-- 时间和日期函数
SELECT CURRENT_DATE() -- 获取当前日期
SELECT CURRENT_TIME() -- 获取当前时间
SELECT NOW() -- 获取当前的具体日期时间
SELECT LOCALTIME() -- 获取本地时间
SELECT SYSDATE() -- 获取系统时间
SELECT YEAR(NOW()) -- 获取当前年份
SELECT MONTH(NOW()) -- 获取当前月份
SELECT DAY(NOW()) -- 获取当前日
SELECT HOUR(NOW()) -- 获取当前小时
SELECT MINUTE(NOW()) -- 获取当前分数
SELECT SECOND(NOW()) -- 获取当前秒数
-- 系统
SELECT SYSTEM_USER() -- 获取系统用户
SELECT USER() -- 获取用户
SELECT VERSION() -- 获取当前版本号
5.2聚合函数(常用)
-- =========== 聚合函数 ======= SELECT COUNT(name)FROM student; -- 获取当前表中的数量(指定列),会忽略所有的null值 SELECT COUNT(*) FROM student -- COUNT(*) ,不会忽略null值 本质是计算行数,所有数据都会走一遍 SELECT COUNT(1) FROM student -- COUNT(1),不会忽略null值 会比COUNT(*)快 SELECT SUM(`inventory_id`) AS 总和 FROM rental SELECT AVG(`inventory_id`) AS 平均分 FROM rental SELECT MAX(`inventory_id`) AS 最高分 FROM rental SELECT min(`inventory_id`) AS 最低分 FROM rental
数据库级别的MD5加密(扩展)
什么是MD5
主要增强算大复杂度和不可逆性
MD5不可逆,具体的值的MD5 是一样的
MD5 破解加密网站的原理,背后有一个字典 MD5加密后的值 返回加密前的值
-- ==============测试MD5 加密 ===========
CREATE TABLE `testmd5`(
`id` INT(4) not NULL,
`name` VARCHAR(20) NOT NULL,
`pwd` VARCHAR(50) NOT NULL,
PRIMARY KEY (`id`)
)ENGINE = INNODB DEFAULT CHARSET = utf8
-- 明文密码
insert into testmd5 values(1,'张三','123456'),(2,'李四','123456'),(3,'王五','123456')
-- 加密
update testmd5 SET pwd = MD5(pwd) WHERE id = 1 ;
update testmd5 SET pwd = MD5(pwd) WHERE id ; -- 加密全部的密码
-- 插入的时候加密
insert into testmd5 values(4,'小明',MD5('123456'))
-- 如何校验 : 将用户传递进来的密码,进行MD5加密,然后对比加密后的值
select * FROM testmd5 where `name` = '小明' and pwd = md5('13456')6、事务
6.1、什么是事务
要么都成功,要么都失败
将一组sql放在一个批次中去执行
事务原则:ACID 原则 原子性,一致性,持久性,隔离性
原子性(Atomicity)
同生共死
一致性(Consistency)
事务前后的数据完整性要保持一致,事务前是多少,事务后还是多少
隔离性(Isolation)
事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离。
如果发生干扰就会产生一系列的问题 脏读、虚读、不可重复读、幻读
持久性(Durability)
事务一但提交就不可逆,被持久化到数据库中!
事务如果还未被提交,数据就会返回到原始数据
执行事务
-- ============ 事务 ============= -- mysql是默认事务自动提交的 set autocommit = 0 /*关闭*/ set autocommit = 1 /*开启(默认的)*/ -- 手动处理事务 -- 事务开启 START TRANSACTION -- 标记一个事务的开始,从这个之后的SQL 都在同一个事务内 -- 提交 :持久化 COMMIT -- 回滚 : 回到原来的样子 (失败!) ROLLBACK -- 事务结束 set autocommit = 1 -- 开启自动提交 -- 了解 SAVEPOINT 保存点名 -- 设置一个事务的保存点 ROLLBACK TO SAVEPOINT 保存点名 -- 回滚到保存点 RELEASE SAVEPOINT 删除保存点
模拟事务
CREATE TABLE `account`(
`id` int(3) not null auto_increment,
`name` VARCHAR(30) not NULL,
`money` DECIMAL(9,2) NOT NULL,
PRIMARY KEY (`id`)
)ENGINE = INNODB DEFAULT CHARSET = utf8
insert into account (name,money)
values('A',2000.00),('B',10000.00)
-- 模拟转账
set autocommit = 0 ; -- 关闭自动提交
start transaction -- 开启一个事务(一组事务)
update account set money = money-500 where name = 'A' -- A减500
update account set money = money+500 where name = 'B' -- B加500
commit; -- 提交事务
rollback;
set autocommit = 1; -- 恢复默认在mysql中,事务其实是一个最小的不可分割的工作单元。事务能够保证一个业务的完整性。
比如银行转账:
-- a -> -100 ``UPDATE` `user` `set` `money = money - 100 ``WHERE` `name` `= ``'a'``; ` `-- b -> +100 ``UPDATE` `user` `set` `money = money + 100 ``WHERE` `name` `= ``'b'``;
在实际项目中,假设只有一条 SQL 语句执行成功,而另外一条执行失败了,就会出现数据前后不一致。
因此,在执行多条有关联 SQL 语句时,事务可能会要求这些 SQL 语句要么同时执行成功,要么就都执行失败。
6.2、如何控制事务 - COMMIT / ROLLBACK
在 MySQL 中,事务的自动提交状态默认是开启的。
-- 查询事务的自动提交状态 SELECT @@AUTOCOMMIT; +--------------+ | @@AUTOCOMMIT | +--------------+ | 1 | +--------------+
自动提交的作用:当我们执行一条 SQL 语句的时候,其产生的效果就会立即体现出来,且不能回滚。
什么是回滚?举个例子:
CREATE DATABASE bank; USE bank; CREATE TABLE user ( id INT PRIMARY KEY, name VARCHAR(20), money INT ); INSERT INTO user VALUES (1, 'a', 1000); SELECT * FROM user; +----+------+-------+ | id | name | money | +----+------+-------+ | 1 | a | 1000 | +----+------+-------+
可以看到,在执行插入语句后数据立刻生效,原因是 MySQL 中的事务自动将它提交到了数据库中。那么所谓回滚的意思就是,撤销执行过的所有 SQL 语句,使其回滚到最后一次提交数据时的状态。
在 MySQL 中使用 ROLLBACK 执行回滚:
-- 回滚到最后一次提交 ROLLBACK; SELECT * FROM user; +----+------+-------+ | id | name | money | +----+------+-------+ | 1 | a | 1000 | +----+------+-------+
由于所有执行过的 SQL 语句都已经被提交过了,所以数据并没有发生回滚。那如何让数据可以发生回滚
-- 关闭自动提交 SET AUTOCOMMIT = 0; -- 查询自动提交状态 SELECT @@AUTOCOMMIT; +--------------+ | @@AUTOCOMMIT | +--------------+ | 0 | +--------------+
将自动提交关闭后,测试数据回滚:
INSERT INTO user VALUES (2, 'b', 1000); -- 关闭 AUTOCOMMIT 后,数据的变化是在一张虚拟的临时数据表中展示, -- 发生变化的数据并没有真正插入到数据表中。 SELECT * FROM user; +----+------+-------+ | id | name | money | +----+------+-------+ | 1 | a | 1000 | | 2 | b | 1000 | +----+------+-------+ -- 数据表中的真实数据其实还是: +----+------+-------+ | id | name | money | +----+------+-------+ | 1 | a | 1000 | +----+------+-------+ -- 由于数据还没有真正提交,可以使用回滚 ROLLBACK; -- 再次查询 SELECT * FROM user; +----+------+-------+ | id | name | money | +----+------+-------+ | 1 | a | 1000 | +----+------+-------+
那如何将虚拟的数据真正提交到数据库中?使用 COMMIT :
INSERT INTO user VALUES (2, 'b', 1000); -- 手动提交数据(持久性), -- 将数据真正提交到数据库中,执行后不能再回滚提交过的数据。 COMMIT; -- 提交后测试回滚 ROLLBACK; -- 再次查询(回滚无效了) SELECT * FROM user; +----+------+-------+ | id | name | money | +----+------+-------+ | 1 | a | 1000 | | 2 | b | 1000 | +----+------+-------+
总结
自动提交
查看自动提交状态:
SELECT @@AUTOCOMMIT;设置自动提交状态:
SET AUTOCOMMIT = 0。
手动提交
@@AUTOCOMMIT = 0时,使用COMMIT命令提交事务。事务回滚
@@AUTOCOMMIT = 0时,使用ROLLBACK命令回滚事务。
7、索引
CodingLabs - MySQL索引背后的数据结构及算法原理 索引背后的数据结构及算法原理
MySQL官方对索引的定义为:索引(Index)是帮助MySQL高效获取数据的数据结构。
提取句子主干,就可以得到索引的本质:索引是数据结构。
7.1、索引的分类
在一个表中,主键索引只能有一个,唯一索引可以有多个
主键索引(PRIMARY KEY)
唯一的标识,主键不可重复,只能有一个列作为主键
唯一索引(UNIQUE KEY)
避免重复出现的列出现,唯一索引可以重复,多个列都可以标识为唯一索引
常规索引(KEY/INDEX)
全文索引(FullText)
MySQL优化-------看懂explain
【MySQL优化】——看懂explain_漫漫长途,终有回转;余味苦涩,终有回甘-CSDN博客_explain
7.2、索引原则
索引不是越多越好
不要对经常变动的数据添加索引
小数据量的表不需要加索引
索引一般加在常用来查询的字段上
8、权限管理和备份
8.1、用户管理
用户表所在目录在 mysql.user
-- 创建用户 CREATE `user` 用户名 IDENTIFIED BY '密码'
CREATE USER weixiaoru identified by '1234556';
-- 修改密码(修改当前用户密码)
set password = password ('123456')
-- 修改密码(修改自定用户密码)
set password for weixiaoru = password ('111111')
-- 给用户重命名
RENAME user weixiaoru to weixiaoru1
-- 用户授权(权限最高也不会超过root) 除了创建新的用户,其他权限都可以有
GRANT all privileges on *.* to sb -- 指定所有用户权限给某人(也就是特定的用户)
-- 查看权限
show grants for weixiaoru -- 查看指定用户的权限
show grant for [email protected]
-- 撤销权限revoke
revoke all privileges on *.* from weixiaoru -- 撤销weixiaoru这个用户的所有权限
-- 删除用户
drop user weixiaoru8.2、数据库备份
作用:1.就是为了保证重要的数据不丢失
2.数据转移
mysql备份的方式
这届拷贝物理文件
在Navicat这种可视化工具上面直接导出
使用命令行导出 mysql dump 在命令行使用
使用命令行导出的方法
必须要在管理员命令界面才可以完成
# mysql dump -h 主机 -u 用户名 -p 密码 数据库 表名 > 物理磁盘位置/文件名 (导出一张表) mysql dump -hlocalhost -uroot -p123456 school student >D:XXX/xXXX.sql 位置 # mysql dump -h 主机 -u 用户名 -p 密码 数据库 表名1 表2 表3 > 物理磁盘位置/文件名 (导出多张表,中间不适用逗号,直接空格) mysql dump -hlocalhost -uroot -p123456 school student >D:XXX/xXXX.sql 位置 #导入 #登录的情况下,切换到使用的数据库 source 备份文件的物理磁盘位置 source D:/a.sql
9、数据库设计
9.2、设计数据库的步骤:
分析需求:分析业务和需要处理的数据库的需求
用户表(用户登录、注销,用户的个人信息,写
概要设计:设计关系图E-R图
9.2、数据库三大范式
关系型数据库设计:三大范式的通俗理解 - 景寓6号 - 博客园 博客链接(关系型数据库三大范式详解)
三大范式
第一范式(1NF)
原子性:也就是保证每一列都不能再继续分
第二范式(2NF)
前提是:必须先满足第一范式
每张表只描述一件事情
第三范式(3NF)
前提:满足第一范式还有第二范式
第三范式需要确保数据表中的每一列数据都和主键直接相关,而不能间接相关
10、JDBC
10.1、数据库驱动
驱动:声卡、显卡、数据库
应用程序 ----------------->mysql 驱动------------------------->数据库
mysql驱动是有数据库厂商提供的
10.2、JDBC
sun公司为了简化开发人员的(对数据库的统一)操作,提供了一个(java操作数据库的)规范,速成JDBC
这些规范的实现由具体的厂商去做~
对于开发人员来说,我们只需要掌握JDBC接口的操作即可

10.3、第一个JDBC程序
创建测试数据库
CREATE DATABASE JDBC CHARACTER SET utf8 COLLATE utf8_general_ci; USE jdbc; CREATE TABLE users( id int PRIMARY KEY, `name` VARCHAR(40), `password` VARCHAR (40), `email` VARCHAR(100), birthdy DATE ); INSERT INTO users(id,`name`,`password`,`email`,birthday) VALUES (1,'zhangsan','123456','[email protected]','199-01-25'), (2,'lisi','123456','[email protected]','1996-08-25'), (3,'wangwu','123456','[email protected]','1997-10-01');
1.创建一个普通项目
2.导入数据库驱动
3.编写一个测试代码
package com.xiaoru.lesson01;
import com.mysql.cj.x.protobuf.MysqlxDatatypes;
import com.sun.xml.internal.bind.v2.runtime.output.StAXExStreamWriterOutput;
import java.sql.*;
//我的第一个jdbc程序
public class JdbcFirst {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//1.加载驱动
//DriverManager.registerDriver(new com.mysql.cj.jdbc.Driver());
Class.forName("com.mysql.cj.jdbc.Driver");
//2.用户信息和url
// useUnicode = true 设置可以使用中文
// &characterEncoding = utf8 设置中文字符集为utf-8
// &useSSl = true 设置使用安全的连接
String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode = true&characterEncoding = utf8&useSSl = true";
String username = "root";
String password = "weixiaoru";
//3.连接成功,数据库对象 Connection代表数据库
Connection connection = DriverManager.getConnection(url, username, password);
//4.执行SQL对象 Statement 执行SQL的对象
Statement statement = connection.createStatement();
//5.执行SQL的对象去执行SQL,可能存在结果,查看返回结果
String sql = "SELECT * from users";
ResultSet resultSet = statement.executeQuery(sql); // 返回结果集,结果集中封装所有我们要查询的结果
while (resultSet.next()){
System.out.println("id=" +resultSet.getObject("id"));
System.out.println("name+" +resultSet.getObject("name"));
System.out.println("password+" +resultSet.getObject("password"));
System.out.println("email+" +resultSet.getObject("email"));
System.out.println("birthday+" +resultSet.getObject("birthday"));
System.out.println("===================");
// System.out.println("resultSet.getObject(\"birthday\") = " + resultSet.getObject("birthday"));
}
//6.释放连接
resultSet.close();
statement.close();
connection.close();
}
}
步骤总结
1、加载驱动
2、用户信息和url
3、连接数据库DriverManger
4、获得执行的sql对象
5、执行SQL 获得返回的结果集
6、释放连接
DriverManager
//DriverManager.registerDriver(new com.mysql.cj.jdbc.Driver());
Class.forName("com.mysql.cj.jdbc.Driver"); //固定写法,加载驱动URL
String url = "jdbc:mysql://localhost:3306/jdbc? useUnicode = true&characterEncoding = utf8&useSSl = true"; //mysql 默认端口号就是3306 //oracle 默认端口号就是1521
statement执行SQL对象 preparStatement 执行SQL的对象
statement.executeQuery();//查询操作返回ResultSet statement.execute(); //执行任何SQL statement.executeUpate(); //更新、插入、删除。都是用这个,返回一个受影响的行数 statement.execute
ResultSet查询的结果集:封装了所有的查询结果
获得指定的数据类型
resultSet.getobject();//在不知道列类型的情况下使用 //如果知道列的指定类型就使用之指定的类型 resultSet.getString(); resultSet.getInt(); resultSet.getFloat(); resultSet.getDate(); ......
遍历,指针
resultSet.beforeFirst();//移动到最前面 resultSet.afterLast();//移动到最后面 resultSet.next();//移动到下一个 resultSet.previous();//移动到前一行 resultSet.absolute(row);//移动到指定行
释放资源
resultSet.close(); statement.close(); connection.close(); //因为这些意
10.4、statemant对象
JDBC中的statement对象用于向数据库发送SQL语句,想完成对于数据库的增删改查,只需要通过这个对象向数据库发送增删改查语句即可。
Statement对象的executeUpdata方法,用于向数据库发送增删改的SQL语句,executeUpdate执行完后,将会返回一个整数(即增删改语句导致了数据库几行数据发生了变化)。
Statement.executeQuery方法用于向数据库发送查询语句,executeQuery方法返回代表查询结果的ResultSet对象。
CRUD操作-creat 增------executeUpdate
使用executeUpdate(string sql)方法完成数据添加操作,示例操作:
Statement st = conn.createStatement();
String sql = "insert into user(...) values(.....) ";
int num = st.executeUpdate(sql);
if(num>0){
System.out.println("插入成功!!!");
}CRUD操作-delete 删------executeUpdate
使用executeUpdate(string sql)方法完成数据删除操作,示例操作:
Statement st = conn.createStatement();
String sql = "delete from user where id=1 ";
int num = st.executeUpdate(sql);
if(num>0){
System.out.println("插入成功!!!");
}CRUD操作-update 改------executeUpdate
使用executeUpdate(string sql)方法完成数据修改操作,示例操作:
Statement st = conn.createStatement();
String sql = "update user set name = '' where name = '' ";
int num = st.executeUpdate(sql);
if(num>0){
System.out.println("修改成功!!!");
}CRUD操作-read 查------executeQuery
使用executeQuery(string sql)方法完成数据查询操作,示例操作:
Statement st = conn.createStatement();
String sql = "select * from user where id = 1 ";
ResultSet = st.executeQuery(sql);
while(rs.next)({
//根据获取列的数据类型,分别调用rs的相应方法映射到java对象中
}代码实现增删改查
1、提取工具类
public class JdbcUtils {
private static String driver = null;
private static String url = null;
private static String username = null;
private static String password = null;
static {
try {
//获得类加载器,获得它的资源(返回一个输入流)
//1、加载一个输入流(配置)
InputStream in = JdbcUtils.class.getClassLoader().getResourceAsStream("db.properties");
//2、新建一个加载工具类
Properties properties = new Properties();
//3、使用这个类读取输入流
properties.load(in);
//4、获得配置的属性
driver = properties.getProperty("driver");
url = properties.getProperty("url");
username = properties.getProperty("username");
password = properties.getProperty("password");
//驱动只用加载一次
Class.forName(driver);
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
//获取连接
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(url, username, password);
}
//释放连接资源
public static void release(Connection conn, Statement st, ResultSet rs){
if (rs!=null){
try {
rs.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if (st != null){
try {
st.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if (conn != null){
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}2.编写增删改
//增加
package com.xiaoru.lesson02;
import com.xiaoru.lesson02.utils.JdbcUtils;
import org.omg.Messaging.SyncScopeHelper;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
public class TestInsert {
public static void main(String[] args) {
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try{
conn = JdbcUtils.getConnection();
st = conn.createStatement();
String sql = "INSERT INTO users(id , `name`,`password`,email,birthday)\n" +
"VALUES (4,'xiaohong','123456','[email protected]','2021-01-01')";
int i = st.executeUpdate(sql);
if (i>0){
System.out.println("插入成功!");
}
} catch (Exception e) {
e.printStackTrace();
}finally {
JdbcUtils.release(conn,st,rs);
}
}
}
//删除
package com.xiaoru.lesson02;
import com.xiaoru.lesson02.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
public class TestDelete {
public static void main(String[] args) {
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try{
conn = JdbcUtils.getConnection();
st = conn.createStatement();
String sql = "DELETE FROM users WHERE id = 4";
int i = st.executeUpdate(sql);
if (i>0){
System.out.println("删除成功!");
}
} catch (Exception e) {
e.printStackTrace();
}finally {
JdbcUtils.release(conn,st,rs);
}
}
}
//更新
package com.xiaoru.lesson02;
import com.xiaoru.lesson02.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
public class TestUpdate {
public static void main(String[] args) {
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try{
conn = JdbcUtils.getConnection();
st = conn.createStatement();
String sql = "UPDATE users SET `name` = 'zhangsan' where id = 1";
int i = st.executeUpdate(sql);
if (i>0){
System.out.println("更新成功!");
}
} catch (Exception e) {
e.printStackTrace();
}finally {
JdbcUtils.release(conn,st,rs);
}
}
}
//查找
package com.xiaoru.lesson02;
import com.xiaoru.lesson02.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class TestSelect {
public static void main(String[] args){
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try {
conn = JdbcUtils.getConnection(); //使用自己写的dbutiles类获取数据库连接
st = conn.createStatement(); //获得SQL执行对象
String sql = " select * from users ";
//执行SQL查询语句,接收返回的结果集
rs = st.executeQuery(sql);
while (rs.next()){
System.out.println(rs.getString("name"));
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
JdbcUtils.release(conn,st,rs);
}
}
}
SQL注入问题
sql存在漏洞,会被攻击导致数据泄露 存在SQL拼接漏洞
package com.xiaoru.lesson02.utils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class SQL注入 {
public static void main(String[] args) {
login("zhangsan","123456");//正常注入
// login(" 'or' 1=1"," 'or'1=1"); //非正常注入,存在SQL拼接漏洞
}
//登录业务
public static void login(String username,String password){
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try {
conn = JdbcUtils.getConnection(); //使用自己写的dbutiles类获取数据库连接
st = conn.createStatement(); //获得SQL执行对象
//sql SELECT * from users WHERE `name` = 'zhangsan' AND `password` = '123456'
// String sql = "select * from users where `name` = "+username;
String sql = "SELECT * from users WHERE `name` = '"+username+"' AND `password` = '"+password+"'";
//执行SQL查询语句,接收返回的结果集
rs = st.executeQuery(sql);
while (rs.next()){
System.out.println(rs.getString("name"));
System.out.println(rs.getString("password"));
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
JdbcUtils.release(conn,st,rs);
}
}
}
10.5、ProparedStatement 对象
ProparedStatement 可以防止SQL注入。效率更高
这两个都适用于增删改查,但是ProparedStatement 可以防止SQL注入的本质是,把传递进来的参数当作字符
假设其中存在转义字符,就直接会被忽略,会被直接转义(比如说‘ ‘)
1、增加
package com.xiaoru.lesson03;
import com.xiaoru.lesson02.utils.JdbcUtils;
import java.sql.*;
public class TestInsert {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement st = null;
ResultSet rs = null;
try {
conn = JdbcUtils.getConnection();
//区别
//使用? 占位符代替参数
String sql = "INSERT INTO users(id , `name`,`password`,`email`,`birthday`) values(?,?,?,?,?)";
st = conn.prepareStatement(sql); //预编译sql ,先写sql ,然后不执行
//手动给参数赋值
st.setInt(1,4);
st.setString(2,"zhaoliu");
st.setString(3,"123456");
st.setString(4,"[email protected]");
//注意点: sql.Date 数据库 Java.sql.Date()
// util.Date Java new Date().getTime() 获得时间戳
st.setString(5,"1999-12-25");
//执行
int i = st.executeUpdate();
if (i>0){
System.out.println("插入成功!");
}
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
JdbcUtils.release(conn,st,rs);
}
}
}2、删除
package com.xiaoru.lesson03;
import com.xiaoru.lesson02.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class TestDelete {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement st = null;
ResultSet rs = null;
try {
conn = JdbcUtils.getConnection();
//区别
//使用? 占位符代替参数
String sql = "DELETE FROM users WHERE id=? ";
st = conn.prepareStatement(sql); //预编译sql ,先写sql ,然后不执行
//手动给参数赋值
st.setInt(1,4);
//执行
int i = st.executeUpdate();
if (i>0){
System.out.println("删除成功!");
}
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
JdbcUtils.release(conn,st,rs);
}
}
}
3、更改
package com.xiaoru.lesson03;
import com.xiaoru.lesson02.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class TestUpdate {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement st = null;
ResultSet rs = null;
try {
conn = JdbcUtils.getConnection();
//区别
//使用? 占位符代替参数
String sql = "UPDATE users SET `name` =? WHERE `id` = ? ";
st = conn.prepareStatement(sql); //预编译sql ,先写sql ,然后不执行
//手动给参数赋值
st.setInt(2,1);
st.setString(1,"xiaoru");
//执行
int i = st.executeUpdate();
if (i>0){
System.out.println("更新成功!");
}
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
JdbcUtils.release(conn,st,rs);
}
}
}4、查找
package com.xiaoru.lesson03;
import com.xiaoru.lesson02.utils.JdbcUtils;
import jdk.nashorn.internal.objects.annotations.Where;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class TestSelect {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement st = null;
ResultSet rs = null;
try {
conn = JdbcUtils.getConnection();
//区别
//使用? 占位符代替参数
String sql = "select * from users where id = ?";
st = conn.prepareStatement(sql); //预编译sql ,先写sql ,然后不执行
//手动给参数赋值
st.setInt(1,1);
//执行
rs = st.executeQuery();
while (rs.next()){
System.out.println(rs.getString("name"));
System.out.println("password");
System.out.println("===============");
}
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
JdbcUtils.release(conn,st,rs);
}
}
}5、SQL注入
package com.xiaoru.lesson03;
import com.xiaoru.lesson02.utils.JdbcUtils;
import java.sql.*;
public class SQL注入 {
public static void main(String[] args) {
login("xiaoru","123456");
// login(" ' 'or1=1"," ' 'or1=1");
}
//登录业务
public static void login(String username,String password){
Connection conn = null;
PreparedStatement st = null;
ResultSet rs = null;
try {
conn = JdbcUtils.getConnection();
//PreparedStatement防止SQL注入的本质是,把传递进来的参数当作字符
//假设其中存在转义字符,就直接忽略,会被直接转义(比如说‘’)
String sql = "select * from users where `name` = ? and `password` = ?";
st = conn.prepareStatement(sql);
st.setString(1,username);
st.setString(2,password);
rs = st.executeQuery();
while (rs.next()){
System.out.println(rs.getString("name"));
System.out.println(rs.getString("password"));
}
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
JdbcUtils.release(conn,st,rs);
}
}
}10.6、使用idea连接数据库
10.7、事务
要么都成功要么都失败
ACID原则
原子性 要么都完成要么都不完成 可以理解原子的概念来理解
一致性
隔离性
持久性 一旦提交就不可逆,就持久到数据库了
隔离性的问题
脏读:就是读取了
不可重复读:
虚读(幻读):
代码实现
package com.xiaoru.lesson04;
import com.xiaoru.lesson02.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class TestTransaction {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement st = null;
ResultSet rs = null;
try {
conn = JdbcUtils.getConnection();
//关闭数据库的自我提交,就相当于开启事务
conn.setAutoCommit(false);//开启事务
String sql = "update account set money = `money`-100 where name ='A'";
st = conn.prepareStatement(sql);
st.executeUpdate();
String sql2 = "update account set money = `money`+100 where name ='B'";
st = conn.prepareStatement(sql2);
st.executeUpdate();
//业务完毕提交事务
conn.commit();
System.out.println("业务完毕,提交事务");
} catch (SQLException throwables) {
try {
conn.rollback();//如果失败就回滚事务
} catch (SQLException e) {
e.printStackTrace();
}
throwables.printStackTrace();
} finally {
JdbcUtils.release(conn,st,rs);
}
}
}10.8、数据库连接池
什么是连接池
数据库连接池是负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个。
池化技术:准备一些预先的资源,过来就连接预先准备好的
常用连接数 10个
最小俩内书可以按照常用连接数来确定
最大连接数 15个
等待超时:100ms
编写连接池,实现一个接口 DataSource
使用了这些数据库连接池之后,我们在项目开发中就不需要编写连接数据库的代码了!
连接池
开源数据源实现(拿来即用)
DBCP
C3P0
Druid
DBCP
package com.xiaoru.Lesson05.utils;
import org.apache.commons.dbcp2.BasicDataSourceFactory;
import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
public class JdbcUtils_DBCP {
private static DataSource dataSource = null;
static {
try {
InputStream in = JdbcUtils_DBCP.class.getClassLoader().getResourceAsStream("com/dbcpconfig.properties");
Properties properties = new Properties();
System.out.println(in);
properties.load(in);
//创建数据源 工厂模式 -->创建
dataSource = BasicDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
e.printStackTrace();
}
}
//获取连接
public static Connection getConnection() throws SQLException {
return dataSource.getConnection(); //从数据源中获取连接
}
//释放连接
public static void release(Connection conn, Statement st , ResultSet rs){
if(rs != null){
try {
rs.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if ( st != null){
try {
st.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if ( conn != null){
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}C3P0
结论:无论大家是用什么数据源,本质还是一样的,datasourse接口不会变
1、为什么要使用连接池
使用连接池乐意节省内存,提高了服务器地服务效率,能够支持更多的客户服务。通过使用连接池,将打打提高程序运行效率,同时,我们可以通过其自身的管理机制来见识数据库连接的数量、使用情况等
2、连接池的工作原理
连接池的建立
连接池中连接的使用管理
连接池的关闭
第一、连接池的建立
一般在系统初始化时,连接池会根据系统配置建立,并在池中创建了几个连接对象,以便使用时能从连接池中胡后勤。连接池的连接不能随意创建和关闭,这样避免了连接随意创建和关闭,这样避免了随意建立和关闭造成的系统开销。
第二、连接池的管理
连接池中如果有控线连接,则将连接诶分配给客户使用
第三、连接池的关闭

java String 类
trim()方法用于删除字符串的头尾空白符
java页面弹窗弹框的使用
11、String、StringBuffer与StringBuilder之间区别
| String | StringBuffer | StringBulider |
|---|---|---|
| Stringde的值是不可变得,这就导致每次对String的操作都会生成新的String对象,不仅效率低下,而且浪费大量的优先内存空间 | StringBuffer是可变类,和线程安全的字符串操作类,任何对他指向的字符串的操作都不会产生新的对象。每个StringBuffer对象都有一定的缓冲区容量,当字符串大小没有超过容量时,不会分配新的容量,当字符串大小超过容量时,会自动增加容量 | 可变类,速度更快 |
| 不可变对象 | 可变对象 | 可变对象 |
| 线程安全 | 线程不安全 | |
| 多线程操作字符串 | 单线程操作字符串 |
11.1、String——String字符串常量类
String类型最大的区别其实在于 String是不可变对象,因此在每次对String类型进项改变的时候其实都等同于生成了一个新的String对象,然后将指针指向新的String对象,这样不仅效率低下,而且大量浪费有限的内存空间,所以经常改变内容的字符串最好·不要用String。因为每次生成对象都会对系统性能产生影响,特别当内存无引用对象多了以后,JVM的GC(垃圾回收机制)就会开始工作,那速度一定会相当慢的。

我们可以看到,初始String值为“hello”,然后在这个字符串后面加上新的字符串“world”,这个过程是需要重新在栈堆内存中开辟内存空间的,最终得到了“hello world”字符串也相应的需要开辟内存空间,这样短短的两个字符串,却需要开辟三次内存空间,不得不说这是对内存空间的极大浪费。为了应对经常性的字符串相关的操作,就需要使用Java提供的其他两个操作字符串的类——StringBuffer类和StringBuild类来对此种变化字符串进行处理。
11.2、StringBuffer和StringBuilder类 ——StringBuffer、StringBuilder字符串变量
StringBuffer字符串变量(线程安全)
StringBuilder字符串变量(非线程安全)
StringBuilder字符串常量。如果要频繁对字符串内容进行修改,处于效率最好使用StringBuffer,如果想转成String类型,可以调用StringBuffer的toString()方法
StringBuffer 上的主要操作是 append 和 insert 方法,可重载这些方法,以接受任意类型的数据。每个方法都能有效地将给定的数据转换成字符串,然后将该字符串的字符追加或插入到字符串缓冲区中。
append 方法始终将这些字符添加到缓冲区的末端;
insert 方法则在指定的点添加字符
StringBuilder:字符串变量(非线程安全)。在内部,StringBuilder 对象被当作是一个包含字符序列的变长数组。
11.3、三者之间的区别
1.三者在执行速度方面的比较:StringBuilder>StringBuffer>String
2.String <(StringBuffer,StringBuilder)的原因
String:字符串常量
StringBuffer:字符串变量
StringBuilder:字符串变量
从上面的名字可以看到,String是“字符创常量”,也就是不可改变的对象。对于这句话的理解你可能会产生这样一个疑问 ,比如这段代码:
1 String s = "abcd"; 2 s = s+1; 3 System.out.print(s);// result : abcd1
我们明明就是改变了String型的变量s的,为什么说是没有改变呢? 其实这是一种欺骗,JVM是这样解析这段代码的:首先创建对象s,赋予一个abcd,然后再创建一个新的对象s用来 执行第二行代码,也就是说我们之前对象s并没有变化,所以我们说String类型是不可改变的对象了,由于这种机制,每当用String操作字符串时,实际上是在不断的创建新的对象,而原来的对象就会变为垃圾被GC回收掉,可想而知这样执行效率会有多底。
而StringBuffer与StringBuilder就不一样了,他们是字符串变量,是可改变的对象,每当我们用它们对字符串做操作时,实际上是在一个对象上操作的,这样就不会像String一样创建一些而外的对象进行操作了,当然速度就快了。
3.一个特殊的例子:
1 String str = “This is only a” + “ simple” + “ test”; 3 StringBuffer builder = new StringBuilder(“This is only a”).append(“ simple”).append(“ test”);
你会很惊讶的发现,生成str对象的速度简直太快了,而这个时候StringBuffer居然速度上根本一点都不占优势。其实这是JVM的一个把戏,实际上:
String str = “This is only a” + “ simple” + “test”;
其实就是:
String str = “This is only a simple test”;
所以不需要太多的时间了。但大家这里要注意的是,如果你的字符串是来自另外的String对象的话,速度就没那么快了,譬如:
String str2 = “This is only a”;
String str3 = “ simple”;
String str4 = “ test”;
String str1 = str2 +str3 + str4;
这时候JVM会规规矩矩的按照原来的方式去做。
4. StringBuilder与 StringBuffer
StringBuilder:线程非安全的
StringBuffer:线程安全的
当我们在字符串缓冲去被多个线程使用是,JVM不能保证StringBuilder的操作是安全的,虽然他的速度最快,但是可以保证StringBuffer是可以正确操作的。当然大多数情况下就是我们是在单线程下进行的操作,所以大多数情况下是建议用StringBuilder而不用StringBuffer的,就是速度的原因。
5、初始化上的区别,String可以空赋值,后者不行,报错
//String String s = null; String s = “abc”; //StringBuffer StringBuffer s = null; //结果警告:Null pointer access: The variable result can only be null at this location StringBuffer s = new StringBuffer();//StringBuffer对象是一个空的对象 StringBuffer s = new StringBuffer(“abc”);//创建带有内容的StringBuffer对象,对象的内容就是字符串”
12、java各种集合以及其区别
集合类型主要有3种:set(集)、list(列表)和map(映射)
集合接口分为:Collection和Map,List、Set实现了Collection接口
12.1、vector
vector可以实现可增长的对象数组。与数组一样,他可以包含可以使用证书索引进项访问的组件。不过vector的大小是可以增加或者减小的。以便使用创建vector后进行添加或者删除操作

vector的继承关系

vector继承于AbstractList,实现了List、randomAcess、Cloneable、Serializable等接口
(1) vector 继承了AbstractList,实现了List接口
(2)Vector实现了RandomAccess接口,即提供了随机访问功能。
(3)Vector 实现了Cloneable接口,即实现克隆功能。
(4)Vector 实现Serializable接口,表示支持序列化。
源码分析Vector
(1)构造方法
vector的构造方法一共有四个,因为
第一个: 创建一个空的Vector,并且指定了Vector的初始容量为10

第二个:创建一个空的Vector,并且指定了Vector的初始容量

第三个:创建一个空的Vector,并且指定了Vector的初始容量和扩容时的增长系数

第四个:根据其他集合来创建一个非空的Vector

第四个需要解释一下,首先是把其他集合转化为数组,然后复制粘贴到Vector里面。
(2)增加元素
增加元素有两个主要的方法,第一个是在Vector尾部追加,第二个是在指定位置插入元素。
第一个:在Vector尾部追加元素

我们再进来看一下ensureCapacityHelper(elementCount + 1)是如何实现的。

现在相当于真正扩容的方法是grow方法,别着急我们再进来看看。

在这一步我们扩容的时候首先就要排除一些异常的情况,首先就是capacityIncrement(需要增加的数量)是否大于0,如果大于0直接增加这么多。然后发现增加了上面那些还不够那就扩充为实际需要minCapacity的大小。最后发现还不够,就只能扩充到虚拟机能表示的数字最大值了。
第二个:在指定位置增加元素
这个就比较简单了。我们直接看源码就能看明白

(3)删除元素
删除元素时候同样也有两种方法,第一个根据元素值来删除,第二个根据下表来删除元素。
第一个:根据元素值来删除元素

我们发现删除元素其实是调用了removeElement()方法来删除元素的,没关系不要嫌麻烦,进入这个方法内部看一下。

到了这一步,我们又发现,执行删除操作的还不是removeElement()方法,而是removeElementAt(i),我们再进入这个方法看看。

到了这个方法我们其实可以分析一下,要删除元素要移动大量的元素,时间效率肯定是不好的。毕竟Vector是通过数组来实现的,而不是通过链表。
第二个:删除指定位置的元素
删除指定位置的元素就比较简单了,我们到指定的位置进行删除就好了,但是同样需要把后面的元素进行移位。

(3)更改元素
更改元素我们就先看一个吧。这个在大部分场景下一般不用(大部分,根据自己业务来定)。

(4)查找元素
查找元素我们给出三个,第一个查询Vector容器中是否包含某个元素,第二个查询第一次出现的指定元素的索引,第三个最后一次出现的指定元素的索引。
第一个:查询Vector容器中是否包含某个元素

我们发现,查询Vector是否包含某个元素时候,其实是调用了第二个方法,那我们直接就看第二个
第二个:查询第一次出现的指定元素的索引

第三个:查询最后一次出现的指定元素的索引

1)线程安全:
从上面的构造方法还有增删改查的操作其实我们都发现了,都有这么一个synchronized关键字,就是这个关键字为Vector容器提供了一个安全机制,保证了线程安全。
2)构造方法:
Vector实际上是通过一个数组去保存数据的。当我们构造Vecotr时;使用默认构造函数,默认容量大小是10。
3)增加元素:
当Vector容量不足以容纳全部元素时,Vector的容量会增加。若容量增加系数 大于0,则将容量的值增加“容量增加系数”;否则,将容量大小增加一倍。
4)克隆:
Vector的克隆函数,即是将全部元素克隆到一个数组中。
(5)遍历
不过到这可还没结束,还有重要的一点我们还没说,那就是遍历。其实在我之前的文章介绍ArrayList时候已经提到过了,遍历方式也就那么几种,既然Vector是基于数组实现的,那么遍历方式肯定也是随机访问最快。在这里代码演示几个:

三、Vector与其他容器的区别
源码看完了,对于Vector的实现,我相信你也基本上明白其内部实现了,下面就看看他和别的容器的区别,在文章一开始我们就提到了Vector其实基本上和ArrayList一样的,下面对比分下一下:
ArrayList是线程非安全的,这很明显,因为ArrayList中所有的方法都不是同步的,在并发下一定会出现线程安全问题。另一个方法就是Vector,它是ArrayList的线程安全版本,其实现90%和ArrayList都完全一样,区别在于:
1、Vector是线程安全的,ArrayList是线程非安全的
2、Vector可以指定增长因子,如果该增长因子指定了,那么扩容的时候会每次新的数组大小会在原数组的大小基础上加上增长因子;如果不指定增长因子,那么就给原数组大小*2,源代码是这样的:
public ResultSet list(Connection conn ,BookType bookType) throws SQLException {
conn = Dbutil.getConnection();
StringBuffer sb = new StringBuffer("select * from t_booktype");
if (StringUtil.isNotEmpty()){
sb.append(" and typeName like '% "+bookType.getTypeName()+" %'");
}else {
JOptionPane.showMessageDialog(null,"查询为空");
}
// System.out.println();
st=conn.prepareStatement(sb.toString().replaceFirst("and","where"));
return st.executeQuery();
}13、int和integer的区别
1.integer是int的包装类,int则是java的一种基本数据类型
2、integer变量必须实例化后才能使用,而int变量不需要
3、integer实际是对象的引用,当new一个integer时,实际上生成一个指针指向此对象;而int则是直接存储数据值
4、integer的默认值是null,int的默认值是0
关于Integer和int的比较
1、由于integer变量实际上是对一个integer对象的引用,所以两个通过new生成的integer 变量永远是不相等的(因为new生成的是两个对象,其内存地址不同)
Integer i = new Integer(100); Integer j = new Integer(100); system.out.print(i == j); // fasle
2、Integer变量和int变量比较时,只要两个变量的值是相等的,则结果为true(因为包装类Integer和基本数据类型int比较时,java会自动拆包装为int,然后进行比较,实际就变为两个int变量的比较)
Integer i = new Integer(100); int j = 100; System.out.print(i == j); //true
3、非new生成的Integer变量和new Integer()生成的变量比较时,结果为false。(因为 ①当变量值在-128~127之间时,非new生成的Integer变量指向的是java常量池中的对象,而new Integer()生成的变量指向堆中新建的对象,两者在内存中的地址不同;②当变量值在-128~127之间时,非new生成Integer变量时,java API中最终会按照new Integer(i)进行处理(参考下面第4条),最终两个Interger的地址同样是不相同的
Integer i = new Integer(100); Integer j = 100; System.out.print(i == j); //false
4、对于两个非new生成的Integer对象,进行比较时,如果两个变量的值在区间-128到127之间,则比较结果为true,如果两个变量的值不在此区间,则比较结果为false
Integer i = 100; Integer j = 100; System.out.print(i == j); //true
Integer i = 128; Integer j = 128; System.out.print(i == j); //false
对于第4条的原因: java在编译Integer i = 100 ;时,会翻译成为Integer i = Integer.valueOf(100);,而java API中对Integer类型的valueOf的定义如下:
public static Integer valueOf(int i){
assert IntegerCache.high >= 127;
if (i >= IntegerCache.low && i <= IntegerCache.high){
return IntegerCache.cache[i + (-IntegerCache.low)];
}
return new Integer(i);
}java对于-128到127之间的数,会进行缓存,Integer i = 127时,会将127进行缓存,下次再写Integer j = 127时,就会直接从缓存中取,就不会new了
边栏推荐
猜你喜欢

Cut out web icons through PS 2021

最新,每天填坑,Jeston TX1 精卫填坑,第一步:刷机

Problems when yolov5 calls ip camera

String comparison size in MySQL (date string comparison problem)

化学试剂磷脂-聚乙二醇-羟基,DSPE-PEG-OH,DSPE-PEG-Hydroxyl,MW:5000

如何查看一个现有的keil工程之前由什么版本的keil IDE编译

Usage of JOIN in MySQL

Chapter 10 Clustering

DSPE-PEG-Silane,DSPE-PEG-SIL,磷脂-聚乙二醇-硅烷修饰活性基团

Phospholipid-polyethylene glycol-thiol, DSPE-PEG-Thiol, DSPE-PEG-SH, MW: 5000
随机推荐
针对简历上的问题
3分钟带你了解微信小程序开发
DSPE-PEG-PDP,DSPE-PEG-OPSS,磷脂-聚乙二醇-巯基吡啶供应,MW:5000
PCL—点云数据分割
meime模块
DSPE-PEG-PDP, DSPE-PEG-OPSS, phospholipid-polyethylene glycol-mercaptopyridine supply, MW: 5000
化学试剂磷脂-聚乙二醇-羟基,DSPE-PEG-OH,DSPE-PEG-Hydroxyl,MW:5000
C语言中关于2的n次方求值问题(移位运算)
IndexError: only integers, slices (`:`), ellipsis (`...`), numpy.newaxis (`None`) and integer or boo
知识工程作业2:知识工程相关领域介绍
SOCKS5
Amazon sellers how to improve the conversion
oracle inner join and outer join
ModuleNotFoundError No module named 'xxx' possible solutions
MySQL分组后取最大一条数据【最优解】
活体检测 Adaptive Normalized Representation Learning for GeneralizableFace Anti-Spoofing 阅读笔记
subprocess.CalledProcessError: Command 'pip install 'thop'' returned non-zero exit status 1.
Deveco studio 鸿蒙app访问网络详细过程(js)
A senior test engineer asked me these questions as soon as the interview came
ImportError: libGL.so.1: cannot open shared object file: No such file or directory