1.数据库介绍
数据库是安装在操作系统,可以系统性的存储大量数据的软件.
作用:存储数据,管理数据
2.数据库的分类
SQL 关系型数据库
Mysql ,Ocacle,Sql Server,DB2,SQLite
通过表和表,列和列的关系进行数据的存储
NOSQL 非关系型数据库
Redis,MongDB
非关系型数据库,对象存储,类型JSON或者字典方式存储数据
3.命令行初见Mysql 1.登录 1 2 mysql -uroot -p123456 //-u用户名 -p密码
命令都是以;结尾的
2.查看数据库
3.切换数据库
4.查看数据库中的所有表
5.显示数据库中所有表的消息
6.退出
4.操作数据库
小提示,如果你的表名或者字段是一个特殊字符需要用``包起来
数据库->数据表>数据
1.创建数据库 1 2 CREATE DATABASE hello; CREATE DATABASE IF NOT EXISTS hello;
2.删除数据库 1 DROP DATABASE IF EXISTS hello;
5.数据库的列类型
数值
名称
存储数据的大小
占用的字节大小
tinyint
十分小的数据
1
smallint
较小的数据
2
mediumint
中等大小的数据
3
int
标准的整数(常用)
4
bigint
较大的数据
8
float
浮点数
4
double
浮点数(精度问题)
8
decimal
字符串形式的浮点数(金融)
9
字符串
名称
特点
长度范围
char
字符串固定大小的
0-255
varchar
可变字符串(常用)
0-65535
tinytext
微型文本
2^8-1
text
文本串
2^16-1
时间日期
名称
格式
date
YYYY-MM-DD
time
HH:MM:SS
datetime
YYYY-MM-DD HH:MM:SS(常用)
timestamp
时间戳(1970.1.1到现在的毫秒数 常用)
null
6.数据库的字段属性 Unsigned:
zerofill:
0填充
不足的位数,使用0来填充,int(3), 5->005
自增:
* 自动在是一条记录的基础上+1
* 通常来设置唯一的主键 index,必须是整数类型
* 可以自定义设置主键初始值和步长
非空 NULL not null:
默认:
规范
每个表都必须存在以下五个字段
1 2 3 4 5 id 主键 `version` 乐观锁 is_delete 伪删除 gmt_create 创建时间 gmt_update 修改时间
7.创建数据表 1 2 3 4 5 6 7 8 9 10 11 CREATE TABLE IF NOT EXISTS `student`( `id` INT(4) NOT NULL AUTO_INCREMENT COMMENT '学号', `name` VARCHAR(20) NOT NULL DEFAULT '匿名' COMMENT '姓名', `pwd` VARCHAR(20) NOT NULL DEFAULT '123456' COMMENT '密码', `birthday` DATETIME DEFAULT NULL COMMENT '出事日期', PRIMARY KEY ( `id` ) )ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE TABLE [IF NOT EXISTS] `表名`( `字段名` 列类型 [属性] [索引] [注释], )[表类型][字符集设置][注释]
查看创建数据库的语句
1 SHOW CREATE DATABASE xxx;
查看创建数据表的定义语句
显示表的结构
8.数据库引擎的区别
INNODB 默认使用
MYISAM 早些年使用的
特性
MYISAM
INNODB
事务支持
不支持
支持
数据行锁定
不支持
支持
外键约束
不支持
支持
全文索引
支持
不支持
表空间的大小
较小
较大,为两倍
常规使用操作:
MYISAM 节约空间,速度较快
INNODB 安全性高,事务的处理,多表多用户操作
在物理空间存在的位置
所有数据库文件都存储在data目录下,一个文件夹对应一个数据库
本质还是文件存储
MySQL引擎在物理文件上的区别
INNODB 在数据库表中只有一个*.frm文件,以及上级目录下的ibdata1文件
MYISAM 对应文件
*.frm - 表结构的定义文件
*.MYD 数据文件(data)
*.MYI 索引文件(index)
设置数据库的字符集
9.修改和删除表 1.修改表名 1 ALTER TABLE student RENAME lorin
2.增加表的字段 1 ALTER TABLE student ADD age INT(11)
3.修改表的字段
1 ALTER TABLE student CHANGE age age1 int(1)
1 ALTER TABLE student MODIFY age VARVHAR(11)
4.删除表的字段 1 ALTER TABLE student DROP age
5.删除表 1 DROP TABLE IF EXISTS student
注意:
字段名为了安全使用``包裹起来
注释 –
sql关键字大小写不敏感,建议大家写小写
10.MySQL数据库管理 1.外键(了解即可)
保证数据库的一致性,但是设置数据库层的外键会导致逻辑混乱.建议在应用层解决.
1 2 3 4 -- 定义外键key KEY `FK_gradeid` (`gradeid`) -- 给这个外键添加约束(执行引用) 到哪个表的那个键 CONSTRAINT `FK_gradeid` FOREIGN KEY ( `gradeid` ) REFERENCES `grade` ( `gradeid` )
1 2 -- 创建好表折后添加 ALTER TABLE `student` ADD CONSTRAINT `FK_gradeid` FOREIGN KEY(`gradeid`) REFERENCES `grade`(`gradeid`)
2.DML语言(全部记住) 1.添加 1 2 3 4 5 -- INSERT INTO 表名([字段1,字段2]) VALUES('值1','值2') -- 插入一条 INSERT INTO `grade` (`gradename`) VALUES('大四') -- 插入多条 INSERT INTO `grade` (`gradename`) VALUES('大一'),('大三')
2.更新 1 2 3 4 5 6 7 -- UPDATE `表名` SET `字段`='codelorin' WHERE 字段=1; UPDATE `grade` SET `gradename`='codelorin' WHERE gradeid=1; -- UPDATE `表名` SET `字段`='codelorin' -- 这样会修改所有的值 -- 修改多个 UPDATE `grade` SET `gradename`='codelorin',xxx=xxx WHERE gradeid=1;
where子句
操作符
含义
范围
结果
=
等于
5=6
false
<>或者!=
不低于
5<>6
true
>
大于
<
小于
<=
小于等于
BETWEEN…AND…
在某个范围内
[2,5]闭区间
AND
&&
5>1and 1>2
false
OR
||
注意:
数据库的列尽量带上``
条件没有指定会修改所有的列
value是一个具体的值也可以是变量(一般用于时间)
1 2 UPDATE `grade` SET `birthday`=CURRENT_TIME WHERE gradeid=1; -- CURRENT_TIME当前时间
3.删除 1 2 3 -- DELETE FROM grade WHERE gradeid =1
1 2 3 4 5 -- 删除所有数据 TRUNCATE `grade` TRUNCATE `表名` -- 删除所有数据 DELETE FROM grade
DELETE和TRUNCATE的区别
相同点:都能删除数据,都不会删除表结构
不同点:
TRUNCATE重新设置自增列 计数器会归零
TRUNCATE 不会影响事务
3.DQL查询数据(最重点)
Data Query LANGUAGE: 数据库查询语言
完整语法
1 2 3 4 5 6 7 select xxx from xxx join where group by 分组 having 过滤 order by 排序 limit 限制
1.全部
2.制定字段 1 SELECT * FROM `subject` WHERE `gradeid`=1
3. 别名 1 2 -- AS起别名 SELECT `studentno` AS 学号,`loginpwd` AS 密码 FROM student
4.函数
Concat 连接字符串
1 SELECT CONCAT('姓名:',studentname) AS 新名字 FROM student
系统版本
5.变量
自增
1 SELECT @@auto_increment_increment FROM `grade`
6.去重
distinct
1 SELECT DISTINCT `studentno` FROM result
7.where条件子句
逻辑运算符
8.模糊查询
重点
运算符
语法
描述
IS NULL
a is null
如果操作符为NULL,结果为真
IS NOT NULL
a is not null
如果操作符不为NULL,结果为真
BETWEEN
a between b and c
若a在b和c之间,则结果为真
LIKE
a like b
a相似匹配b
IN
a in(a1,a2)
假设a在a1或a2其中的某一个,结果为真
like结合 %(匹配0到任意一个字符) _(一个字符)
9.联表查询
JOIN
on和where的区别
on 是关联条件,where 则是查询条件
inner join
1 SELECT s.studentno,`studentname`,`subjectno`,`studentresult` FROM student as s INNER JOIN result as r WHERE s.studentno=r.studentno
left join
1 SELECT s.studentno,`studentname`,`subjectno`,`studentresult` FROM student as s left JOIN result as r ON s.studentno=r.studentno
right join
1 SELECT s.studentno,`studentname`,`subjectno`,`studentresult` FROM student as s RIGHT JOIN result as r ON s.studentno=r.studentno
操作
描述
inner join
两个表的数据都可以拿到
left join
会从左表返回所有的值,即使右表中没有匹配
right join
会从右表中返回所有的值,即使左表没有匹配
没有匹配实践
1 SELECT s.studentno,`studentname`,`subjectno`,`studentresult` FROM student as s RIGHT JOIN result as r ON s.studentno=r.studentno where studentresult is NULL
10.自连接
自己的表和自己的表连接,核心:一张表拆为两张一样的表即可
父类
categoryid
categoryname
2
信息技术
3
软件开发
5
美术设计
子类
pid
categoryid
categoryname
3
4
数据库
2
8
办公信息
3
6
web开发
5
7
pas技术
1 SELECT a.`categoryname` as 'father',b.`categoryname` as 'son' FROM `category` as a,`category` as b WHERE a.`categoryid`=b.`pid`
11.分页和排序
order by ASC升序 DESC降序
1 SELECT * from result ORDER BY studentresult DESC
分页 limit(下标,要几个)
规律: (n-1)*page size,page size
1 2 SELECT * from result LIMIT 0,2
12.子查询
where这个值是计算出来的
1 2 3 select xx from xx where xx=( select xx form xx where )
13.函数
绝对值
ABS()
向上取整
CEILING()
向下取整
FLOOR()
0-1的随机数
RAND()
判断一个数的符号 负数返回-1正数返回1
SIGN()
字符串长度
CHAR_LENGTH()
字符串拼接
CONCAT()
当前时间
CURRENT_DATE()
当前日期
CURRENT()
当前时间
NOW()
本地时间
LOCALTIME()
14.聚合函数
函数名称
描述
COUNT()
计数
SUM()
求和
AVG()
平均值
MAX()
最大值
MIN()
最小值
count()
1 2 3 count(xx) 会忽略null count(*) 不会忽略null count(1) 不会忽略null
分组过滤 group by
having
1 SELECT studentno,SUM(studentresult) 总成绩 FROM `result` GROUP BY studentno HAVING studentno!=1002
15.数据库级别的md5加密
md5(xxx)
总结 select 去重 字段 from 表
xx join 连接表 on 等值判断
where
group by 分组
having 过滤
order by 排序
limit 限制
11.事务
要不都成功,要不都失败
将一组sql放入一个批次中去执行
事务原则: ACID原则 脏读,幻读
原子性
A给B转账,B收到A转的钱,要不都成功,要不都失败
一致性
A有800元,B有200元无论怎么转,总价是1000
持久性
事务没有提交就恢复到原状,提交了就持久化到数据库
隔离性
多个用户访问数据库时,为每个用户开启事务,事务间互相隔离
隔离的问题
脏读:
指一个事务读取了另外一个事务没有提交的数据
不可重复读:
一个事务多次读取结果不同,不一定是错误可能是场合不同
虚读(幻读):
一个事物读取别的事务插入的数据,导致前后读取不一致
事务在sql层面的操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 set autocommit = -- 0 关闭事务 set autocommit = -- 1 开启事务(默认的) start transaction -- 标记一个事务的开启,一下执行的所有sql都在一个事务内 insert xx -- 提交 持久化(成功) commit -- 回滚 回到原来的状态(失败) rollback -- 事务结束 set autocommit = 1 -- 自动提交 -- 了解 savepoint -- 设置一个事务的保存点 rollback to savepoint -- 回滚到保存点 release savepoint -- 撤销保存点
12.索引
索引是帮助mysql实现高效获取数据的数据结构
1.索引的分类
主键索引(PRIMARY KEY)
唯一索引(UNIQUE KEY)
常规索引(KEY/INDEX)
全文索引(FullText)
用法:
索引名(列名)
1 alter table xxx add fulltext index `studentName` (`studentName`)
2.分析sql执行状况 1 2 explain xxxsql语句 explain select * from xx where match(studentName) against('liu')
插入100万条数据测试
1 2 3 4 5 6 7 8 9 10 11 12 CREATE TABLE `app_user` ( `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, `name` VARCHAR(50) DEFAULT '' COMMENT '用户昵称', `email` VARCHAR(50) NOT NULL COMMENT '用户邮箱', `phone` VARCHAR(20) DEFAULT '' COMMENT '手机号', `gender` TINYINT(4) UNSIGNED DEFAULT 0 COMMENT '性别(0:男;1:女)', `password` VARCHAR(100) NOT NULL COMMENT '密码', `age` TINYINT(4) DEFAULT 0 COMMENT '年龄', `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP, `update_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=INNODB DEFAULT CHARSET=utf8 COMMENT = 'app用户表'
1 2 3 4 5 6 7 8 9 10 11 12 13 14 DELIMITER $$ CREATE FUNCTION mock_data() RETURNS INT BEGIN DECLARE num INT DEFAULT 1000000; DECLARE i INT DEFAULT 0; WHILE i<num DO INSERT INTO `app_user`(`name`,`email`,`phone`,`gender`,`PASSWORD`,`age`)VALUES(CONCAT('用户',i),'19224305@qq.com',123456789,FLOOR(RAND()*2),UUID(),FLOOR(RAND()*100)); SET i=i+1; END WHILE; RETURN i; END; SELECT mock_data() -- 执行此函数 生成一百万条数据
1 2 3 4 -- 创建索引查看时间差别,数据结构yyds SELECT * FROM app_user WHERE `name`='用户999999' CREATE INDEX id_app_user_name ON app_user(`name`)
索引不是越多越好
不要对经常变动的数据增加索引
小数据的表不需要加索引
索引一般常用来查询的字段上
索引的数据结构
Btree: InnoDB默认的数据类型
13.权限管理 1.用户管理
本质是修改mysql下的user表
1 CREATE USER lorin IDENTIFIED BY '123456'
1 set password = password('123456')
1 set password for lorin=password('123456')
1 GRANT ALL PRIVILEGES ON *.* TO xxx
1 SHOW GRANTS FOR root @localhost
1 REMOVE ALL PRIVILEGES ON *.* FROM xxx
14.数据库的备份
保证重要的数据不丢失
数据转移
数据库命令行备份
1 mysqldump -hlocalhost -uroot -p123456 数据库名称 表 > D:/1.sql
数据库加载
1 2 source d:/1.sql mysql -uroot -p123456 库名<备份文件
15.数据库的设计
当数据库比较复杂的时候
设计数据库步骤:
收集信息,分析需求
用户表(用户登录注销,用户个人信息,写博客,创建分类)
分类表(文章分类,谁创建的)
文章表(文章的信息)
友链表(友链信息)
标识实体(把需求落实到每个字段)
标识实体之间的关系
写博客:user->blog
创建分类: user->category
关注:user->user
友链: links
评论: user->user->blog
16.三大范式
数据规范化
1.第一范式
原子性:要求每一列都是不可分割的最小原子数据项
2.第二范式
前提满足第一范式
需要保证数据库的每一列都和主键相关,而不能只和主键的某一部分相关
每张表只做一件事
3.第三范式
满足第一,二范式
每一列数据都和主键直接相关而不能间接相关
关联查询的表不能超过三张表
数据库性能在某些情况更加重要
规范性
故意给表增加一些冗余的字段(多表->单表)
故意增加一些计算列(索引)
17.JDBC(重点)
数据库驱动
1.导入数据库驱动 新建lib目录
可以展开即是导入成功
2.代码demo 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 package com.codeloirn.jdbc;import java.sql.*;public class Demo { public static void main (String[] args) throws ClassNotFoundException, SQLException { Class.forName("com.mysql.jdbc.Driver" ); String url = "jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=true" ; String username = "root" ; String password = "root" ; Connection connection = DriverManager.getConnection(url, username, password); Statement statement = connection.createStatement(); 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" )); } resultSet.close(); statement.close(); connection.close(); } }
connection
代表数据库
1 2 3 connection.setAutoCommit(); connection.commit(); connection.rollback();
statement
执行sql
1 2 3 statement.executeQuery(); statement.execute(); statement.executeUpdate();
ResultSet
1 2 3 4 resultset.getObjest(); resultset.getString(); resultset.getDate();
close 释放连接
1 2 3 resultSet.close(); statement.close(); connection.close();
3.CURD 1.create 1 2 3 4 5 6 Statement statement = connection.createStatement(); String sql = "insert into user() values()" ; int num = statement.executeUpdate(sql);if (num>0 ){ System.out.println("success!" ) }
2.update 1 2 3 4 5 6 Statement statement = connection.createStatement(); String sql = "update user set name ='' where name =''" ; int num = statement.executeUpdate(sql);if (num>0 ){ System.out.println("success!" ) }
3.read 1 2 3 4 5 6 Statement statement = connection.createStatement(); String sql = "SELECT * FROM users" ; ResultSet resultSet = statement.executeQuery(sql); while (resultSet.next()) { }
4.delete 1 2 3 4 5 6 Statement statement = connection.createStatement(); String sql = "delete from user where id=1" ; int num = statement.executeUpdate(sql);if (num>0 ){ System.out.println("success!" ) }
4.提取工具类
properties
1 2 3 4 driver =com.mysql.jdbc.Driver url =jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=true username =root password =root
Utils
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 package com.codeloirn.jdbc2.utils;import java.io.IOException;import java.io.InputStream;import java.sql.*;import java.util.Properties;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 inputStream = JdbcUtils.class.getClassLoader().getResourceAsStream("db.properties" ); Properties properties = new Properties(); properties.load(inputStream); 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 e) { e.printStackTrace(); } } if (st != null ) { try { st.close(); } catch (SQLException e) { e.printStackTrace(); } } if (conn != null ) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } }
main
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 package com.codeloirn.jdbc2;import com.codeloirn.jdbc2.utils.JdbcUtils;import java.sql.Connection;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;public class JdbcStudy { 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 users VALUES(7,'codelorin',123,'admin@l.cn','1980-12-04')" ; int i = st.executeUpdate(sql); if (i > 0 ) { System.out.println("success!" ); } } catch (SQLException e) { e.printStackTrace(); } finally { JdbcUtils.release(conn, st, null ); } } }
5.sql注入
安全问题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 package com.codeloirn.jdbc2;import com.codeloirn.jdbc2.utils.JdbcUtils;import java.sql.Connection;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;public class JdbcStudy { public static void main (String[] args) { String username = "'or' 1=1" ; String password = "'or' 1=1" ; Connection conn = null ; Statement st = null ; ResultSet rs = null ; try { conn = JdbcUtils.getConnection(); st = conn.createStatement(); String sql = "SELECT * FROM `users` WHERE `name`='" + username + "' and `password` ='" + password + "'" ; ResultSet resultSet = st.executeQuery(sql); while (resultSet.next()) { System.out.println(resultSet.getObject("name" )); System.out.println(resultSet.getObject("password" )); } } catch (SQLException e) { e.printStackTrace(); } finally { JdbcUtils.release(conn, st, null ); } } }
由于sql的逻辑运算符的原因,存在sql注入漏洞,会被攻击导致数据泄露.
6.解决sql注入问题
增删改
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 package com.codeloirn.jdbc3;import com.codeloirn.jdbc2.utils.JdbcUtils;import java.sql.*;import java.util.Date;public class Test { public static void main (String[] args) { Connection conn = null ; PreparedStatement st = null ; try { conn = JdbcUtils.getConnection(); String sql = "INSERT INTO users(id,`name`,`password`,`email`,`birthday`) VALUES(?,?,?,?,?)" ; st = conn.prepareStatement(sql); st.setInt(1 , 10 ); st.setString(2 , "lorin" ); st.setString(3 , "123321" ); st.setString(4 , "codelorin@163.com" ); st.setDate(5 , new java.sql.Date(new Date().getTime())); int i = st.executeUpdate(); if (i > 0 ) { System.out.println("success!" ); } } catch (SQLException e) { e.printStackTrace(); } finally { JdbcUtils.release(conn, st, null ); } } }
查
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 package com.codeloirn.jdbc2;import com.codeloirn.jdbc2.utils.JdbcUtils;import java.sql.*;public class JdbcStudy { public static void main (String[] args) { String username = "codelorin" ; String password = "123" ; Connection conn = null ; PreparedStatement st = null ; ResultSet rs = null ; try { conn = JdbcUtils.getConnection(); 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.getObject("name" )); System.out.println(rs.getObject("password" )); } } catch (SQLException e) { e.printStackTrace(); } finally { JdbcUtils.release(conn, st, null ); } } }
18.事务问题
ACID原则
原子性:要不都完成,要不都失败
一致性:总数不变
隔离性:多个进程互补干扰
持久性:一旦提交不可逆,持久化到数据库了
隔离性的问题
脏读:一个事务读取了另外一个没有提交的事务
不可重复读:在同一个事务内,重复读取表中的数据,表数据发生了改变
虚读(幻读):在一个事务内,读取到了别人插入的数据,导致前后读出来的结果不一致
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 package com.codeloirn;import com.codeloirn.jdbc2.utils.JdbcUtils;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;public class TransactionDemo { public static void main (String[] args) { Connection conn = null ; PreparedStatement st = null ; ResultSet rs = null ; try { conn = JdbcUtils.getConnection(); conn.setAutoCommit(false ); String sql1 = "update account set money = money-100 where name ='A'" ; st = conn.prepareStatement(sql1); st.executeUpdate(); String sql2 = "update account set money = money+100 where name ='B'" ; st = conn.prepareStatement(sql2); st.executeUpdate(); conn.commit(); System.out.println("success" ); } catch (SQLException e) { try { conn.rollback(); } catch (SQLException e1) { e1.printStackTrace(); } e.printStackTrace(); } finally { JdbcUtils.release(conn, st, null ); } } }
19.数据库连接池
数据库连接完毕,执行完毕,释放
连接释放十分浪费资源
池化技术:准备一些预先的资源,过来就连接预先准备好的
最小连接数:10
最大连接数:15
等待超时:100ms
编写连接池,实现DataSource接口
DBCP
C3P0
Druid:阿里巴巴
使用这些数据库连接池,我们就不需要编写连接数据库的代码了!
DBCP
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 driverClassName =com.mysql.jdbc.Driver url =jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=true username =root password =root initialSize =10 maxActive =50 maxIdle =20 minIdle =5 maxWait =60000 connectionProperties =useUnicode=true;characterEncoding=UTF8 defaultAutoCommit =true defaultReadOnly =defaultTransactionIsolation =READ_UNCOMMITTED
Dbcp工具类实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 package com.codeloirn.dbcp.utils;import org.apache.commons.dbcp.BasicDataSourceFactory;import javax.sql.DataSource;import java.io.InputStream;import java.sql.*;import java.util.Properties;public class JdbcUtilsDbcp { private static DataSource dataSource = null ; static { try { InputStream inputStream = JdbcUtilsDbcp.class.getClassLoader().getResourceAsStream("dbcpconfig.properties" ); Properties properties = new Properties(); properties.load(inputStream); 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 e) { e.printStackTrace(); } } if (st != null ) { try { st.close(); } catch (SQLException e) { e.printStackTrace(); } } if (conn != null ) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } }
demo
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 package com.codeloirn.dbcp;import com.codeloirn.dbcp.utils.JdbcUtilsDbcp;import com.codeloirn.jdbc2.utils.JdbcUtils;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.SQLException;import java.util.Date;public class Test { public static void main (String[] args) { Connection conn = null ; PreparedStatement st = null ; try { conn = JdbcUtilsDbcp.getConnection(); String sql = "INSERT INTO users(id,`name`,`password`,`email`,`birthday`) VALUES(?,?,?,?,?)" ; st = conn.prepareStatement(sql); st.setInt(1 , 12 ); st.setString(2 , "lorin111" ); st.setString(3 , "123321" ); st.setString(4 , "codelorin@163.com" ); st.setDate(5 , new java.sql.Date(new Date().getTime())); int i = st.executeUpdate(); if (i > 0 ) { System.out.println("success!" ); } } catch (SQLException e) { e.printStackTrace(); } finally { JdbcUtilsDbcp.release(conn, st, null ); } } }