MySQL数据库,JDBC接口,MyBatis框架等,掌握的数据的存放和管理。
Java数据库开发基础,介绍MySQL数据库、JDBC操作数据库、C3P0数据库连接池,Java反射等内容,进行油画商城开发。

3.1.1 MySQL基础之数据类型

MySQL数据库的安装、数据类型。
MySQL数据库内容分两部分介绍:


MySQL安装:www.mysql.com。

MySQL属于关系型数据库,MySQL是按照数据结构来组织、存储和管理数据的仓库。


ALTER USER ‘root’@‘localhost’ IDENTIFIED WITH mysql_native_password BY ‘156354’;

数据库管理系统是一种操纵和管理数据库的大型软件,用于建立、使用和维护数据库,简称 DBMS。它对数据库进行统一的管理和控制,以保证数据库的安全性和完整性。应用开发工具是使用数据库的软件,比如说用户管理系统,说是系统,其实是管理数据库的软件。数据库系统是由数据库和管理软件组成的系统以及数据管理员组成。
在help命令后的命令都是标准命令描述,需要大写,提示信息。
my.ini是mySQL的配置文件。登录: mysql -uroot -p或mysql -uroot -p加上密码。;退出:exit或quit或\q。获得版本号: mysql -V 或mysql --version。登陆的同时打开指定的数据库:mysql -uroot -p密码 -D db_name。显示现有的库:SHOW DATABASES/SCHEMAS。查看打开的数据库:SELECT DATABASE();。命令行结束符默认是;或\g,如SELECT DATABASE();。可以通过help或\h或?加上相关关键字来查看手册\c可以取消当前命令的执行
常用SQL语句:select user()得到登陆的用户。select version()得到mysql的版本信息。select now()得到当前的日期时间。select database()得到当前打开的数据库。查看上一步的错误、警告和通知信息:SHOW WARNINGS;。
SQL语句语法规范
常用MySQL的关键字需要大写,库名、表名、字段等使用小写SQL语句支持折行操作,拆分时不能把完整的单词拆开。数据库名称、表名称、字段名称不要使用MySQL的保留字,如果必须使用,需要使用反引号``将其括起来。
关闭严格模式:1.查看模式:select @@sql_mode; 2.关闭严格模式:set GLOBAL sql_mode=’ ‘;
数据库相关操作
创建数据库:CREATE DATABASE/SCHEMA db_name;(数据库名称最好有意义,名称不要包含特殊字符或MySQL关键字)。查看当前服务器下的全部数据库:SHOW DATABASES/SCHEMAS;。检测数据库名称是否存在,如果不存在则进行创建:CREATE DATABASE IF NOT EXISTS db_name;。创建数据库的同时制定编码方式:CREATE DATABASE IF NOT EXISTS test3 [DEFAULT] CHARACTER SET ‘UTF-8’;。修改指定数据库的编码方式:ALTER DATABASE db_name DEFAULT CHARACTER SET [=] charset;。打开指定数据库:USE db_name;。得到当前打开的数据库:SELECT DATABASE();。删除指定的数据库:DROP DATABASE db_name;。如果数据库存在则删除:DROP DATABASE IF EXISTS db_name;。查看指定数据库的详细信息:SHOW CREATE DATABASE db_name;。SHOW TABLES是显示当前数据库中所有表的名称。
mysql 注释: #注释 或者 --注释。-- 注释(–与注释内容之间必须加空格)。
每个数据表中至少有一列,行可以有零行或多行来组成。在表刚刚创建,表中还没有存储数据的时候,我们认为数据表是“零行”。而列则代表了字段,表中至少含有一个字段才可以创建。
数据表是数据库最重要的组成部分之一,数据保存在数据表中。数据表由行(row)和列(column)来组成。表名要求唯一,不要包含特殊字符,最好含义明确。
创建表:CRETAE TABLE IF NOT EXISTS tbl_name(字段名称 字段类型[完整性约束条件],字段名称 字段类型[完整性约束条件],. . . )ENGINE=存储引擎 CHARSET=编码方式;
MySQL中的数据类型
1、数值型:整数型、浮点数、定点数。2、字符串类型。3、日期时间类型。
USE 是选择数据库的命令,ALERT 是删除,添加或修改字段时使用的命令。查看user数据表结构的命令是 SHOW COLUMNS FROM user;
整数型

浮点数和定点数(decimal):
在 mysql中float、double是浮点数,decimal是定点数。decimal是严格按照指定的精度进行四舍五入的,而float和double则是系统自动进行了四舍五入,不可控。并且使用decimal这个类型在进行四舍五入时会产生警告,而float和double都不会产生警告。浮点数相对于定点数的优点:在长度一定的情况下,浮点数能够表示更大的数据范围。缺点:会引起精度问题,也就是存在误差。所以对货币(银行业务、买卖商品、工资)等对精度敏感的数据,应该用decimal定点数表示或存储。而对精度要求不高,数据范围要求更大的,可以使用浮点数float、double。DECIMAL和DOUBLE一样,内部以字符串形式存储数值。

字符串型

VARCHAR举例,如果存储 4个字节的数据,还需要一个字节用于记录存储的数据长度,所以实际长度为5,即L+1。实际占用的存储空间只可能是L+1个字节或者L+2个字节。
日期时间类型

定点数可以理解为数据以字符串的形式来存进数据库的,保证了精确性浮点的存储方式是采用:符号位+阶码+尾数的形式。区别如下:(1)浮点数存在表示误差,定点数采用字符串进行存储,精度高 。(2)对货币等精度敏感的数据,应该采用定点数进行存储 。
ENUM和SET都是比较特殊的字符串数据列类型。ENUM和SET的主要区别是:ENUM只能取单值,它的数据列表是一个枚举集合。SET可取多值。它的合法取值列表最多允许有64个成员。空字符串也是一个合法的SET值。
VARCHAR(M)是一种比CHAR更加灵活的数据类型,同样用于表示字符数据,但是VARCHAR可以保存可变长度的字符串。其中M代表该数据类型所允许保存的字符串的最大长度,也就是说VARCHAR(M)中的M表示允许保存的字符串长度。比如 VARCHAR(20) 则表示最大允许存入的字符长度为20。
命令窗口点击右键,可粘贴。
int和UNSIGNED都是用来描述这个数据的类型的,不能分开。写约束的时候只要是描述同一个特征的关键字不要分开,就不会出错。默认值不是创建完表就有,是你插入一条数据时,如果某个字段没有赋值,它的值为默认值。
完整性约束条件
unsigned无符号,没有负数,从0开始。zerofill零填充,当数据显示长度不够的时候可以使用前补0的效果填充至指定长度。NOT NULL非空约束,插入值的时候这个字段必须要给值。
DEFAULT默认值,如果插入值的时候没有给字段赋值,则使用默认值。PRIMARY KEY主键,标识记录的唯一性,值不能重复,一个表只能有一个主键,自动禁止为空。UNIQUE KEY唯一性,一个表中可以有多个字段是唯一索引,同样的值不能重复,但是NULL除外。AUTO_INCREMENT自动增长,只能用于数值列,而且配合索引所有。FOREIGN KEY外键约束。
表中插入值
INSERT INTO tb_name(id,username,…) VALUES(1,‘KING’,…);
查询表中所有记录:SELECT * FROM tb_name;是指所有的字段,使用这条sql语句可以把表格中的所有字段的数据都查询出来。
MySQL中自动编号的关键字是AUTO_INCREMENT。

查询当前 MySQL 的模式
select @@sql_mode;
取消严格模式
set global sql_mode=‘ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION’;
set session sql_mode=‘ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION’;
无符号unsigned约束不能为负数,零填充ZEROFILL 不足位数前面补0。零填充默认也是无符号。
DECIMAL(M,D)类型,M为数字的总位数,其范围为1~65位。D为小数点后面的位数,其范围是0~30,不得超过M。而Float类型,它最多保留7位小数。Double类型,它最多保留15位左右的小数。DECIMAL类型,它最多保留30位左右的小数,所以它的精度最高,如果后面保留的小数多,要求精度比较高,则选择DECIMAL类型。decimal[(M,D)]默认保存精度是整数。
TEXT在检索过程中是不区分大小写转换的,也就是检索过程中,大小写是不转换的,区分大小写的,和搜索内容的时候是区分大小写的表达的意思是一致的。TEXT列不能有默认值。
CHAR类型的检索速度比VARCHAR块,但VARCHAR比CHAR节省空间。CHAR默认存储数据的时候,后面会用空格填充到指定长度,只有手动在前面加空格,显示的时候才会看见前面有空格。而在检索的时候会去掉后面的空格;VARCHAR在保存的时候不进行填充,尾部的空格会留下;
SELECT CONCAT(’
’,‘a’,’’),CONCAT(’’,‘b’,’*’) FROM test_str 连接字符串。
set通过数字插入时,set的每个选项值对应一个数字,依次是1,2,4,8,16…,最多有64个选项
set如果想要添加多个字符,则可以使用逗号分隔,也可以使用多个选项的数字之和(比如:1+2+4=7),就会把索引值为1,2,4 的三个选项插入进去。
枚举和集合在插入数据时不区分大小写。因为ENUM的字段值不区分大小写,并且mysql字段的值默认也是不区分大小写的
ENUM和SET类型都是集合类型,不同的是ENUM类型最多可枚举65535个元素,而SET类型最多枚举64个元素。并且ENUM每次只能插入所列举的单个字符,在开发中可根据这些特性来决定具体的使用情况。比如 爱好的字段可以使用SET类型,性别的内容使用ENUM类型。
set集合类型插入时可以插入多个值,插入的值可以不用按照集合的顺序插入,但是集合会把他们按顺序保存。集合也可以根据序号插入。序号从1开始(1、2、4)。枚举也可以设置对应的序号,序号从1开始(1、2、3),超出长度则报错。枚举类型会自动过滤掉空格。
TIME

DATE:

YEAR:

打开严格模式:可以在cmd中使用如下sql设置mysql为严格模式:set session sql_mode = ‘ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION’;
或者修改my.ini配置文件,设置sql_mode为:sql_mode = ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,
TIME:HH:MM:SS 形式,占3字节。DATE:占3字节 YYYY-MM-DD形式,如果YYYY部分写的是7799,则自动转换成19701999,如果写的是0069,则自动转换成20002069,占3字节。DATETIME:YYYY-MM-DD HH:mm:DD形式,占8字节TIMESTAMP:占3字节插入CURRENT_TIMESTAMP或NULL或什么也不写,都会得到当前日期和时间。YEAR存储年份(范围19012155),占1字节,如果YYYY部分写的是7799,则自动转换成19701999,如果写的是0069,则自动转换成2000~2069。
PRIMARY KEY:
1.
2.

3.


单列主键和复合主键都是用来标识数据库中某条数据的唯一性。复合主键通常用在关系表中。比如权限表。具体是否要使用和实际的业务场景结合的。一个表中使用什么主键,是很灵活的,具体还是要和业务结合的。
主键:主键的作用就是唯一标识表中的某一行数据。索引:索引的作用就是提高数据的检索速度。他们的关系是:主键一定是索引,但是索引不一定是主键。一个表只能有一个主键或联合主键,但是可以有多个索引
在数据库中,索引是对数据库表中一列或多列的值进行排序的一种存储结构,相当于图书的目录,使用索引可以提高检索速度。
复合主键:PRIMARY KEY(id,courseId)。他们两个共同定位到一条记录,两个必须同时相同才代表重复记录。
AUTO_INCREMENT 自增标志。* 默认起始值为1,每次增长1。* 一个表中只有一个自增的列。* 自增必须是索引列。* 已有的最大值 + 1。
自增:1、必须要配合主键索引使用。2、key可以放前面可以放后面,UNSIGNED不能放后面。3、自增默认从1开始,每次加1,AUTO_INCREMENT约束的字段设置为NULL或者DEFAULT都是默认加一, ''会报错。
字段a,字段b都约束了唯一性。但是它们是独立的。只是a字段的值不能重复,b字段的值也不能重复。他们没有关系。
NOT NULL非空约束,插入值的时候值不能为空值。DEFAULT设置默认值 若没用指定值,则使用默认值。UNIQUE KEY:唯一索引,值不能重复,NULL除外。
COMMENT关键字是给字段添加注释。格式如下:

注意:使用命令的形式只在当前窗口生效。
为了区分MySQL的保留字与普通字符而引入的符号。一般建表时都会将表名,库名都加上反引号来保证语句的执行度

3.1.2 MySQL基础之表的管理

介绍MySQL数据库的表的管理及常用存储引擎。
SELECT:是用来查询数据库中数据条目的,ALTER:修改数据表名或者修改数据表字段。
add,alter,drop是DDL语句,DDL语句是对表结构的修改,比如:给表添加一个字段,修改表字段的类型,删除表等。insert,update,delete是DML语句,DML语句是对表数据的修改,比如:向表中插入一条数据,修改表中的数据,删除一条数据等。
表结构相关操作
1、添加字段:ALTER TABLE tb_name ADD 字段名称 字段属性[完整性约束条件][FIRST(将某个字段加到起始位置)|AFTER字段名称];添加多个字段用”,”分隔。2、删除字段:ALTER TABLE tb_name DROP 字段名称;可以同时进行添加删除字段操作.
删除数据表中列的操作语句为ALTER TABLE tbl_name DROP col_name 和 ALTER TABLE tbl_name DROP COLUMN col_name。
添加多列的语句为 ALTER TABLE tbl_name ADD [COLUMN] (col_name col_definition,…)。
SQL语句不区分大小写,所以大写也是可以的
添加与删除默认值
添加:ALTER TABLE tdl_name ALTER 字段名称 SET DEFAULT默认值;
删除:ALTER TABLE tbl_name ALTER 字段名称 DROP DEFAULT。
字段属性varchar的字段需指定长度。
分布式系统可以理解成将一个大的系统拆分成很多子系统,每个系统都可以独立开发和运行。使用分布式系统的好处之一是可以进行负载均衡。
字段属性与完整性约束条件是一样的。只是说法不一样。如果要修改索引,需要先删除原来的,然后重新创建
修改字段类型、字段属性:ALTER TABLE tb_name MODIFY 字段名称 字段类型[字段属性][FIRST|AFTER 字段名称]。修改字段名称、字段类型、字段属性:ALTER TABLE tb_name CHANGE 原字段名称 新字段名称 字段类型[字段属性][FIRST|AFTER 字段名称]。
如果原字段的字段属性/完整性约束条件的是否为空是NOT NULL则修改字段的字段属性一定要加上NOT NULL,不加会使原字段的是否为空变成NULL。
column_definition是字段类型的意思。[FIRST|AFTER col_name]表示字段的位置。
drop是删除表,数据库等的操作。只是修改id字段的属性,应该使用modify或者change
change 每次使用,用change不可以只修改字段属性,需要把新字段和旧字段都写上, 即使字段名没有更改,也要重写一次。
无论是普通索引还是唯一索引或者复合索引,统称为索引唯一索引:在索引的基础上添加了唯一的特点。复合索引:在索引的基础上添加了多个字段组成一个索引的特点。以上两个都是在索引的基础上添加了一些其它的特点,从而起了一个更加具体的名字来描述这个索引。如果一个索引没有添加一些其它特点,那么就是一个普通索引。创建时和下面的语句基本相同,去掉额外的特征就可以,比如:ALTER TABLE table_name ADD INDEX index_name ( column ) 。索引名默认是字段名
添加主键:ALTER TABLE tb_name ADD PRIMARY KEY(字段名称)。删除主键:ALTER TABLE tb_name DROP PRIMARY KEY;(如果主键带有自增属性,必须先去除自增才能删除主键)。添加唯一/索引:ALTER TABLE tb_name ADD UNIQUE KEY|INDEX index_name;删除唯一/索引:ALTER TABLE tb_name DROP INDEX index_name;
如果这个索引定义时是这种格式INDEX(columnA, columnB)索引,就是联合索引,对于联合/复合索引,Mysql从左到右的使用索引中的字段,一个查询可以只使用索引中的一部份,但只能是最左侧部分。例如索引是index (a,b,c),可以支持a | a,b | a,b,c 3种组合进行查找,但不支持 b,c或c进行查找 。复合主键和复合索引不是一个概念
重命名表的操作 修改数据表名称: ALTER TABLE tb_name RENAME [TO|AS] new _tb_name; 或RENAME TABLE tb_name TO new_tb_name;

在mysql8.0中,.frm文件变成了图里的.sdi文件,这是8.0的新特性,在8.0版本中用sdi文件来描述数据库的信息。
查看my.ini时配置文件中是否有 datadir目录,例如:datadir=F:\mysql-5.7.26-winx64\data
如果有如上的配置,可以再到cmd窗口切换到mysql安装程序的bin目录,运行如下命令
mysqld --initialize-insecure --user=mysql。data文件夹就自动创建好了。
mysql默认建表的存储引擎是InnoDB存储引擎。mysql5.5之前存储引擎默认是MyISAM存储引擎,会产生3个文件 .frm表结构文件 .MYD数据文件 .MYI索引文件。可以在创建表的时候指定数据文件和索引文件的存储位置,只有MyISAM表支持。DATA DIRECORY [=] 数据保存的绝对路径。INDEX DIRECTORY [=] 索引文件保存的绝对路径。MyISAM单表最大支持的数据量位2的64次方条记录。每个表最多可以建立64个索引。如果是复合索引,每个复合索引最多包含16个列,索引值最大长度是1000B。MyISAM引擎存储格式定长(FIXED 静态)是指字段中不包含VARCHAR/TEXT /BLOB 静态格式最简单最安全的一种格式,假如出现数据崩溃了,它也是最快恢复的,同样查找数据的方式也是最快的动态(DYNAMIC)只要字段中包含了VARCHAR/TEXT/BLOB。设置为静态存储格式,固定了字段的长度,但是有时候使用varchar等更省空间。压缩(COMPRESSED)myisampack创建。在创建数据表时,可以在ENGINE参数后添加 ROW_FORMAT=FIXED/DYNAMIC进行格式化,设置FIXED(静态)或者DYNAMIC(动态)。查看表存储格式是否定长/动态:SHOW TABLE STATUS LIKE ‘table_name’\G。
InnoDB存储引擎
1、设计遵循ACID模型,支持事务,具有从服务崩溃中恢复的能力,能够最大限度保护用户的数据。原子性(Atomiocity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability);
2、支持行级锁,可以提升多用户并发时的读写性能;3、支持外键,保证数据的一致性和完整性;4、拥有自己独立的缓冲池,常用的数据和索引都存在缓存中;5、对于INSERT、UPDATE、DELETE操作,使用一种change buffering的机制来自动优化,还可以提供一致性的读,并且还能够缓存变更的数据,减少磁盘I/O,提高性能。6、创建InnoDB表之后会产生两个文件:①.frm表结构文件②.ibd,数据和索引存储空间中。mysql8创建Innodb引擎的表是只生成一个文件的。7、所有的表都需要创建主键,最好配合上AUTO_INCRAMENT,也可以放到经常查询的列作为主键。查询效率低于MyISAM

3.1.3 MySQL基础之数据管理

MySQL数据库中数据的增删改查、多表联查等内容
SELECT * FROM 表名,是查询表中的数据,DESC 表名,是查询表的结构,SHOW CREATE TABLE 表明,查询表的详细信息
数据管理之插入数据
VALUES是可以插入多条记录的,而VALUE只能插入一条记录(mysql8也可插入多条记录)。
1、不指定字段名称INSERT tbl_name VALUE(值,…)。2、指定字段名称INSERT tbl_name (字段名称,…) VALUES (值,…)。3、插入多条INSERT tbl_name (字段名称,…) VALUES (值,…),(值,…),(值,…);。4、INSERT… SET…语法INSERT tbl_name SET 字段名称=值,字段名称=值,…;5、INSERT…SELECT…:INSERT tb1_name (字段名称,…)SELECT (字段名称,…) FROM tb2_name WHERE 条件;
如果为自动编号的字段赋值的话,我们可以采用NULL或DEFAULT让其按照默认的递增的形式来实现。给有默认值的字段赋值时,我们可以用DEFAULT让其采用默认值
修改记录 UPDATE tbl_name SET 字段名称=值,字段名称=值[WHERER 条件],如果不添加条件,整个表中的记录都会被更新。删除记录 DELETE FROM tbl_name[WHERE条件],如果不添加条件,表中的所有记录都会被删除。DELETE 清空数据表的时候不会重置AUTO_INCREMENT的值,可以通过ALTER语句将其重置为1,ALTER TABLE tbl_name AUTO_INCREMENT=1;彻底清空数据表 TRUNCATE[TABLE] tbl_name;(1)清空表中所有记录(2)会重置AUTO_INCREMENT的值
不指定tinyint长度默认是3,你不指定int的长度默认是10。
查询记录

SELECT select_expr,... FROM tb_name[WHERE 条件][GROP BY{col_name|position} HAVING 二次筛选][ORDER BY {col_name|position|expr}[ASC|DESC]][LIMIT 限制结果采集的显示条数]。
1、SELECT * FROM tb_name查询表中的所有记录。2、SELECT 字段名称,... FROM tb_name。
3、SECECT 字段名称,... FROM db_name.tb_name;不用打开数据库就能查询指定数据表。5、SELECT 字段名称[AS] 别名名称,... FROM db_name.tb_name;给字段起别名。6、给数据表起别名:SELECT 字段名称,... FROM tb_name AS 别名;。7、表名.字段名的形式:SELECT tb_name.字段名称,... FROM tb_name;。
查询表达式中的顺序可以和原数据表中字段的顺序不一致且SELECT中查询表达式的顺序将影响着结果的顺序。
在mysql语句中<>在where条件中表示不等于,<=>在where条件中表示等于(可检测NULL值,”=”不能检测NULL值)。
对于增删改查以及模糊查询中,在sql语句的语法上是不区分大小写的,但在字段值的内容上是区分大小写的。
记录操作——WHERE条件筛选记录
检测NULL值,不能用WHERE userDesc=NULL的方式检查NULL值,要用WHERE userDesc<=>NULL的方式。还可以用[NOT] IS NULL检测NULL值,SELECT id,username,age,userDesc FROM user1 WHERE userDesc IS NULL;(2)指定范围,...WHERE age BETWEEN 18 AND 30;(3)指定集合,SELECT id,username,age FROM user1 WHERE id [NOT] IN(1,3,5,7,9);(4)逻辑运算符,...WHERE sex='男' AND age>=20;...WHERE id=1 OR username='queen';(5)匹配字符(配合通配符使用),[NOT] LIKE(默认忽略大小写),通配符:%代表任意长度的字符串;_代表任意一个字符.模糊查询:SELECT 字段名 FROM 表名 WHERE 字段名 LIKE '%_'。

SELECT 字段名 FROM 表名 WHERE 字段名 LIKE ‘%_’。
<=>在where条件中表示等于(可检测NULL值,”=”不能检测NULL值)
查询记录:GROUP BY分组:把值相同放到一个组中,最终查询出的结果只会显示组中一条记录。1、分组配合GROUP_CONCAT()查看组中某个字段的详细信息。2、配合聚合函数使用:COUNT()统计记录总数(如果写的是COUNT(字段名称),字段中的值为NULL,则不统计进来,如果写的是COUNT()会统计NULL值)、SUM()求和、MAX()求最大值、MIN()求最小值、AVG()求平均值,如SELECT COUNT() FROM user1;3、配合WITH ROLLUP关键字:会在记录末尾添加一条记录,是上面所有记录的总和;4、HAVING字句对分组结果进行二次筛选 如:HAVING 条件。
用HAVING进行分组条件的指定时,一定要保证分组条件要么为聚合函数,要么条件中的字段必须出现在当前的SELECT语句中。简单来说就是having子句可以对分组结果进行二次筛选。
having 和where是结合条件表达式的操作,order by 为排序操作,group by为分组操作。
给字段取别名和给表取别名用法一样,as可省掉
WITH ROLLUP\G将结果按列打印的作用。
ORDER BY排序:SELECT 字段名称 FROM tbl_name ORDER BY 字段名称 ASC(升序,默认)|DESC(降序)。按多个字段排序:SELECT id,username,age FROM user1 ORDER BY age ASC, id ASC;age按升序排列,在age值相同时按id号进行升序排列,若age值没有相同的则id不进行升序排列。SELECT RAND() ;–产生一个随机数(0到1之间的一个随机数)。
ORDER BY RAND();随机记录/随机排序
为什么按照随机数函数RAND()排序,就会打乱顺序?RAND()生成一个随机数,使用ORDER BY RAND(),这样每次检索的结果排序会不同,是mysql底层设计。
Atom中安装autocomplete-sql插件可自动补全。如下:选择File->Settings,选择Install,搜索autocomplete-sql,点击install安装。
mysql是不支持在子查询中使用limit分页查询的,所以需要再嵌套一层。
可搜索mysql题库练习语句。
查询记录:LIMIT限制结果集显示条数:1、LIMIT值:显示结果集的前几条记录。
2、LIMIT offset,row_count从offset开始,显示几条记录,偏移量offset从0开始。
INSERT…SELECT可以将查询结果插入到指定数据表。如:将学生表student中的stuname列的前5条记录插入到选课表course中的username中,INSERT course(username) SELECT stuname FROM student LIMIT 5;
where条件判断与内连接的查询结果是一样的
多表查询:1、笛卡尔积的形式:SELECT emp.id, emp.username, emp.age, dep.depName FROM emp, dep;。2、内连接(常用,内连接会查出符合两个表中连接条件的记录,是交集部分)的形式:查询两个表中符合连接条件的记录:SELECT 字段名称,… FROM tb_name1 INNER JOIN tb_name2 ON 连接条件;INNER 可以省略。3、外连接的形式:左外连接:SELECT 字段名称,… FROM tb_name1 LEFT OUTER JOIN tb_name2 ON 条件;先显示左表中的全部记录,再去右表中查询符合条件的记录,不符合的以NULL代替。右外连接:SELECT 字段名称,… FROM tb_name1 RIGHT OUTER JOIN tb_name2 ON 条件;先显示右表中的全部记录,再去左表中查询符合条件的记录,不符合的以NULL代替。OUTER可以省略。关键字LEFT左边的那个表(这里是e)为主表,右边的表(这里是d)为从表;关键字RIGHT右边的那个表(这里是d)为主表,左边的表(这里是e)为从表。内连接与外连接区别
内连接查询结果不包含NULL结果,外连接查询结果会包含NULL,没有的值以NULL补充。
内连接查询表中符合连接条件的记录,左外连接查询时根据主表条件将副表中的记录查出。
起了别名后必须使用别名的,因为用了别名的意思相当于舍弃了原有的名字。原来的表名就会无效
atom当中写sql语句,关键字显示颜色,可装language-sql-mysql插件,选择Settings中的Install,再Install。
外键约束
1.只有INNODB存储引擎支持外键,2.创建外键两种方式:一、建表时指定外键:[CONSTRAINT 外键名称] FOREIGN KEY 子表(字段名称) REFERENCES 主表(字段名称)。(CONSTRAINT 外键名称)可选可不选,不加创建外键时,自动起外键名称。
外键字段必须和主表的主键字段类型要相似,如果是数值型要求一致,并且无符号也要一致,如果是字符型,要求类型一致,长度可以不同。如果外键字段没有创建索引,MySQL会自动添加索引。子表的外键关联的必须是父表的主键。要想保证数据的一致性和完整性,就必须要用到外键,外键字段是依赖于已存在表的一个主键,所以一定要先有主表。如果父表中有与子表相关联的记录,不能更新或删除父表中的相关联的记录,要删除主表(父表),需要先删除子表。二、动态创建/删除外键
外键约束的参照操作:①CASCADE从父表进行删除或更新,子表也跟着删除或更新,级联的操作②SET NULL从父表删除或更新记录,并且设置子表的外键列为NULL③NO ACTION|RESTRIC拒绝对父表做更新或删除操作。
②动态删除外键:ALTER TABLE tb_name DROP FOREIGN KEY fk_name;
③动态添加外键:ALTER TABLE tb_name ADD [CONSTRAINT 外键名称] FOREIGN KEY(外键字段) REFERENCES 主表(主键字段);动态添加外键之前表中的记录一定是合法的记录,没有脏值,否则外键添加不会成功。
特殊形式的查询
1–子查询 SELECT 字段名称 FROM tbl_name WHERE col_name =(SELECT col_name FROM tbl_name)内层查询的结果可作为外层的条件。
子查询(必须要放在括号里),SELECT 字段名称 FROM tbl_name WHERE col_name =(SELECT col_name FROM tbl_name),内层查询的结果可作为外层的条件。1、由IN引发的子查询:SELECT * FROM emp WHERE depId IN (SELECT id FROM dep);。2、由NOT IN 引发的子查询:SELECT * FROM emp WHERE depId NOT IN (SELECT id FROM dep);。3、由比较运算符引发的子查询:SELECT id,username,score,FROM stu WHERE score>=(SELECT score FROM level WHERE id=1);。4、由EXISTS引发的子查询:EXISTS后面的SELECT语句返回一个布尔类型,若后面的值不存在前面的语句不执行,若存在,则执行(EXISTS 后面的语句返回的BOOLEAN值,是是否执行前面语句的条件),SELECT * FROM emp WHERE EXISTS (SELECT depName FROM dep WHERE id=10);。
带有ANY SOME ALL 关键字查询:
SELECT * FROM stu WHERE score>=ANY(SELECT score FROM level);ANY跟SOME意义相同,
SELECT * FROM stu WHERE score>=SOME(SELECT score FROM level);,
SELECT * FROM stu WHERE score>=ALL(SELECT score FROM level);

运算符<>是不等于,等同于!=。
使用[NOT] IN 的子查询中,NOT IN与 !=ALL或<>ALL运算符等效。

INSERT … SELECT可以将查询结果插入到指定数据表中,CREATE … SELECT:创建数据表的同时把另外一个表中的数据导入进来。
CREATE TABLE newtb_name LIKE oldtb_name;创建一个跟旧数据表结构相同的新数据表。
SELECT DISTINCT(字段名称) FROM tb_name;查询的列表中的不显示重复字段项
。INSERT…SET一次只能插入一条记录,可以使用子查询;INSERT…VALUES一次可以插入多条记录,不可以使用子查询。
2–联合查询(合并两个表):
UNION:SELECT 字段名称,… FROM tb_name1 UNION SELECT 字段名称,… FROM tb_name2;查询两个表中的重复项不显示。UNION ALL:SELECT 字段名称,… FROM tb_name1 UNION ALL SELECT 字段名称,… FROM tb_name2;直接合并两个表中的记录。
3–自身连接查询:
无限极分类的实现形式,-- 查询所有的分类信息,并且得到其父分类:
SELECT s.id,s.cateName AS sCateName,p.cateName AS pCateName
FROM cate AS s
LEFT JOIN cate AS p 主表是s 根据s的pID去找id
ON s.pId=p.id;
– 查询所有的分类及其子分类:
SELECT p.id,p.cateName AS pCateName,s.cateName AS sCateName
FROM cate AS s
RIGHT JOIN cate AS p 主表是p 根据p的id去找pId
ON s.pId=p.id;
– 查询所有的分类并且得到子分类的数目:
SELECT p.id,p.cateName AS pCateName,COUNT(s.cateName) AS count
FROM cate AS s
RIGHT JOIN cate AS p
ON s.pId=p.id
GROUP BY p.cateName
ORDER BY id ASC;。

3.1.4 MySQL基础之常用函数

介绍MySQL数据库中的常用函数。
MYSQL常用函数:
数字函数
SELECT CEIL(x)返回大于x的最小整数(进一取整);SELECT FLOOR(x)返回小于x的最大整数(去一取整);SELECT ROUND()四舍五入;SELECT TRUNCATE(3.456123987,3)取小数点后三位,直接截断;SELECT MOD(5,2)5对2取余;SELECT ABS()求绝对值;SELECT POWER(2,3)2的3次方;SELECT PI()得到圆周率;SELECT RAND()产生随机数;SELECT SIGN()如果括号中是整数,返回1,如果是负数返回-1,如果是0返回0;SELECT EXP(2)e的2次方;
数据库中数学函数的使用% 和MOD 都可以用于取余数。
字符串函数
CHAR_LENGTH(s);得到字符串的字符数;得到字符串的长度:LENGTH(s);合并字符串:CONCAT(s1,s2,…)将字符串合并成一个字符串,如果字符串中包含NULL返回的拼接结果就是NULL;
以指定的分隔符拼接字符串:CONCAT_WS(x,s1,s2,s3);将字符串转换为大写:UPPER(s)|UCASE(s);将字符串转换为小写:LOWER(s)|LCASE(s);反转字符串:REVERSE(s);返回字符串的前几个或后几个字符:LEFT(s,n),RIGHT(s,n);用字符串填充到指定长度:LPAD(s(原字符串),n(长度),s1(用来填充的字符串))(左端填充)RPAD(s,n,s1)(右端填充);去掉字符串两端的空格:TRIM()|LTRIM()|RTRIM();重复指定的次数:REPEAT(s(字符串),n(重复次数));
字符串替换:REPLACE(s(原字符串),s1(要被替换的字符串),s2(用来替换的字符串));
截取字符串:SUBSTRING(s(原字符串),n1(起始点,从1开始),n2(截取几位));比较字符串:STRCMP(s1,s2)如果第一个字符串大于第二个字符串返回1,小于返回-1,等于返回0;
FORMAT() 函数作用是数字格式化。SELECT FORMAT(10002554.333,1);第一个参数是要修改的,第二个是规定的格式。并且千分位是标准格式,不用特殊设置。

日期时间函数
返回当前时间:CURDATE()|CURRENT_TIME();返回当前的日期时间:NOW(),CURRENT_TIMESTAMP(),SYSDATE();返回日期中的月份:MONTH(月份);返回月份名称:MONTHNAME(月份);返回星期几:DAYNAME(时间);返回一周内的第几天:DAYOF WEEK(时间);返回第几个星期:WEEK(时间);计算两个日期相差的天数:DATEDIFF(第一个日期,第二个日期)第一个减第二个;DATE_FORMAT函数将月份和日期截取出来。当date字段为表示时间的字段,格式为:‘YYYY-MM-DD’,只截取月份和日期,可以写成:DATE_FORMAT(date,’%m-%d’)。":"也可以.
其他常用函数
SELECT VERSION()得到当前版本;SELECT CONNECTION_ID()得到当前连接数,每个连接都有一个在数据库中唯一的ID;SELECT DATABASE()或者SCHEMA();得到当前打开的数据库;SELECT USER(),CURRENT_USER(),SYSTEM_USER(),SESSION_USER()得到当前用户;SELECT LAST_INSERT_ID()得到上一步插入操作产生的AUTO_INCREMENT的值;SELECT MD5(‘king’)加密函数PASSWORD(‘root’)密码加密算法添加用户和系统用户使用的加密算法是PASSWORD,只能使用PASSWORD而不能使用MD5来添加用户的密码。USER() :以utf8字符集中的字符串形式返回当前的MySQL用户名和主机名。
在mysql中sql语句可以用分号或者\G来结尾,而\G表示 go的意思。\G也就是go的缩写。默认情况下,mysql的查询结果是横向输出的,第一行是列头,后面是记录,如果长的话就会很乱。mysql中,在sql语句后面加\G表示将查询结果按列打印。
MySQL也可在一台机器上装服务端,这台机器叫服务器。其他用户可在另外的电脑上,通过客户端连接到MySQL,有多少客户端连接MySQL服务器,这些客户端的数量就叫服务器连接数。
mysql 5.7.9以后废弃了password字段和password()函数。可以使用MD5或者SHA加密,官方文档如下https://dev.mysql.com/doc/refman/8.0/en/encryption-functions.html#function_password。
使用GROUP BY时报错,由于默认的 MySQL 配置中 sql_mode 配置了 only_full_group_by,需要 GROUP BY 中包含所有 在 SELECT 中出现的字段。因此需要在 MySQL 的配置中去掉这个配置。两种方式可以修改:1.修改配置文件(永久起效)mysql.ini,在[mysqld]下面手动添加sql_mode的方式强制指定不需要ONLY_FULL_GROUP_BY属性,添加代码:sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,如果重启mysql服务器后设置的sql_mode不起效建议通过管理员运行cmd使用如下命令重启mysql服务再试试:net stop mysql ,net start mysql。.2.可以通过下边的SQL语句查看并修改一下(重启mysql服务器失效):select @@sql_mode; set GLOBAL sql_mode=’ '; 第一条是查看数据设置的模式,第二条是关闭该模式。
mysql数据库的关闭,并不是说在cmd中登录数据库,然后使用quit退出后,就是关闭数据库;而是在系统服务中关闭数据库服务或者使用关闭数据库的命令来关闭。系统服务关闭方法:方式一.系统计算机–管理–服务–找到MySQL。方式二:任务管理器–服务–找到MySQL。
使用关闭数据库的命令:cmd–net stop mysql。开启mysql数据库的命令:cmd中–net start mysql。
图形化工具Workbench使用:

https://dev.mysql.com/downloads/workbench/。

3.1.5 JDBC基础

介绍Java数据库开发的重点JDBC,包括API详解,增删改查操作的实现,以及使用数据库连接池C3P0以提高执行效率。
内容:


JDBC的全称为:Java DataBase Connectivity(java数据库连接),【可对多种数据库进行统一操作,不需要对单个数据库的驱动进行详细了解】,【仅需要了解 JDBC 的规范即可】 - 具体驱动会具体实现相应功能。
JDBC基础:
JDBC开发步骤:




在成员方法上方添加@Test注解引入JUnit相关jar包,此时成员方法就可像主方法一样使用,即不用在主方法中调用成员方法就可直接执行成员方法。
Junit是作用于单个方法的测试,相对main方法来说,对于模块化的测试的效率更高,因为在main方法中测试的话需要加载其他所有关联的方法,增加了代码量,而使用Junit则只需要为需要测试的方法添加标签就可以对目标方法进行测试。Junit单元测试工具,进行测试运行方法。
当有多个@Test注解,并不按照方法的书写顺序执行,如果你想让它按照顺序执行,可以用 @Before 和 @After 来设置一下。将光标定位放在某个方法名处那么就只会执行此方法。
junit中的有一些使用的限定规范–>.测试方法必须使用 public void 修饰,而且不能带有任何参数。 所以不建议在@Test方法中添加static,对应属性也不建议使用static修饰。
JUnit是一个Java语言的单元测试框架。JUnit4是它的一个jar包。JUnit4和JUnit5的区别在于两个jar包版本不同。使用了@Test注解在方法之上的作用是,对该方法进行测试。在idea中可以自动导入JUnit的jar包,这也是idea的优势之一。
具体实现步骤:

DriverManager类中getConnection()方法的参数。第一个参数是数据库url地址,格式是jdbc:mysql://MySQL服务器ip地址:端口号/数据库名,端口号必须要写。第二个和第三个参数分别是数据库的用户名和密码。
数据库驱动的jar包可在如下网址中下载:https://mvnrepository.com/artifact/mysql/mysql-connector-java/8.0.11。
mysql8需要使用com.mysql.cj.jdbc.Driver驱动包。注意使用如下形式配置驱动:

高版本的mysql的数据库url地址书写:jdbc:mysql://localhost:3306/databasename?useSSL=false&serverTimezone=Hongkong&userUnicode=true&characterEncoding=utf-8。
userSSL=false:在高版本的数据库需要指明是否进行SSL连接,所谓SSL链接就是表示是为网络通信提供安全及数据完整性的一种安全协议。所以添加了这个设置。serverTimezone=Hongkong:高版本的数据库中如果不设置时区,会由于数据库的时间不正确而导致报错。useUnicode=true&characterEncoding=utf-8:主要用来指定编码格式。
JDBC的API:
1.DriverManager驱动管理类:

Class.forName() 是根据类名加载类的实例对象,不是获取类名。
2.Connection对象是JDBC程序与数据库连接的一个对象:

数据库存储过程的实质就是部署在数据库端的一组定义代码以及SQL。将常用的或很复杂的工作,预先用SQL语句写好并用一个指定的名称存储起来,那么以后要叫数据库提供与已定义好的存储过程的功能相同的服务时,只需调用execute,即可自动完成命令。
3.Statement对象执行SQL:

execute()执行所有的sql,包括增删改查操作。如果是查询语句select,则返回true,否则返回false。所以execute()方法可以看成是executeQuery()和executeUpdate()方法执行范围的和,但要注意它们的返回结果的含义是不同的,executeQuery()和executeUpdate()方法更常用。
Statement :执行sql。
主要作用:一、执行sql,
boolean execute(String sql) 执行sql,执行select返回true,反之返回false。
ResultSet executeQuery(String sql) 执行sql中select语句。
int executeUpdate(String sql) 执行sql中的update,insert,delete语句,返回影响条数。
二、执行批处理,
addBatch(String sql) 添加到批处理。executeBacth(String sql) 执行批处理。clearBacth(String sql) 清空批处理。
4.ResultSet对象,结果集:

boolean next();最开始是0行,第一次判断第一行有无,判断是否有下一行的记录,如果有就指向下一行。ResultSet光标最初位于结果集第一行的前面,调用next()方法后才移到第一行,当调用next()方法返回值为false时,说明光标位于最后一行之后。
对于提取数据表的枚举类型ENUM和集合类型SET的数据,直接使用getString()方法,进行获取就可以了。
获取数据的方法中的参数columnIndex列序号/columnLabel列名,一般写列名,因为列序号会跟随sql语句顺序变化。
JDBC的资源释放:


mysql服务器设置了最大连接数。宕机,计算机术语,口语简单把停掉机器叫做down机,转换为汉字是“宕机”也可理解为 “电脑死机了”。具体是指操作系统无法从一个严重系统错误中恢复过来,或系统硬件层面出问题,以致系统长时间无响应,而不得不重新启动计算机的现象。它属于电脑运作的一种正常现象,任何电脑都会出现这种情况。
在finally块的代码(对应的try-catch块无论是否发生异常,finally块代码一定执行)中正确释放资源:

JDBC的CRUD操作:

stmt.executeUpdate(sql);-------->返回的是int,多少条记录受影响。不为零,就证明起作用了。
JDBC的工具类的抽取:

将JDBC的加载驱动,获得数据库连接,还有数据库资源的释放放在工具类的静态方法中。
静态代码块的作用可以让在类加载的时候就会执行静态代码块儿中的代码,所以,如果有需要初始化一些代码的时候,可以写在静态代码块儿中。
1、静态方法:静态方法可以在类加载的时候就会执行方法体的代码。所以有如果有需要初始化一些代码的时候,可以写在静态方法中,这样在类加载的时候,就会执行方法中的代码了。2、驱动的加载只需要一次,这样每次直接调用这个方法就可以直接调用加载好的驱动类。3、使用静态方法的好处:一是方便调用,可以直接使用 工具类.方法名 来使用的。二是因为访问时不需要创建对象,也就节约了内存资源。一般在实际开发中,工具类的编写也都需要使用静态方法。
局部变量在使用前必须初始化,引用数据类型对象置为null。全局变量定义后都有默认值,引用数据类型对象默认值是null,基本数据类型变量是0,0.0等。
利用属性文件存放工具类JDBCUtils的参数,是一个很好的方案。当参数发生变化了,可直接在属性文件里修改参数,而不用在源代码中修改,能很好地提高开发效率。
properties配置文件信息,文件后缀为“.properties”,属文本文件,文件的内容格式是“键=值”的格式。
jdbc.properties文件要放在src目录下,而不是放在包下。

用类的加载器的方式获取属性文件的输入流(通过文件输入流的方式只适合桌面程序不适合web程序,因为web程序发布到服务器,文件地址会发生改变。):
JDBCUtils.class是创建一个JDBCUtils的Class对象,Class对象就是某个类的字节码对应的类,关于这里的这个语句JDBCUtils.class.getClassLoader().getResourceAsStream()的理解,可以参考以下思路:JDBCUtils.class是创建一个JDBCUtils的Class对象。Class的getClassLoader() 是返回类加载器,JDBCUtils.class.getClassLoader()就是获取JDBCUtils类的类加载器,也就是ClassLoader对象。ClassLoader的getResourceAsStream()是返回读取指定资源的输入流。
综上所述:JDBCUtils.class.getClassLoader().getResourceAsStream(“jdbc.properties”)是返回一个读取指定资源的输入流。ClassLoader.getSystemResourceAsStream(“jdbc.properties”);跟上述代码功能一样,都可以用来获取指定的资源的输入流。
JDBC的SQL注入漏洞:



aaa和111并不是数据库的密码,而是数据库中user表中的数据。
bug产生的原因就是因为在登录文本框的用户名位置输入演示的aaa’ or '1=1这样的内容(注意这里是sql语句,=号不是赋值的意思,而是比较的意思。),这个内容作为字符串拼接到sql语句中以后,只要用户名正确,无论密码是什么,where的判断条件都是true,都可以登录成功。为什么where语句判断条件为true,因为or和and一起使用时会先执行and,再执行or。无论and的执行结果是否为true,or前面的表达式username='aaa’都为true(因为用户名是对的),那么where语句的条件成立,这样即使密码不正确也可以登录成功。
MySQL中 – 表示注释,注意–与后边内容之间要有空格,在各个环境中表现的不同(在cmd中,–和后边内容没有空格,会将–当成sql语句执行,如果sql语句不正确,将会报错。在workbench中,–和后边内容没有空格,会提示错误,在Atom中,–和后边内容没有空格,也可以表示注释,但是Atom中不能执行sql语句。)。MySQL中关系型运算符AND的优先级大于OR的优先级,所以会先判断AND后判断OR。
cmd执行sql语句时,必须以分号结尾,表示sql语句结束。而在java代码中,sql可以不加分号,在执行具体的sql时会自动添加。在workbench中,如果只是一句sql语句,没有分号,也是可以的。
SQL注入的漏洞的产生原因是知道用户名,然后输入用户名时附带输入了sql的关键字,OR或 – ,从而对sql语句的逻辑做出错误解析;
JDBC的SQL注入漏洞的解决:

这里只是表示通过connection对象调用preparedStatement()方法,并不是通过类调用。

对于占位符?,表名、字段名是不允许用问号占位,占位符一般都是放在条件的后面,或者设置字段值的位置。Statement每执行一次sql就会编译一次,Preparestatement对sql编译之后,会给要传入的参数留一个位置。执行时不会对sql(相同结构的sql只编译一次)再进行编译了。即使参数不同,多执行几次也不会在编译了。
为了防止SQL注入漏洞,应该尽量避免使用动态拼装的SQL,应该采用预编译的方式(PreparedStatement接口的实例对象);可以对用户登录框的信息进行正则校验,从而可以避免一些不当的操作;SQL注入漏洞就是通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。
SQL注入漏洞的解决:利用PreparedStatement接口的实例对象,原有的SQL语句是字符串拼接(若字符串有mysql关键则会干扰sql语句),而PreparedStatement 是用占位符 ?的形式,固定SQL的形式,让后续传入的变量都为字符串,无论是不是mysql中的关键字。
PreparedStatement的使用:
prepardStatemen可以存储预编译SQL语句,编译好后,只往里添参数就好,而statement 每次执行都需要把字符串编译成sql语句。如果要执行的sql语句次数比较多的时候,用prepardStatemen会比statement 执行的效率很多。
预编译SQL的使用:预编译SQL的占位符可以代替字段数据,但是不能代替子查询语句。
PreparedStatement对象中setDate()方法没有时分秒,使用setTimestamp()方法有时分秒。
同时ResultSet对象中使用getTimestamp()方法获取时间。\t 表示制表符。当前面的输出内容位数为8的倍数,\t将输出8个空格。当前面的输出内容位数不是8的倍数,\t将补足8位。
数据库连接池:

特点:用数据库连接池时,不需要再临时创建到数据库的连接,而是直接去使用某个容器或者地址中创建好的connection,用完后归还,从而提高程序的执行效率。常用的连接池有 : DPCP、C3P0。
应用程序直接获取连接的缺点:

连接池:

C3P0连接池:
C3P0连接池的使用:
手动设置连接池:

配置文件设置连接池:
可用xml或properties文件配置,xml配置文件的名称必须为c3p0-config.xml底层会自动去根目录读取这个名称的c3p0连接池配置文件。

c3p0连接池的工具类代码实现:

c3p0连接池的代码实现:

ctrl+shift+o进行导包操作。
关于c3p0的使用,希望后面学习的朋友们可以在配置的时候少走弯路。1. c3p0连接池需要搭配另外一个jar包使用。:mchange-commons-java-0.2.3.4.jar。2. c3p0-0.9.2.1.jar 搭配 mchange-commons-java-0.2.3.4.jar。3.最新版本的c3p0-0.9.5.2.jar 搭配 mchange-commons-java-0.2.11.jar。
第二条对应资源 :链接:https://pan.baidu.com/s/1-vMp-TwOGWjHGnEry29dKg提取码:bq1w。
C3P0数据库连接池对象的获取,可以通过ComboPooledDataSource获取数据库连接池的对象。
xml中多个参数连接&要用&amp; 转义一下,其他的properties文件和xml文件可以用同一种的。

3.1.6 Java反射

反射是常用的知识点。主要介绍反射的概念和常用的API
Java的反射机制:
内容:

反射的概述:

反射是运行过程中对自身的操作,编译的时候是生成这个类的class文件对象,并不是这个对象。通过反射来生成对象。


反射就是不通过new关键字,在运行时动态的获取信息或者动态的调用对象方法,new对象是在类加载过程中分配内存。java中反射是在运行过程中动态的加载进入。有个很大的好处就是可以节省很多资源。通俗地说,反射机制就是可以把一个类,类的成员(函数,属性),当成一个对象来操作。也就是说:类,类的成员,在运行的时候还可以动态地去操作他们。可以用于:数据库JDBC中通过Class.forName(Driver).来获得数据库连接驱动。分析类文件:能得到类中的方法等等。反射机制的作用:编写一些通用性较高的代码或者框架的时候使用。
访问一些不能访问的变量或属性:破解别人代码。比如在前面的JDBC中:

这就是一个简单的通过反射的方法加载Driver类中的内容。对应上面的new Driver()就是通过new关键字(非反射)来加载Driver类中的内容。
new和反射用处区别:new是静态的,反射是动态的,主要是用来动态创建类的实例。比如说有一些框架(或者说通用的代码),我们写入一个类,框架就会自动为我们实例化对象,但是写框架的人并不知道我们会创建什么样的类,这个时候他就需要写反射机制 ,在用户创建新类运行的时候动态的去加载,用new的话就不行。比如:在JDBC入门课程中在JDBC的工具类JDBCUtils中用类的加载器的方式获取JDBC的属性文件jdbc.properties运用了反射机制,用类的加载器的方式获取属性文件的输入流(通过文件输入流的方式只适合桌面程序不适合web程序,因为web程序发布到服务器,文件地址会发生改变。):
JDBCUtils.class是创建一个JDBCUtils的Class对象,Class对象就是某个类的字节码对应的类,关于这里的这个语句JDBCUtils.class.getClassLoader().getResourceAsStream()的理解,可以参考以下思路:JDBCUtils.class是创建一个JDBCUtils的Class对象。Class的getClassLoader() 是返回类加载器,JDBCUtils.class.getClassLoader()就是获取JDBCUtils类的类加载器,也就是ClassLoader对象。ClassLoader的getResourceAsStream()是返回读取指定资源的输入流。
综上所述:JDBCUtils.class.getClassLoader().getResourceAsStream(“jdbc.properties”)是返回一个读取指定资源的输入流。ClassLoader.getSystemResourceAsStream(“jdbc.properties”);跟上述代码功能一样,都可以用来获取指定的资源的输入流。

第一个<T> 代表的是泛型,第二个 T 代表的是方法的返回值。1、泛型是写在<>之中的,在编译时期就能告诉编译器,这个集合中应该存储的类型,以便编译期间约束。2、在这里<T> T 整体是返回值的声明。表示的返回值T是泛型,T是一个占位符,是Type的简称,表示普通Java 类。<T>是一种形式,表示你用的是泛型编程,不受类型的约束。3、由于public <T> T getDao(Class<T> tClass) 声明中,参数tClass也使用Class<T>。返回值的泛型<T>是与传入的参数Class<T>相对应的。4、综上<T> T是返回值类型,代表方法必须返回T类型的,而这个T类型由传入的Class<T>决定。

反射常用对象的概述:
Class类的实例表示正在运行的java应用程序中的类和接口;Constructor:关于类的单个构造方法的信息以及对它的访问权限;Field:提供有关类或接口的单个字段的信息,以及对它的动态访问权限;Method:提供关于类或接口上单独某个方法的信息。


Class类:

Class.forName(包名.类名) 只是代码书写格式。“未知”指的实际上是JVM不知道具体的类、具体的对象是什么。而我们程序员是知道类名的,只传入了具体的类名字符串,在JVM看,它只有这个类名字符串。有别于上面的“ 类名.class”,这里的类名实际上是指当前的java文件中有Import进来这个具体的类。也就是说JVM知道这个类的情况。


Constructor类:



getDeclaredConstructor获取私有的构造方法。
Class<?>... parameterTypes,Class<?>代表类型,中间的"..."表示无限参数,parameterTypes表示该无限参数类型的名字,parameterTypes 就是表示参数类型数组。
Ctrl+ 1 快捷键可以自动补全前边接收的类型。
Class 类中的newInstance() 方法和 Constructor类中的newInstance() 方法区别:首先无论是哪个的newInstance()都是用来创建对象的,在用法上是有区别的,区别如下:1、Class.newInstance() 是在java.lang 包下。Constructor.newInstance() 是在 java.lang.reflect 包下的。2、Class.newInstance() 只能够调用无参的构造函数,即默认的构造函数,而Constructor.newInstance() 可以调用带参的构造函数和无参的构造函数。3、Class.newInstance()对于捕获或者未捕获的异常均由构造器抛出;Constructor.newInstance()通常会把抛出的异常封装成InvocationTargetException抛出;4、Class.newInstance() 要求被调用的构造函数是可见的,也即必须是public类型的; Constructor.newInstance() 在特定的情况下,可以调用私有的构造函数。
toString()方法在Object类中,是返回对象名@哈希码这样的对象内容。继承Object类后,重写toString,将具体的对象属性等内容以字符串的形式返回。
Field类:

Field类中get和set方法的使用,set方法的第一个参数是要设置的对象,第二个参数是值。get方法的参数是要获取值的对象。

field.setAccessible(true);是设置属性是否可以被访问到,但是Field[] field = cs.getDeclaredFields();获取到的是属性的数组,field.setAccessible(true);无法对数组类型字段调用setaccessible()设置。如果想设置属性可以被访问,并且设置值,建议获取单个属性并设置。
使用反射可以增加程序的灵活性,简洁代码,提高代码的复用率。在Java各种框架的底层使用反射比较多。例如我们的项目底层有时是用mysql,有时用oracle,需要动态地根据实际情况加载驱动类,这个时候反射就有用了。假设com.java.dbtest.myqlConnection,com.java.dbtest.oracleConnection这两个类我们要用,这时候我们的程序就需要写得比较动态化,通过Class tc =Class.forName(“com.java.dbtest.TestConnection”);通过类的全类名让jvm在服务器中找到并加载这个类,而如果是oracle则改变一下传入的参数就可以了。
Java默认导入的是java.lang,java.lang包下的类可以自动导入,而Field类属于java.lang.reflect包下,java.lang.reflect与java.lang不是一个包,java.lang并不包含它下面的子包的内容,因此需要写导入语句。
Method类:


method.setAccessible(true);获得私有方法的访问权限。

getDeclaredMethod方法的两个参数的的含义:第一个参数是要获取的方法的名称,第二个参数Class<?>...paremeterTypes是要获取的方法的参数列表(参数类型的字节码类,如String.class)。

3.1.7 项目:油画商城

使用JDBC完成商品列表,添加商品,以及分类管理等功能
内容:

项目展示:
后台管理:登录页面、分类列表、分类添加、商品列表、商品添加
前台管理:商品显示、商品详情
技能点说明:



创建类及引入配置文件:

com.xx是域名反写,再说具体的包名:dao是数据访问层,该包下的类主要完成对数据库的操作。domain包下放置实体类。service是业务逻辑层,该包下的类用来完成具体的业务逻辑。utils是工具包,放工具类。web下有action包和filter,filter是过滤器,该包下是过滤器类。action包下控制器,主要完成路径的接收和转发。
Jar包下载:jar包本身一般没有属于自己的官网,绝大多数情况都是从靠谱的maven依赖仓库中直接下载。推荐使用https://mvnrepository.com/ 。以commons-fileupload为例,讲解下网站的使用:1)在主页搜索关键词,如果希望下载不同的版本,那么不要带上最后的版本号:

2)在搜索结果中,可以根据“usages”用户数量来判断。一般使用的都是最热门的技术,当然这么判断也可能会找到不合适的jar包(这也是目前都在资料中提供jar包,而不推荐自主下载的原因)。而后面学习到maven之后。可以根据maven依赖的groupId和artifactId来判断是否为需要的jar包。

3)进入详情后,同样可以查看每个版本的使用人数,推荐选择稍微新一些但使用人数较多的版本:

4)点击jar即可下载jar包,红线的位置一般是jar包的功能描述:

随着项目的增多,代码也越来越多,为了让代码更加清晰,一般采用三层架构的思想去写代码:让他们各司其职:

Java的三层架构就是将整个业务应用划分为三层架构:三层架构分为数据访问层(dao,Data access layer)、业务逻辑层(service,Business Logic Layer)、表示层(web,User Interface layer)。数据访问层(dao):数据访问层是指访问数据系统中的文件,实现对数据库中数据的增删改查操作。业务逻辑层(service):用来处理具体的业务逻辑。表示层(web):主要功能是显示数据和接受传输用户的数据。在dao层中查询数据,判断用户是否存在。service层处理业务逻辑,此处没有复杂的逻辑,所以只是简单的调用了dao层的方法。
Dao层是Data Access Object 数据访问对象,完成与数据库的交互,对数据库的增删改查操作。dao层有接口和实现类。
三层架构和MVC可以共存。但不能合并,MVC是表现模式,三层架构是典型的架构模式,三层架构的分层模式是典型的上下关系,上层依赖于下层。但MVC作为表现模式是不存在上下关系的,而是相互协作关系。即使将MVC当作架构模式,也不是分层模式。两者是应用于不同领域的技术。
href=# 的意思是这个超链接是禁用的,或者说不指向任何地址。
ComboPooledDataSource,去自动到classpath目录下面加载“c3p0-config.xml”配置文件。
所以配置文件必须放在和包同级的目录下才能够加载到classpath目录。
用户退出功能时,可用session调用invalidate()方法后销毁的是本次会话,session失效的时候就会立刻创建一个新的seesion。
servlet作为控制器的作用://接收参数;//封装数据;//调用业务层处理数据;//页面跳转。

重定向和转发都可以进行跳转,一般情况下使用那种方式都可以,但是有两种情况需要使用转发,一个使用request携带参数进行传递,需要使用转发,另一种如果要跳转的页面时在WEB-INF目录下,需要使用转发。
添加分类时使用servlet来跳转比直接跳转到jsp页面要安全,因为跳转到servlet,而不是直接跳转jsp页面,这样在jsp页面的路径就不会在访问路径中显示(servlet请求转发到jsp页面),比较安全。

<input type="hidden" name="method" value="save">隐藏字段相当于在请求url为...CategoryServlet后面加?method=save。

不管是是post或着get都可以使用getParameter()获取参数。但是如果form表单enctype设置multipart/form-data提交文件,不能使用getParameter()获取参数。
在form表单设置为post提交,使用action指明的路径中加了?和参数名,这样做也是可以跳转。如果使用get方法提交,则使用action指明的路径中加了?和参数名不能传递参数。
字符集编码过滤器编写:

这里没有设置response是因为没有直接使用response向页面输出数据,而是用response进行的重定向转发。若要用response向浏览器页面写数据时,就要设置一下编码格式了。
添加过滤器后,css,js,png等不能正确加载(可能是在过滤中设置response.setContentType(“text/html;charset=UTF-8”)将响应的文本设置成html格式了,.css等也变成text/html而不是text/css所以页面样式等会出现错误),可在过滤器中增加如下设置:

过滤器中设置请求字符集编码和响应内容类型在上面代码段后面。
浏览器中的字符集和浏览器的设置有关。可以在浏览器中按F12,输入document.charset,按回车键,即可查询浏览器的字符集。
如果不写带参的构造方法。一个类默认有一个无参的构造方法。所以虽然没有写,其实是有构造方法的。
workbench中创建架构设计器。
在类的方法(非静态方法)中访问当前类中的其它方法可以直接调用,相当于前面默认加了this调用当前对象的某个方法。
在开发中直接跳转页面和跳转至后台然后返回页面这两种风格,都有使用,具体看项目。一般如果不通过后台跳转页面,那么整个项目都不会通过后台返回页面,此时的数据交互会通过ajax来进行。
参数method放在链接后面,还是放到隐藏字段的输入项中:1、method放在链接后面:form中添加enctype="multipart/form-data"是指定传输数据为二进制类型。这时不能就使用request.getParameter(“method”);获得method值了,可以把method拼接放在url上。比如:

所以当在servlet中不可以使用request.getParameter()等途径获得到数据时,可以考虑将参数放在url上。2、放到隐藏的输入项中:隐藏提交。hidden同text,password一样,是input输入框的type属性的其中一个属性值,它作为一个类中的属性值,可以使用hidden属性隐藏提交。如上所示两种形式的参数传递都可以,可以根据使用场景来决定使用。

表单上传文件时,用:<input type = "hidden" name="method" value="save">来设置参数,对应的Servlet类不能通过request.getParameter(“method”);获取method参数。

通常获取路径的方法:

在jsp页面中,通常获取项目路径的方法有:1)${pageContext.request.contextPath} 。2)<%
String path = request.getContextPath();

String basePath = request.getScheme()+"

Java数据库开发与应用之MySQL数据库、JDBC操作数据库、C3P0数据库连接池,Java反射等相关推荐

  1. [原创]java WEB学习笔记80:Hibernate学习之路--- hibernate配置文件:JDBC 连接属性,C3P0 数据库连接池属性等...

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

  2. Java系列技术之JDBC操作数据库-钟洪发-专题视频课程

    Java系列技术之JDBC操作数据库-22人已学习 课程介绍         JDBC连接数据库是Java系列技术中数据库知识的核心技术,是学习后续课程JavaWeb入门前需要掌握的基础! 这门课的前 ...

  3. java完整JDBC操作数据库

    java使用JDBC操作数据库的包含以下7个主要步骤: 1.加载JDBC驱动程序 在连接数据库之前,首先要加载想要连接的数据库的驱动到JVM(Java虚拟机),这通过java.lang.Class类的 ...

  4. Java笔记(第七篇 JDBC操作数据库)

    JDBC是连接数据库和java程序的桥梁,通过JDBC API可以方便地实现对各种主流数据库的操作.学习java语言,必须学习JDBC技术,因为JDBC技术实在java语言中被广泛使用的一种操作数据库 ...

  5. spring boot 2.0采用com.mysql.cj.jdbc.Driver数据库驱动引发的系统时间不一致问题

    首先简单描述一下项目情况,老板新注册了一家公司,既然有公司了肯定得有个公司门户网站.现在已经是web 2.0时代了,网站内容不可能再像以前那样全部采用静态html页面.于是开发了一个内容管理系统,简称 ...

  6. java监听数据库操作_第十六篇——JDBC操作数据库之监听器

    JavaWeb应用中,很多的地方都和session有关.因此session相关的事件监听器,在日常工作中非常有用. 有时候我们需要统计当前在线的人数和访问人数总数,此时就可以使用监听器技术来很简单的实 ...

  7. JavaWeb:用JDBC操作数据库

    JDBC系列阅读 JavaWeb:用JDBC操作数据库 JavaWeb:JDBC之事务 JavaWeb:JDBC之数据库连接池 使用JDBC实现水果超市管理系统 1. 什么是JDBC JDBC的全称是 ...

  8. 【JDBC】JDBC 简介 ( JDBC 概念 | JDBC 本质 | 使用 JDBC 操作数据库的好处 | JDBC 提供的 API 组件 )

    文章目录 一.JDBC 概念 二.JDBC 本质 三.使用 JDBC 操作数据库的好处 四.JDBC 提供的 API 组件 一.JDBC 概念 JDBC 全称 Java DataBase Connec ...

  9. 20.JDBC操作数据库

    目录 1. Java基本介绍 2. JDK下载安装及其环境配置 3. 一个简单的java程序 4. Eclipse基本使用.数据类型.运算符 5. 控制语句(if.switch.for.while.f ...

最新文章

  1. 程序猿面试什么最重要?
  2. 一篇文章了解生物特征识别六大技术
  3. 百度 71个炸天的开源项目,你知道几个?
  4. 微信小程序 网络请求之设置合法域名
  5. 自己帮别人写的网站可以公开源码吗_专注爬虫:20个精心总结爬虫项目,爬虫技术这里强(附源码)...
  6. java servlet post取值_Java servlet无法获得POST参数
  7. cvs 代码无法提交
  8. CentOS7出现“FirewallD is not running”
  9. PB级(大数据)的来源
  10. SQL Server实际执行计划COST欺骗案例
  11. 和我一起打造个简单搜索之ElasticSearch入门
  12. JS 浏览器差异(IE和FF)
  13. 【量化数据分析】Amos拟合优度与假设检验
  14. 你的Web系统真的安全吗?
  15. 育儿心得,所有适龄女青年都该看一下(转)
  16. 微信公众号 创建菜单post数据格式
  17. C 时间库 time.h 获取当前时间
  18. 火车头采集成功了,虽然是这么的牵强。
  19. Nginx+mongrel部署Rails应用
  20. LTE学习笔记 ——GTP-U

热门文章

  1. 网站上的轮播图都是怎么实现的?
  2. mc正版中国服务器,OurCraft Minecraft 服务器
  3. Vue组件化编程开发
  4. redis续期_redis分布式锁自动延长过期时间
  5. docker公共仓库和私有仓库创建使用
  6. 进行批量操作-审核或弃审
  7. excel一列中某一数据第一次出现的位置(使用match实现)
  8. 近红外 CMOS 相机
  9. 离散数学之王教授是哪里人--python
  10. php短信验证失败的原因,php短信验证问题