mysql全面详解

Mysql 学习

1.安装mysql

安装MySQL

这里建议大家使用压缩版,安装快,方便.不复杂.

软件下载

mysql5.7 64位下载地址:

https://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7.19-winx64.zip

电脑是64位的就下载使用64位版本的!

安装步骤

1、下载后得到zip压缩包.

2、解压到自己想要安装到的目录,本人解压到的是D:\Environment\mysql-5.7.19

3、添加环境变量:我的电脑->属性->高级->环境变量

选择PATH,在其后面添加: 你的mysql 安装文件下面的bin文件夹

4、编辑 my.ini 文件 ,注意替换路径位置

[mysqld]
basedir=D:\Program Files\mysql-5.7\
datadir=D:\Program Files\mysql-5.7\data\
port=3306
skip-grant-tables

5、启动管理员模式下的CMD,并将路径切换至mysql下的bin目录,然后输入mysqld –install (安装mysql)

6、再输入 mysqld --initialize-insecure --user=mysql 初始化数据文件

7、然后再次启动mysql 然后用命令 mysql –u root –p 进入mysql管理界面(密码可为空)

8、进入界面后更改root密码

update mysql.user set authentication_string=password('123456') where user='root'and Host = 'localhost';

9、刷新权限

flush privileges;

10、修改 my.ini文件删除最后一句skip-grant-tables

11、重启mysql即可正常使用

net stop mysql
net start mysql

12、连接上测试出现以下结果就安装好了

img

2.数据库基本命令(命令行)

img

几个基本的数据库操作命令 :

update user set password=password('123456')where user='root'; 修改密码
flush privileges; 刷新数据库
show databases; 显示所有数据库
use dbname;打开某个数据库
show tables; 显示数据库mysql中所有的表
describe user; 显示表mysql数据库中user表的列信息
create database name; 创建数据库
use databasename; 选择数据库

exit; 退出Mysql
? 命令关键词 : 寻求帮助
-- 表示注释

3.操作数据库

命令行操作数据库

创建数据库 : create database [if not exists] 数据库名;

删除数据库 : drop database [if exists] 数据库名;

查看数据库 : show databases;

使用数据库 : use 数据库名;

数据值和列类型

列类型 : 规定数据库中该列存放的数据类型

数值类型

img

字符串类型

img

日期和时间型数值类型

img

NULL值

  • 理解为 “没有值” 或 “未知值”
  • 不要用NULL进行算术运算 , 结果仍为NULL

通常用图形化界面操作,稍作了解

创建表(CREATE TABLE)

CREATE TABLE IF NOT EXISTS `student` (
  `id` int(4) NOT NULL AUTO_INCREMENT COMMENT '学号',
  `name` varchar(30) NOT NULL DEFAULT '匿名' COMMENT '姓名',
  `pwd` varchar(20) NOT NULL DEFAULT '123456' COMMENT '密码'
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

如果忘记了怎么写可以查看以前表的语句

-- 查看数据库的定义
SHOW CREATE DATABASE school;
-- 查看数据表的定义
SHOW CREATE TABLE student;
-- 显示表结构
DESC student; 

修改表 ( ALTER TABLE )

修改表名 :ALTER TABLE 旧表名 RENAME AS 新表名

添加字段 : ALTER TABLE 表名 ADD字段名 列属性[属性]

修改字段 :

  • ALTER TABLE 表名 MODIFY 字段名 列类型[属性]
  • ALTER TABLE 表名 CHANGE 旧字段名 新字段名 列属性[属性]

删除字段 : ALTER TABLE 表名 DROP 字段名

删除数据表

语法:DROP TABLE [IF EXISTS] 表名

  • IF EXISTS为可选 , 判断是否存在该数据表
  • 如删除不存在的数据表会抛出错误

4.外键

外键

外键作用

保持数据一致性完整性,主要目的是控制存储在外键表中的数据,约束。使两张表形成关联,外键只能引用外表中的列的值或使用空值。

例子,student表的grandId引用grand表的grandId

ALTER TABLE `student`
ADD CONSTRAINT `FK_gradeid` FOREIGN KEY (`gradeid`) REFERENCES `grade` (`gradeid`);

注意 : 删除具有主外键关系的表时 , 要先删子表 , 后删主表

5.DML语言

5.1添加

INSERT命令

语法:

INSERT INTO 表名[(字段1,字段2,字段3,...)] VALUES('值1','值2','值3')
INSERT INTO grade(gradename) VALUES ('大一');

5.2修改

update命令

语法:

UPDATE 表名 SET column_name=value [,column_name2=value2,...] [WHERE condition];
UPDATE grade SET gradename = '高中' WHERE gradeid = 1;

5.3删除

DELETE命令

语法:

DELETE FROM 表名 [WHERE condition];
DELETE FROM grade WHERE gradeid = 5

6.查询(重点)

6.1简单查询

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}];
    --  指定查询的记录从哪条至哪条

注意 : [ ] 括号代表可选的 , { }括号代表必选得

查询全部

-- 查询所有学生信息
SELECT * FROM student;

查询指定字段

-- 查询指定列(学号 , 姓名)
SELECT studentno,studentname FROM student;

可以取别名,方便使用

-- 这里是为列取别名(当然as关键词可以省略)
SELECT studentno AS 学号,studentname AS 姓名 FROM student;

-- 使用as也可以为表取别名
SELECT studentno AS 学号,studentname AS 姓名 FROM student AS s;

-- 使用as,为查询结果取一个新名字
-- CONCAT()函数拼接字符串
SELECT CONCAT('姓名:',studentname) AS 新姓名 FROM student;

在这里插入图片描述

DISTINCT关键字的使用

作用 : 去掉SELECT查询返回的记录结果中重复的记录 ( 返回所有列的值都相同 ) , 只返回一条

-- # 查看哪些同学参加了考试(学号)  去除重复项
SELECT * FROM result; -- 查看考试成绩
SELECT studentno FROM result; --  查看哪些同学参加了考试
SELECT DISTINCT studentno FROM result; -- 了解:DISTINCT 去除重复项 , (默认是ALL)

使用表达式的列

在这里插入图片描述

-- 学员考试成绩集体提分一分查看
SELECT studentno,StudentResult+1 AS '提分后' FROM result;

在这里插入图片描述

6.2 where

-- 查询考试成绩在95-100之间的
SELECT Studentno,StudentResult
FROM result
WHERE StudentResult>=95 AND StudentResult<=100;
-- 除了1000号同学,要其他同学的成绩
SELECT studentno,studentresult
FROM result
WHERE studentno!=1000;

6.3模糊查询

模糊查询 :比较操作符

操作符名称语法描述
is nulla is null若操作符为空,则结果为真
is not nulla is not null若操作符不为空,则结果为真
betweena between b and c若a在b和c 之间,则结果为真
likea like b若a与b匹配,则结果为真
ina in(a1,a2,a3,…)若a对于a1,a2其中一个,则结果为真

like的使用

-- LIKE
-- =============================================
-- 查询姓刘的同学的学号及姓名
-- like结合使用的通配符 : % (代表0到任意个字符)  _ (一个字符)
SELECT studentno,studentname FROM student
WHERE studentname LIKE '刘%';

-- 查询姓刘的同学,后面只有一个字的
SELECT studentno,studentname FROM student
WHERE studentname LIKE '刘_';

-- 查询姓刘的同学,后面只有两个字的
SELECT studentno,studentname FROM student
WHERE studentname LIKE '刘__';

-- 查询姓名中含有 嘉 字的
SELECT studentno,studentname FROM student
WHERE studentname LIKE '%嘉%';

in的使用

-- IN
-- =============================================
-- 查询学号为1000,1001,1002的学生姓名
SELECT studentno,studentname FROM student
WHERE studentno IN (1000,1001,1002);

-- 查询地址在北京,南京,河南洛阳的学生
SELECT studentno,studentname,address FROM student
WHERE address IN ('北京','南京','河南洛阳');

6.4联表查询

JOIN 对比

操作符名称描述
inner join如果表中至少有一个匹配,则返回行
left join即使右表中没有匹配,也从左表中返回行
right join即使左表中没有匹配,也从右表中返回行
-- 查询参加了考试的同学信息(学号,学生姓名,科目名,分数)
SELECT s.studentno,studentname,subjectname,StudentResult
FROM student s
INNER JOIN result r
ON r.studentno = s.studentno
INNER JOIN `subject` sub
ON sub.subjectno = r.subjectno

自连接

将一个表看成两个一样的表

在这里插入图片描述

SELECT a.categoryName AS '父栏目',b.categoryName AS '子栏目'
FROM category AS a,category AS b
WHERE a.`categoryid`=b.`pid`

在这里插入图片描述

6.5分页和排序

排序

降序

ORDER BY StudentResult DESC

升序

ORDER BY StudentResult ASC

分页

limit

推导:
    第一页 : limit 0,5
    第二页 : limit 5,5
    第三页 : limit 10,5
    ......
    第N页 : limit (pageNo-1)*pageSzie,pageSzie
    [pageNo:页码,pageSize:单页面显示条数]

6.6子查询

-- 查询 数据库结构-1 的所有考试结果(学号,科目编号,成绩),并且成绩降序排列
SELECT studentno,subjectno,StudentResult
FROM result
WHERE subjectno=(
   SELECT subjectno FROM `subject`
   WHERE subjectname = '数据库结构-1'
)
ORDER BY studentresult DESC;

6.7分组和过滤

GROUP BY 按什么分组
HAVING 分组的过滤条件
-- 查询不同课程的平均分,最高分,最低分
 -- 前提:根据不同的课程进行分组
 
 SELECT subjectname,AVG(studentresult) AS 平均分,MAX(StudentResult) AS 最高分,MIN(StudentResult) AS 最低分
 FROM result AS r
 INNER JOIN `subject` AS s
 ON r.subjectno = s.subjectno
 GROUP BY r.subjectno
 HAVING 平均分>80;
 
 /*
 where写在group by前面.
 要是放在分组后面的筛选
 要使用HAVING..
 因为having是从前面筛选的字段再筛选,而where是从数据表中的>字段直接进行的筛选的
 */

7.函数

7.1常用函数

数据函数

 SELECT ABS(-8);  /*绝对值*/
 SELECT CEILING(9.4); /*向上取整*/
 SELECT FLOOR(9.4);   /*向下取整*/
 SELECT RAND();  /*随机数,返回一个0-1之间的随机数*/
 SELECT SIGN(0); /*符号函数: 负数返回-1,正数返回1,0返回0*/

字符串函数

 SELECT CHAR_LENGTH('狂神说坚持就能成功'); /*返回字符串包含的字符数*/
 SELECT CONCAT('我','爱','程序');  /*合并字符串,参数可以有多个*/
 SELECT INSERT('我爱编程helloworld',1,2,'超级热爱');  /*替换字符串,从某个位置开始替换某个长度*/
 SELECT LOWER('KuangShen'); /*小写*/
 SELECT UPPER('KuangShen'); /*大写*/
 SELECT LEFT('hello,world',5);   /*从左边截取*/
 SELECT RIGHT('hello,world',5);  /*从右边截取*/
 SELECT REPLACE('狂神说坚持就能成功','坚持','努力');  /*替换字符串*/
 SELECT SUBSTR('狂神说坚持就能成功',4,6); /*截取字符串,开始和长度*/
 SELECT REVERSE('狂神说坚持就能成功'); /*反转
 
 -- 查询姓周的同学,改成邹
 SELECT REPLACE(studentname,'周','邹') AS 新名字
 FROM student WHERE studentname LIKE '周%';

日期和时间函数

 SELECT CURRENT_DATE();   /*获取当前日期*/
 SELECT CURDATE();   /*获取当前日期*/
 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 VERSION();  /*版本*/
 SELECT USER();     /*用户*/

7.2聚合函数

函数名称描述
COUNT()返回满足Select条件的记录总和数,如 select count(*) 【不建议使用 *,效率低】
SUM()返回数字字段或表达式列作统计,返回一列的总和。
AVG()通常为数值字段或表达列作统计,返回一列的平均值
MAX()可以为数值字段,字符字段或表达式列作统计,返回最大的值。
MIN()可以为数值字段,字符字段或表达式列作统计,返回最小的值。
SELECT COUNT(*) FROM student;
 SELECT SUM(StudentResult) AS 总和 FROM result;
 SELECT AVG(StudentResult) AS 平均分 FROM result;
 SELECT MAX(StudentResult) AS 最高分 FROM result;
 SELECT MIN(StudentResult) AS 最低分 FROM result;

8.事务

什么是事务

  • 事务就是将一组SQL语句放在同一批次内去执行
  • 如果一个SQL语句出错,则该批次内的所有SQL都将被取消执行
  • MySQL事务处理只支持InnoDB和BDB数据表类型

事务的ACID原则

原子性(Atomic)

  • 在整个事务中,要么都成功要么都失败。比如a向b转账,a转出钱和b转入钱,要么都成功,要么都失败。不会存在a向b转账的过程中服务器崩了,导致钱的数据丢失。

一致性(Consist)

  • 一个事务可以封装状态改变(除非它是一个只读的)。事务必须始终保持系统处于一致的状态,不管在任何给定的时间并发事务有多少。也就是说A和B的账户一共有1000元,那么不管A和B怎么转账A和B的总金额保持一致,这就是保护性和不变性。

隔离性(Isolated)

  • 隔离状态执行事务,使它们好像是系统在给定时间内执行的唯一操作。如果有两个事务,运行在相同的时间内,执行相同的功能,事务的隔离性将确保每一事务在系统中认为只有该事务在使用系统。比如A和B在进行转账操作时,如果有C向A转账则会被认为是另一个事务,不会影响A和B的事务

持久性(Durable)

  • 在事务完成以后,该事务对数据库所作的更改便持久的保存在数据库之中,并不会被回滚。
  • 若数据没有被提交则恢复到原来状态,若数据已经被提交,则持久化到数据库中,事务一旦提交就不可逆了。

基本语法

-- 使用set语句来改变自动提交模式
SET autocommit = 0;   /*关闭*/
SET autocommit = 1;   /*开启*/

-- 注意:
---  1.MySQL中默认是自动提交
---  2.使用事务时应先关闭自动提交

-- 开始一个事务,标记事务的起始点
START TRANSACTION  

-- 提交一个事务给数据库
COMMIT

-- 将事务回滚,数据回到本次事务的初始状态
ROLLBACK

-- 还原MySQL数据库的自动提交
SET autocommit =1;

-- 保存点
SAVEPOINT 保存点名称 -- 设置一个事务保存点
ROLLBACK TO SAVEPOINT 保存点名称 -- 回滚到保存点
RELEASE SAVEPOINT 保存点名称 -- 删除保存点

测试

SET autocommit = 0
START TRANSACTION 
UPDATE ACCOUNT SET cash=cash-500 WHERE `name`='A';
UPDATE ACCOUNT SET cash=cash+500 WHERE `name`='B';
COMMIT;
--rollback;
SET autocommit = 1;

9.规范化数据库设计

为什么需要数据库设计

当数据库比较复杂时我们需要设计数据库

糟糕的数据库设计 :

  • 数据冗余,存储空间浪费
  • 数据更新和插入的异常
  • 程序性能差

良好的数据库设计 :

  • 节省数据的存储空间
  • 能够保证数据的完整性
  • 方便进行数据库应用系统的开发

软件项目开发周期中数据库设计 :

  • 需求分析阶段: 分析客户的业务和数据处理需求
  • 概要设计阶段:设计数据库的E-R模型图 , 确认需求信息的正确和完整.

设计数据库步骤

  • 收集信息

    • 与该系统有关人员进行交流 , 座谈 , 充分了解用户需求 , 理解数据库需要完成的任务.
  • 标识实体[Entity]

    • 标识数据库要管理的关键对象或实体,实体一般是名词
  • 标识每个实体需要存储的详细信息[Attribute]

  • 标识实体之间的关系[Relationship]

10.三大范式

为什么需要数据规范化?

不合规范的表设计会导致的问题:

  • 信息重复

  • 更新异常

  • 插入异常

    • 无法正确表示信息
  • 删除异常

    • 丢失有效信息

第一范式(1NF):要求数据库表的每一列都是不可分割的原子数据项。

img

如上图就不符合第一范式,应该调整如下

img

第二范式(2NF):在1NF的基础上,非码属性必须完全依赖于候选码(在1NF基础上消除非主属性对主码的部分函数依赖)

第二范式需要确保数据库表中的每一列都和主键相关,而不能只与主键的某一部分相关(主要针对联合主键而言)。

保证每张表只描述一件事

举例说明:

img

在上图所示的情况中,同一个订单中可能包含不同的产品,因此主键必须是“订单号”和“产品号”联合组成,

但可以发现,产品数量、产品折扣、产品价格与“订单号”和“产品号”都相关,但是订单金额和订单时间仅与“订单号”相关,与“产品号”无关,

这样就不满足第二范式的要求,调整如下,需分成两个表:

img img

第三范式(3NF):在2NF基础上,任何非主属性不依赖于其它非主属性(在2NF基础上消除传递依赖)

第三范式需要确保数据表中的每一列数据都和主键直接相关,而不能间接相关。

举例说明:

img

上表中,所有属性都完全依赖于学号,所以满足第二范式,但是“班主任性别”和“班主任年龄”直接依赖的是“班主任姓名”,

而不是主键“学号”,所以需做如下调整:

img img

这样以来,就满足了第三范式的要求。

11.JDBC

11.1 数据库驱动

应用程序无法自主的调用数据库,不同的数据库需要不同的数据库驱动来操作数据库。

11.2 JDBC测试

用于对数据库的统一操作,可以称为数据库的规范,我们只需要会操作Jsbc就可以实现对数据库的操作。

导入驱动

新建lib目录,把jar包放入lib文件夹,add as library

在这里插入图片描述

jdbc 测试

package com.chen.lesson01;

import java.sql.*;

public class JDBCFirst {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        //1.加载驱动
        Class.forName("com.mysql.jdbc.Driver");
        //2.用户信息和url
        //userUnicode=true&characterEncoding=utf8&useSSL=true,支持中文编码,设置utf8编码格式,启用安全连接
        String url = "jdbc:mysql://localhost:3306/jdbcstudy?userUnicode=true&characterEncoding=utf8&useSSL=true";
        String username = "root";
        String pwd = "123456";
        //3.连接成功,创建数据库对象   connection 表示数据库对象
        Connection connection = DriverManager.getConnection(url, username, pwd);
        //4.执行sql对象  statement 执行SQL的对象
        Statement statement = connection.createStatement();
        //5.执行sql语句,返回结果集 resultset
        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("============================");
        }
        //6.释放连接
        resultSet.close();
        statement.close();
        connection.close();
    }

}

步骤

1.加载驱动
2.用户信息和url
3.连接成功,创建数据库对象 connection 表示数据库对象
4.执行sql对象 statement 执行SQL的对象
5.执行sql语句,返回结果集 resultset
6.释放连接

11.3 JDBC工具类的编写

先将参数信息保存到资源文件db.properties

driver = com.mysql.jdbc.Driver
url = jdbc:mysql://localhost:3306/jdbcstudy?userUnicode=true&characterEncoding=utf8&useSSL=true
username = root
pwd = 123456

编写工具类

package com.chen.lesson02.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 pwd= 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");
            pwd=properties.getProperty("pwd");
            //加载驱动
            Class.forName(driver);
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    //获取连接
    public static Connection getConnection() throws SQLException {
        return DriverManager.getConnection(url,username,pwd);
    }
    //释放资源
    public static void release(Connection cn, 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(cn!=null){
            try {
                cn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

}

测试调用工具类

package com.chen.lesson02;

import com.chen.lesson02.utils.JdbcUtils;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class TestInsert {
    public static void main(String[] args) {
        Connection coon = null;
        Statement st = null;
        ResultSet rs = null;
        try {
            coon = JdbcUtils.getConnection();//获取数据库连接
            st = coon.createStatement();
            String sql = "INSERT INTO users(`id`,`NAME`,`PASSWORD`,`email`,`birthday`)\n" +
                    "VALUES(5,'czt','123456','1453201694@qq.com','2020-01-01')";
            int i =st.executeUpdate(sql);
            if (i>0){
                System.out.println("插入成功");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JdbcUtils.release(coon,st,rs);
        }
    }
}

11.4 sql注入问题

sql存在问题,可以通过拼接字符串,恶意访问数据库,导致数据泄露

使用PreparedStatement对象可以防止sql注入

PreparedStatement使用方式

package com.chen.lesson02;

import com.chen.lesson02.utils.JdbcUtils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class TestInsert02 {
    public static void main(String[] args) {
        Connection cn = null;
        PreparedStatement st = null;

        try {
            cn = JdbcUtils.getConnection();
            String sql = "INSERT INTO users(`id`,`NAME`,`PASSWORD`,`email`,`birthday`)VALUES(?,?,?,?,?)";
            st = cn.prepareStatement(sql);//预编译
            st.setObject(1,4);
            st.setObject(2,"czt");
            st.setObject(3,"123456");
            st.setObject(4,"1453201694@qq.com");
            st.setObject(5,"2020-01-01");
            int i = st.executeUpdate();
            if(i>0){
                System.out.println("成功");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JdbcUtils.release(cn,st,null);
        }
    }

}

PreparedStatement会先预编译sql语句,通过传参的方式给sql语句赋值,当有sql注入时其中的转义字符如’'会被转义,从而达到防止sql注入的效果

11.5 idea实现事务

基本结构

cn.setAutoCommit(false);//关闭数据库自动提交,同时会开启事务

sql语句

cn.commit();

如果事务执行失败则默认回滚

package com.chen.lesson02;

import com.chen.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 cn = null;
        PreparedStatement st = null;
        ResultSet rs = null;

        try {
            cn = JdbcUtils.getConnection();

            cn.setAutoCommit(false);
            //关闭数据库自动提交,同时会开启事务
            String sql1 = "update account set money = money-100 where name = 'A'";
            st = cn.prepareStatement(sql1);
            st.executeUpdate();

            String sql2 = "update account set money = money+100 where name = 'B'";
            st = cn.prepareStatement(sql2);
            st.executeUpdate();

            cn.commit();
        } catch (SQLException e) {
            e.printStackTrace();
            try {
                cn.rollback();
            } catch (SQLException ex) {
                ex.printStackTrace();
            }
        }finally {
            JdbcUtils.release(cn,st,rs);
        }
    }
}

11.6数据库连接池

数据库连接过程:

数据库连接—执行—释放连接

浪费资源

池化技术:预先准备一些数据连接

打个比方,银行服务:

没有连接池:开门—服务–关门

有连接池:开门–业务员–服务

  • 1
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值