MySQL
一. 安装教程
1. 安装建议:
1.1 尽量不要使用exe安装.(因为卸载麻烦, 安装数据会进入注册表).
1.2 尽量使用压缩包安装.(卸载时把压缩包删除即可).
2. mySql 5.7(64位下载地址): https://dev.mysq.com/get/Downloads/MySQL-5.7/mysql-5.7.19-winx64.zip
------------------------------------------------------------------------------------
3.安装mysql5过程(同时安装5和8, 实测成功⭐⭐):
/* 参考:推荐Win下同时安装MySQL5和MySQL8并存⭐(安装两个mysql需不同命名->mysqld -install [命名]): https://blog.csdn.net/qq_32793985/article/details/105807328 */
-> 3.1 解压, 放在电脑的某个目录下.
-> 3.2 设置环境变量(path中添加: D:\MyDevTools\Mysql5\mysql-5.7.19\bin, 就是bin所在的地址).
-> 3.3 新建mysql配置文件my.ini, 文件内容如下:
[mysqld]
# 设置mysql的安装目录
basedir=D:\MyDevTools\Mysql5\mysql-5.7.19\
# 设置mysql数据库的数据的存放目录
datadir=D:\MyDevTools\Mysql5\mysql-5.7.19\data\
# 设置3305端口
port=3305
# 跳过密码验证
# skip-grant-tables
-> 3.4 启动管理员模式下的cmd,并将路径切换至mysql下的bin目录,执行初始化命令:mysqld --initialize --console; (注意这里会生成一串随机密码,一定要记住!)
-> 3.5 执行数据库安装命令: mysqld --install MYSQL5;
(注意这里安装的时候端口是3305, 名称是MYSQL5,如果直接使用mysqld --install则默认名称为mysql. )
-> 3.6 然后启动mysql服务(启动命令: net start MYSQL5),
然后登录输入命令:mysql -u root -P 3305 -h localhost -p
(-p 后直接确定, 然后输入密码, 就是上面获取的随机密码).
-> 3.7 进入界面后更改root密码:
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '密码';
-> 3.8 最后输入 flush privileges; 刷新权限[注意mysql命令后的分号不要漏掉.]
-> 3.9 显示当前存在的数据库: show databases; 退出: exit;
------------------------------------------------------------------------------------
4.安装mysql8过程:
-> 4.1解压, 放在电脑的某个目录下.
-> 4.2设置环境变量(path中添加: D:\MyDevTools\Mysql5\mysql-5.7.19\bin, 就是bin所在的目录).
-> 4.3新建mysql配置文件my.ini, 文件内容如下:
[mysql]
# 设置mysql客户端默认字符集
default-character-set=utf8
[mysqld]
# 设置3306端口
port = 3306
# 设置mysql的安装目录
basedir = D:\\MyDevTools\\Mysql8\\mysql-8.0.22-winx64\\
# 设置mysql数据库的数据的存放目录
datadir = D:\\MyDevTools\\Mysql8\\mysql-8.0.22-winx64\\data
# 允许最大连接数
max_connections=20
# 服务端使用的字符集默认为8比特编码的latin1字符集
character-set-server=utf8
# 创建新表时将使用的默认存储引擎
default-storage-engine=INNODB
# 创建模式
sql_mode = NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
-> 4.4 启动管理员模式下的cmd, 并将路径切换至mysql下的bin目录, 执行初始化命令:mysqld --initialize --console(注意这里会生成一串随机密码,一定要记住!)
-> 4.5 执行安装命令: mysqld --install
-> 4.6 启动mysql服务: net start mysql
-> 4.7 mysql用户登录: mysql -u root -p, 然后输入上面获取的随机密码.
-> 4.8 修改密码: ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '密码';
-> 4.9 刷新权限: flush privileges;
-> 4.10 显示当前存在的数据库: show databases; 退出: exit;
/* 【问题1】安装MySql时出现: The service already exists! The current server installed;
【解决方法】1.管理员运行CMD; 2.执行sc query mysql; 3.执行sc delete mysql;
【问题2】安装MySql时出现: [SC] DeleteService 失败 1072: 指定的服务已标记为删除。
【解决方法】打开任务管理器, 把MySQL进程停止, 并且关闭任务管理器的界面!!! */
------------------------------------------------------------------------------------
5.安装Navicat或SQLyog来操作数据库(参考链接: https://blog.csdn.net/liangllhahaha/article/details/89508826);
初级教程
二、数据值和列类型
数值类型 | 字符串类型 | 日期和时间型数值类型 | |||
---|---|---|---|---|---|
tinyint | 1字节 | char[(M)] | M字符 | date | YYYY-MM-DD |
smallint | 2字节 | varchar[(M)] | 可变长度 | time | hh:mm:ss |
mediumint | 3字节 | tinytext | 2^8-1字节 | datetime | YYYY-…:mm:ss |
int | 4字节 | text | 2^16-1字节 | timestamp | 时间戳(毫秒) |
bigint | 8字节 | year | YYYY | ||
float | 4字节 | ---------------- | --------------- | --------------- | ---------------- |
double | 8字节 | NULL值 | |||
decimal[(m, d)] | m个字节 | “没有值” 或 “未知值” | 别用于算术运算! |
- 数据字段属性(常见的⭐⭐)
1.UnSigned //无符号的, 声明该数据列不允许负数.
2.ZEROFILL //0填充的, 不足位数的用0来填充 , 如int(3),5则为005
3.Auto_InCrement
/* 1. 自动增长的, 每添加一条数据, 自动在上一个记录数上加 1(默认),
2. 通常用于设置主键, 且为整数类型
3. 可定义起始值和步长:
当前表设置步长(AUTO_INCREMENT=100) : 只影响当前表;
SET @@auto_increment_increment=5 ; 影响所有使用自增的表(全局) */
4.NULL 和 NOT NULL //默认为NULL, 即没有插入该列的数值. 如果设置为NOT NULL , 则该列必须有值
5.DEFAULT //默认的, 用于设置默认值.
/*每一个表,都必须存在以下五个字段!未来做项目用的, 表示一个记录存在的意义! (阿里巴巴规范)
id 主键
`version` 乐观锁
is _delete 伪删除
gmt_create 创建时间
gmt_update 修改时间*/
三、一些最重要的 SQL 命令
- 3.1 结构化查询语句分类
名称 | 解释 | 命令 |
---|---|---|
DDL (数据定义语言) | 定义和管理数据对象,如数据库,数据表等 | CREATE、DROP、ALTER |
DML (数据操作语言⭐) | 用于操作数据库对象中所包含的数据 | INSERT、UPDATE、DELETE |
DQL (数据查询语言⭐) | 用于查询数据库数据 | SELECT |
DCL (数据控制语言) | 用于管理数据库的语言,包括管理权限及数据更改 | GRANT、commit、rollback |
注意: 反引号是用于区别MySQL保留字与普通字符而引入的 (键盘esc下面的键, 注意区别``和’').
-
DDL_数据库和表的操作 (了解!)
1.数据库的操作_查改增删 -- 1.1 查询所有数据库 show databases; -- 1.2 创建新数据库 CREATE DATABASE [if not exists] 数据库名; -- 1.3 删除数据库 DROP DATABASE [if exists] 数据库名; -- 使用数据库 use `数据库名`; 2.数据库表的操作 -- 2.1 创建表 create table [if not exists] `表名`( '字段名1' 列类型 [属性][索引][注释], '字段名2' 列类型 [属性][索引][注释], '...', '字段名n' 列类型 [属性][索引][注释] )[表类型][表字符集][注释]; -- 2.2 改变数据库表 修改表名 : ALTER TABLE 旧表名 RENAME AS 新表名 添加字段 : ALTER TABLE 表名 ADD 字段名 列属性[属性] 修改字段 : ALTER TABLE 表名 MODIFY 字段名 列类型[属性] ALTER TABLE 表名 CHANGE 旧字段名 新字段名 列属性[属性] 删除字段 : ALTER TABLE 表名 DROP 字段名 -- 2.3 删除表 DROP TABLE [IF EXISTS] 表名 3.外键(了解即可) 因为阿里说:【强制】不得使用外键与级联,一切外键概念必须在应用层解决. 【理由】每次做DELETE 或者UPDATE都必须考虑外键约束,会导致开发的时候很痛苦,测试数据极为不方便。
-
DML_数据的改增删操作(⭐)
-- 1. UPDATE: 更新数据库中的数据 (后面一定要接where条件,否则后果很严重!) UPDATE 表名 SET column1=value1,column2=value2,... WHERE [条件:some_column=some_value]; -- 2. INSERT INTO: 向数据库中插入新数据 INSERT INTO 表名 (字段1,字段2,字段3,...) VALUES (value1,value2,value3,...); -- 3.1 DELETE: 从数据库中删除数据 (后面一定要接where条件,否则后果很严重!) DELETE FROM 表名 WHERE [条件:some_column=some_value]; -- 3.2 TRUNCATE: 删除数据库表数据 TRUNCATE TABLE '表名' -- 1.结论: truncate删除数据, 自增当前值会恢复到初始值重新开始; 不会记录日志. -- 2.同样使用DELETE清空不同引擎的数据库表数据.重启数据库服务后: -- InnoDB : 自增列从初始值重新开始 (因为是存储在内存中,断电即失) -- MyISAM : 自增列依然从上一个自增数据基础上开始 (存在文件中,不会丢失)
-
DQL( Data Query Language )_数据的查操作(最重要⭐⭐⭐)
-
SELECT语法结构:
-- (注意 : [ ] 括号代表可选的 , { }括号代表必选得.) SELECT [ALL | DISTINCT] {* | table.* | [table.field1[as alias1][,table.field2[as alias2]][,...]]} 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}]; -- 指定查询的记录从哪条至哪条
-- 1.1 SELECT: 从数据库中提取数据 SELECT 字段1,字段2,... FROM 表名; -- 2.常用语法 -- 常用运算符一: =, <>或!=, >和<, >=和<=, between, and, or UPDATE grade SET gradename = '高中' WHERE gradeid = 1; -- 修改年级信息 -- 常用运算符二: and[&&], or[||], not[!] SELECT studentno,studentresult FROM result WHERE NOT studentno=1000; -- 常用运算符三: as(可以为字段或表取别名), SELECT studentno AS 学号,studentname AS 姓名 FROM student AS s; -- distinct([了解]去除重复的数据,默认是ALL). SELECT DISTINCT studentno FROM result; -- 3.1模糊查询一: like, %[代表0到任意个字符], _[一个字符] SELECT studentno,studentname FROM student WHERE studentname LIKE '刘_'; -- 查询姓刘的同学,后面只有一个字的. -- 3.2模糊查询一: is null, is not null, between, in SELECT studentno,studentname FROM student WHERE studentno IN (1000,1001,1002); -- 查询学号为1000,1001,1002的学生姓名 -- 4. 联表查询 LEFT JOIN: [左外连接,左表为主表.]即使右表中没有匹配,也从左表中返回所有的行. RIGHT JOIN: [右外连接,右表为主表.]即使左表中没有匹配,也从右表中返回所有的行. INNER JOIN: [内连接]如果表中有至少一个匹配,则返回行. 自连接(了解) -- on和wehere的使用: -- join [表名] on [判断条件]; =>连接查询(一般用了join则使用on), -- where [条件可以使具体的值或子查询语句] =>等值查询 -- 5.1 分页: limit [a[, b]] -- 前端数据->后端: n为当前页码; -- 后端数据->前端: pageSize; dataTotal为数据记录总数; pageTotal=dataTotal/pageSize; -- 在limit中, a=(n-1)*pageSize, b=pageSize(页面大小), select studentno,studentname from student limit 0,5; -- 5.2 分组和排序: -- group by 字段名; -- order by 字段名 asc(升序)/desc(降序) -- having (=>过滤分组后的信息, 条件和where是一样的, 位置不同.) SELECT Studentno,StudentResult FROM result ORDER BY StudentResult desc -- 6.子查询和嵌套 -- 在上面SQL基础上,添加需求:课程为 高等数学-2 SELECT r.studentno,studentname FROM student s INNER JOIN result r ON s.`StudentNo`=r.`StudentNo` WHERE StudentResult>=80 AND subjectno=( SELECT subjectno FROM `subject` WHERE subjectname = '高等数学-2' ) -- 使用子查询 -> 分步写简单sql语句,然后将其嵌套起来 SELECT studentno,studentname FROM student WHERE studentno IN( SELECT studentno FROM result WHERE StudentResult>=80 AND subjectno=( SELECT subjectno FROM `subject` WHERE subjectname = '高等数学-2' ) ) -- 7.1 聚合函数(重要⭐) COUNT() -- 返回满足Select条件的记录总和数,如 select count(*) 【不建议使用 *,效率低】. SUM() -- 返回数字字段或表达式列作统计,返回一列的总和。 AVG() -- 通常为数值字段或表达列作统计,返回一列的平均值 MAX() -- 可以为数值字段,字符字段或表达式列作统计,返回最大的值。 MIN() -- 可以为数值字段,字符字段或表达式列作统计,返回最小的值。 SELECT COUNT(studentname) FROM student; SELECT COUNT(*) FROM student; SELECT COUNT(1) FROM student; /*推荐*/ -- 7.2 MYSQL常用函数(了解部分): -- 数据函数 SELECT ABS(-8); /*绝对值*/ SELECT CEILING(9.4); /*向上取整*/ SELECT FLOOR(9.4); /*向下取整*/ SELECT RAND(); /*随机数,返回一个0-1之间的随机数*/ SELECT SIGN(0); /*符号函数: 负数返回-1,正数返回1,0返回0*/ -- 日期和时间函数⭐ SELECT CURRENT_DATE(); /*获取当前日期: 2021-12-02*/ SELECT CURDATE(); /*获取当前日期: 2021-12-02*/ SELECT NOW(); /*获取当前日期和时间: 2021-12-02 01:16:33*/ SELECT LOCALTIME(); /*获取(本地)当前日期和时间: 2021-12-02 01:17:00*/ SELECT SYSDATE(); /*获取(系统)当前日期和时间: 2021-12-02 01:17:25*/ -- 获取年月日,时分秒 SELECT YEAR(NOW()); SELECT MONTH(NOW()); SELECT DAY(NOW()); SELECT HOUR(NOW()); SELECT MINUTE(NOW()); SELECT SECOND(NOW()); -- 系统信息函数 SELECT VERSION(); /*版本*/ SELECT USER(); /*用户*/ -- CONCAT()函数: 拼接字符串 SELECT CONCAT('姓名:',studentname) AS 新姓名 FROM student; -- 8. MD5加密函数-> MD5(str) insert into `testmd5` (`id`, `name`, `pwd`) values(5,'xiao',MD5('123456'));
-
四.事务⭐⭐
- 什么是事务?
- 事务就是将一组SQL语句放在同一批次内去执行.
- 如果一个SQL语句出错,则该批次内的所有SQL都将被取消执行.
- MySQL事务处理只支持InnoDB和BDB数据表类型.
事务的ACID原则:
-- 1.原子性(Atomic)
整个事务中的所有操作,要么全部完成,要么全部不完成,不可能停滞在中间某个环节。
//事务在执行过程中发生错误,会被回滚(ROLLBACK)到事务开始前的状态,就像这个事务从来没有执行过一样。
-- 2.一致性(Consist)
一个事务可以封装状态改变(除非它是一个只读的)。
//事务必须始终保持系统处于一致的状态,不管在任何给定的时间并发事务有多少。也就是说:如果事务是并发多个,系统也必须如同串行事务一样操作。其主要特征是保护性和不变性(Preserving an Invariant),以转账案例为例,假设有五个账户,每个账户余额是100元,那么五个账户总额是500元,如果在这个5个账户之间同时发生多个转账,无论并发多少个,比如在A与B账户之间转账5元,在C与D账户之间转账10元,在B与E之间转账15元,五个账户总额也应该还是500元,这就是保护性和不变性。
-- 3.隔离性(Isolated)
隔离状态执行事务,使它们好像是系统在给定时间内执行的唯一操作。
//如果有两个事务,运行在相同的时间内,执行相同的功能,事务的隔离性将确保每一事务在系统中认为只有该事务在使用系统。这种属性有时称为串行化,为了防止事务操作间的混淆,必须串行化或序列化请求,使得在同一时间仅有一个请求用于同一数据。
-- 4.持久性(Durable)
在事务完成以后,该事务对数据库所作的更改便持久的保存在数据库之中,并不会被回滚。
-
转账案例
/* 课堂测试题目: A在线买一款价格为500元商品,网上银行转账. A的银行卡余额为2000,然后给商家B支付500. 商家B一开始的银行卡余额为10000. 创建数据库shop和创建表account并插入2条数据. */ CREATE DATABASE `shop`CHARACTER SET utf8 COLLATE utf8_general_ci; USE `shop`; CREATE TABLE `account` ( `id` INT(11) NOT NULL AUTO_INCREMENT, `name` VARCHAR(32) NOT NULL, `cash` DECIMAL(9,2) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=INNODB DEFAULT CHARSET=utf8 INSERT INTO account (`name`,`cash`) VALUES('A',2000.00),('B',10000.00); -- 转账实现 SET autocommit = 0; -- 关闭自动提交 START TRANSACTION; -- 开始一个事务,标记事务的起始点 ----------------------- 一组sql --------------------------- UPDATE account SET cash=cash-500 WHERE `name`='A'; UPDATE account SET cash=cash+500 WHERE `name`='B'; ---------------------------------------------------------- COMMIT; -- 提交事务 rollback; -- 回滚 SET autocommit = 1; -- 恢复自动提交
五.索引
注意: 复制狂神笔记中的SQL语句来执行时, 如果执行不成功 => 其实是换行的地方复制了一些看不见的字符, 需要把"换行的地方"都先删除连接头尾文字, 再手动敲过换行即可;
1.索引准则
索引不是越多越好
不要对经常变动的数据加索引
小数据量的表建议不要加索引
索引一般应加在查找条件的字段
2.索引操作
-- 创建索引(搜索键)
CREATE INDEX
-- 删除索引
DROP INDEX
六.MySQL权限管理与备份
6.1 权限管理
略
6.2 数据库备份
第一种[备份单个数据库]: Navicat -> 转储SQL文件(可以选择导出仅结构 或 数据和结构;)
第二种[备份所有数据库]: 在cmd命令窗口输入: mysqldump -uroot -p --all-databases > d:\allsql.sql
(然后输入密码即可; 注意进入cmd后直接输入命令即可, 不用进入mysql命令行输入);
七.数据库设计与实现
注意:
MySql数据库中不区分大小写, 所以不会使用驼峰命名, 二是使用下划线来分割, 比如user_name;
7.1 三大范式
数据库范式分为1NF,2NF,3NF,BCNF,4NF,5NF一般我们在设计数据库结构的时候最多只要满足到BCNF就可以
了。符合高一级的范式必定符合低一级的范式。
第一范式(1NF): 字段是最小的的单元不可再分;
第二范式(2NF): 满足1NF,表中的字段必须完全依赖于全部主键而非部分主键 (必须完全依赖, 一般我们都会做到);
第三范式(3NF): 满足2NF,非主键外的所有字段必须互不依赖(排除传递函数依赖);
/* 注意:
1.为满足某种商业目标 , 数据库性能比规范化数据库更重要;
2.在数据规范化的同时 , 要综合考虑数据库的性能;
3.通过在给定的表中添加额外的字段,以大量减少需要从中搜索信息所需的时间;
4.通过在给定的表中插入计算列,以方便查询;
*/
八.数据库原生连接和JDBC
-
JDBC介绍
1.JDBC是什么: SUN公司为了简化、统一对数据库的操作,定义了一套Java操作数据库的规范(接口),称之为JDBC。 1.1 JDBC全称为:Java Data Base Connectivity(java数据库连接),它主要由接口组成。 1.2 使用前的环境准备: -- 组成JDBC的2个包:java.sql、javax.sql; -- 发JDBC应用需要以上2个包的支持外,还需要导入相应JDBC的数据库实现(即数据库驱动,如mysql-connector-java-5.1.47.jar); // JDBC的使用: ①加载数据库驱动程序[Class.forName()]-> ②获取数据库连接[DriverManager类]-> ③向数据库发送sql语句[Statement类]-> ④处理数据库返回结果[ResultSet] ->⑤释放资源 2.JDBC对象说明; 2.1 DriverManager类; //首先-> Class.forName加载完驱动类: Class.forName("com.mysql.jdbc.Driver");; Jdbc程序中的DriverManager用于加载驱动,并创建与数据库的链接,这个API的常用方法: -- DriverManager.registerDriver(new Driver());//不推荐使用; -- DriverManager.getConnection(url, user, password);//推荐 2.2 Connection类; //Jdbc程序中的Connection,它用于代表数据库的链接; 客户端与数据库所有交互都是通过connection对象完成的,这个对象的常用方法: createStatement(): 创建向数据库发送sql的statement对象; prepareStatement(sql): 创建向数据库发送预编译sql的PrepareSatement对象; setAutoCommit(boolean autoCommit): 设置事务是否自动提交; commit(): 在链接上提交事务; rollback(): 在此链接上回滚事务; 2.3 Statement类;(次要, 使用该类可能被sql注入) //Jdbc程序中的Statement对象用于向数据库发送SQL语句, Statement对象常用方法: executeQuery(String sql) :用于向数据发送查询语句; executeUpdate(String sql):用于向数据库发送insert、update或delete语句; execute(String sql):用于向数据库发送任意sql语句; addBatch(String sql) :把多条sql语句放到一个批处理中; executeBatch():向数据库发送一批sql语句执行; 2.4 PrepareSatement类;(重要, 使用该类可以防止sql注入) -- PreperedStatement是Statement的子类,可以避免SQL注入的问题; -- Statement会使数据库频繁编译SQL,可能造成数据库缓冲区溢出。PreparedStatement可对SQL进行预编译,从而提高数据库的执行效率。并且PreperedStatement对于sql中的参数,允许使用占位符的形式进行替换,简化sql语句的编写。 2.5 ResultSet类; //Jdbc程序中的ResultSet用于代表Sql语句的执行结果。Resultset封装执行结果时,采用的类似于表格的方式。ResultSet 对象维护了一个指向表格数据行的游标,初始的时候,游标在第一行之前,调用ResultSet.next()方法,可以使游标指向具体的数据行,进行调用方法获取该行的数据。 ResultSet既然用于封装执行结果的,所以该对象提供的都是用于获取数据的get方法: -- 获取任意类型的数据: getObject(int index); getObject(string columnName); -- 获取指定类型的数据,例如: getString(int index); getString(String columnName); -- ResultSet还提供了对结果集进行滚动的方法: next():移动到下一行; Previous():移动到前一行; absolute(int row):移动到指定行; beforeFirst():移动resultSet的最前面; afterLast() :移动到resultSet的最后面; 2.6 **释放资源**: -- Jdbc程序运行完后,切记要释放程序在运行过程中,创建的那些与数据库进行交互的对象,这些对象通常是ResultSet, Statement和Connection对象,特别是Connection对象,它是非常稀有的资源,用完后 必须马上释放,如果Connection不能及时、正确的关闭,极易导致系统宕机。 -- Connection的使用原则是尽量晚创建,尽量早的释放。为确保资源释放代码能运行,资源释放代码也一定要放在finally语句中。
-
使用JDBC连接数据库
//步骤1: 创建文件jdbc.properties; driver=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3305/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=true username=root password=root //------------------------------------------------------------------------------ //步骤2: 创建工具类utils:; 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{ InputStream in = JdbcUtils.class.getClassLoader().getResourceAsStream("db.properties"); Properties properties = new Properties(); properties.load(in); // 读取 driver = properties.getProperty("driver"); url = properties.getProperty("url"); username = properties.getProperty("username"); password = properties.getProperty("password"); //1. 驱动只要加载一次 Class.forName(driver); } catch (Exception e) { e.printStackTrace(); } } /** * 返回一个数据库连接 * @return * @throws SQLException */ public static Connection getConnection() throws SQLException { return DriverManager.getConnection(url,username,password); } /** * 释放连接资源 * @param con * @param st * @param rs */ public static void release(Connection con,Statement st, ResultSet rs){ if (con != null){ try { con.close(); } catch (SQLException throwables) { throwables.printStackTrace(); } } if (st != null){ try { st.close(); } catch (SQLException throwables) { throwables.printStackTrace(); } } if (rs != null){ try { rs.close(); } catch (SQLException throwables) { throwables.printStackTrace(); } } } } //------------------------------------------------------------------------------ //步骤3: 增删改查的实现 //查询实现 public class TestSelect { public static void main(String[] args) { Connection con = null; PreparedStatement st = null; ResultSet rs = null; try { con = JdbcUtils.getConnection(); String sql = "select * from jdbcstudy.users where id=?"; st = con.prepareStatement(sql); st.setInt(1,3); rs = st.executeQuery(); if (rs.next()) { System.out.println("id="+rs.getObject("id")); System.out.println("NAME="+rs.getObject("NAME")); System.out.println("PASSWORD="+rs.getObject("PASSWORD")); System.out.println("email="+rs.getObject("email")); System.out.println("birthday="+rs.getObject("birthday")); } } catch (SQLException throwables) { throwables.printStackTrace(); } finally { JdbcUtils.release(con,st,rs); } } } //增加实现 public class TestInsert { public static void main(String[] args) { Connection con = null; PreparedStatement st = null; try { con = JdbcUtils.getConnection(); // 使用? 占位符代替参数 String sql = "insert into jdbcstudy.users(id,`NAME`,`PASSWORD`,`email`,`birthday`) values(?,?,?,?,?)"; // 预编译sql, 先写sql, 然后不执行 st = con.prepareStatement(sql); // 手动给参数赋值 st.setInt(1,5); st.setString(2,"xiaoming"); st.setString(3,"123456"); st.setString(4,"123456@qq.com"); // 注意点: 数据库用java.sql.Date; Java使用java.util.Date; st.setDate(5,new java.sql.Date(new Date().getTime())); // 执行 int num = st.executeUpdate(); if (num > 0){ System.out.println("插入成功!"); } } catch (SQLException throwables) { throwables.printStackTrace(); } finally { JdbcUtils.release(con,st,null); } } }
九.数据常用连接池
-
1.连接池
1.dbcp_数据库连接池; ->1.1 需要的jar文件: Commons-dbcp.jar:连接池的实现; Commons-pool.jar:连接池实现的依赖库; //(Tomcat 的连接池正是采用该连接池来实现的。该数据库连接池既可以与应用服务器整合使用,也可由应用程序独立使用) 2.c3p0_数据库连接池: 2.1 需要的jar文件: c3p0.jar; mchange-commons-java.jar; //c3p0与dbcp区别: dbcp没有自动回收空闲连接的功能, c3p0有自动回收空闲连接功能; 3.druid_数据库连接池(阿里巴巴); /* 连接池常用概念: 最小连接数, 最大连接数, */
注意:
1.编写连接池需实现java.sql.DataSource接口;
-
2.连接池代码使用
-
2.1 dbcp_数据库连接池的使用
//步骤1: 导入相关的2个jar包 -> 加入dbcp的配置文件dbcpconfig.properties #连接设置 driverClassName=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3305/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=true username=root password=root #<!-- 初始化连接 --> initialSize=10 #最大连接数量 maxActive=50 #<!-- 最大空闲连接 --> maxIdle=20 #<!-- 最小空闲连接 --> minIdle=5 #<!-- 超时等待时间以毫JdbcUtils秒为单位 6000毫秒/1000等于60秒 --> maxWait=60000 #JDBC驱动建立连接时附带的连接属性属性的格式必须为这样:[属性名=property;] #注意:"user" 与 "password" 两个属性会被明确地传递,因此这里不需要包含他们。 connectionProperties=useUnicode=true;characterEncoding=UTF8 #指定由连接池所创建的连接的自动提交(auto-commit)状态。 defaultAutoCommit=true #driver default 指定由连接池所创建的连接的只读(read-only)状态。 #如果没有设置该值,则“setReadOnly”方法将不被调用。(某些驱动并不支持只读模式,如:Informix) defaultReadOnly= #driver default 指定由连接池所创建的连接的事务级别(TransactionIsolation)。 #可用值为下列之一:(详情可见javadoc。)NONE,READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE defaultTransactionIsolation=READ_UNCOMMITTED //----------------------------------------------------------------------------- //步骤2: 编写工具类 public class JdbcUtils_DBCP { private static DataSource dataSource = null; static { try{ InputStream in = JdbcUtils_DBCP.class.getClassLoader().getResourceAsStream("dbcpconfig.properties"); Properties properties = new Properties(); properties.load(in); //1. 创建数据源 (工厂模式 -> 创建) dataSource = BasicDataSourceFactory.createDataSource(properties); } catch (Exception e) { e.printStackTrace(); } } /** * 返回一个数据库连接 * @return * @throws SQLException */ public static Connection getConnection() throws SQLException { return dataSource.getConnection(); } /** * 释放连接资源 * @param con * @param st * @param rs */ public static void release(Connection con,Statement st, ResultSet rs){ if (con != null){ try { con.close(); } catch (SQLException throwables) { throwables.printStackTrace(); } } if (st != null){ try { st.close(); } catch (SQLException throwables) { throwables.printStackTrace(); } } if (rs != null){ try { rs.close(); } catch (SQLException throwables) { throwables.printStackTrace(); } } } }
-
2.2 c3p0_数据库连接池的使用
//步骤1: 导入相关的2个jar包 -> 加入C3P0的配置文件c3p0-config.xml <?xml version="1.0" encoding="UTF-8"?> <c3p0-config> <!-- C3P0的缺省(默认)配置: 如果在代码中“ComboPooledDataSource ds = new ComboPooledDataSource();”这样写就表示使用的是C3P0的缺省(默认)配置信息来创建数据源 --> <default-config> <property name="driverClass">com.mysql.jdbc.Driver</property> <property name="jdbcUrl">jdbc:mysql://localhost:3305/jdbcStudy?useUnicode=true&characterEncoding=utf8&useSSL=true</property> <property name="user">root</property> <property name="password">root</property> <property name="acquireIncrement">5</property> <property name="initialPoolSize">10</property> <property name="minPoolSize">5</property> <property name="maxPoolSize">20</property> </default-config> <!-- C3P0的命名配置: 如果在代码中“ComboPooledDataSource ds = new ComboPooledDataSource("MySQL");”这样写就表示使用的是name是MySQL的配置信息来创建数据源 --> <named-config name="MySQL5"> <property name="driverClass">com.mysql.jdbc.Driver</property> <property name="jdbcUrl">jdbc:mysql://localhost:3305/jdbcStudy?useUnicode=true&characterEncoding=utf8&useSSL=true</property> <property name="user">root</property> <property name="password">root</property> <property name="acquireIncrement">5</property> <property name="initialPoolSize">10</property> <property name="minPoolSize">5</property> <property name="maxPoolSize">20</property> </named-config> </c3p0-config> //----------------------------------------------------------------------------- //步骤2: 编写工具类 public class JdbcUtils_C3P0 { private static ComboPooledDataSource dataSource = null; static { try{ //1.创建数据源 dataSource = new ComboPooledDataSource();//获取默认的数据源 // dataSource = new ComboPooledDataSource("MySQL5");//获取对应的数据源 //2.Java代码配置_创建数据源 /* dataSource.setDriverClass(); dataSource.setJdbcUrl(); dataSource.setUser(); dataSource.setPassword(); dataSource.setMinPoolSize(); dataSource.setMaxPoolSize(); */ } catch (Exception e) { e.printStackTrace(); } } /** * 返回一个数据库连接 * @return * @throws SQLException */ public static Connection getConnection() throws SQLException { return dataSource.getConnection(); } /** * 释放连接资源 * @param con * @param st * @param rs */ public static void release(Connection con,Statement st, ResultSet rs){ if (con != null){ try { con.close(); } catch (SQLException throwables) { throwables.printStackTrace(); } } if (st != null){ try { st.close(); } catch (SQLException throwables) { throwables.printStackTrace(); } } if (rs != null){ try { rs.close(); } catch (SQLException throwables) { throwables.printStackTrace(); } } } }
-