MYSQL操作详细操作
1. 什么是事物?
要么都成功,要么都失败
1.SQL执行 A 给 B 转账 A 1000 ---->200 B 200
2.SQL执行 B收到A的钱 A 800 -----> B 400
将一组SQL放在一个批次中去执行
事物原则:ACID 原则 原子性(atomicity),一致性(consistency),隔离性(isolation),持久性(durability) (脏读,幻读。。。)
- 
Atomicity(原子性):要么都成功,要么都失败。 
- 
一致性(Consistency):事务前后的数据完整性要保持一致。 
- 
持久性(durability):事务一旦提交则不可逆,被持久化到数据库中! 
- 
隔离性(isolation):事物的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启事务,不能被其他事物的操作数据所干扰之间要相互隔离。 
- 
隔离会导致的问题: - 
脏读 
- 
不可重复读 
- 
幻读 
 
- 
2.执行事务
-- =========事物==========
-- mysql 是默认开启事物自动提交的
SET autocommit = 0 -- 关闭
SET autocommit = 1 -- 开启
-- 手动处理事务
SET autocommit = 0 -- 关闭自动条件
-- 事务开启
START TRANSACTION -- 标记一个事务开始,从这个之后 sql 都处在同一事务
INSERT xx
INSERT xx
-- 提交,持久化(成功!)
COMMIT
-- 回滚,回到原来的样子(失败)
ROLLBACK
-- 事务结束
SET autocommit = 1 -- 开启自动提交
-- 了解
SAVEPOINT  保存点名 -- 设置一个事务保存点
ROLLBACK TO SAVEPOINT 保存点名 -- 回滚保存点
RELEASE SAVEPOINT 保存点名  -- 撤销保存点
模拟场景:
-- === 模拟转账 ===
INSERT INTO `shop`.`account`(`name`,`money`)VALUES('A',2000.00),('B',10000.00);
-- 模拟转账:事务
SET autocommit = 0; -- 关闭自动提交
START TRANSACTION -- 开启一个事务(一组事务)
UPDATE `shop`.`account` SET `money` = `money` - 500 WHERE `name` = 'A'; -- A减500
UPDATE `shop`.`account` SET `money` = `money` + 500 WHERE `name` = 'B'; -- B加500
COMMIT; -- 提交事务,就被持久化了!
ROLLBACK; -- 回滚
SET autocommit = 1; -- 恢复默认值
3.索引
MySQL官方对索引的定义为:索引 (Index)是帮助MySQL高效获取数据的数据结构。提取句子主干,就可以得到索引的本质:索引是数据结构。
- 
索引的分类 - 
主键索引(PRIMARY KEY) - 
唯一的标识:主键不可重复,只能有一个列作为主键。 
 
- 
- 
唯一索引(UNIQUE KEY) - 
避免面重复的列出现,唯一索引可以重复,多个列都可以标识为唯一索引。 
 
- 
- 
常规索引 ( KEY / INDEX ) - 
默认的,Index、Key关键字设置 
 
- 
- 
全文索引( FullText ) - 
在特定数据库引擎下才有,MYSAM 
 
- 
 
- 
- 
基础语法: -- 索引的使用
 -- 1、在创建表的时候给字段增加索引
 -- 2、创建完毕后,增加索引
 
 -- 显示所有的索引信息
 SHOW INDEX FROM `school`.`student`
 
 -- 增加一个索引
 ALTER TABLE `school`.`student` ADD FULLTEXT INDEX `name`(`name`)
 
 -- EXPLAIN 分析sql执行的状况
 EXPLAIN SELECT * FROM `school`.`student` -- 非全文索引
 
 EXPLAIN SELECT * FROM `school`.`student` WHERE MATCH(`name`) AGAINST ('yi')
 
4.测试索引
 INSERT INTO `school`.`app_user`(`name`,`email`,`phone`,`gender`,`password`,`age`) 
        VALUES(CONCAT('用户',2),'173@11.com',CONCAT('18',FLOOR(RAND()*100000000)),FLOOR(RAND()*2),UUID(),FLOOR(RAND()*100)),
        (CONCAT('用户',3),'173@11.com',CONCAT('18',FLOOR(RAND()*100000000)),FLOOR(RAND()*2),UUID(),FLOOR(RAND()*100)),
        (CONCAT('用户',4),'173@11.com',CONCAT('18',FLOOR(RAND()*100000000)),FLOOR(RAND()*2),UUID(),FLOOR(RAND()*100)),
        (CONCAT('用户',5),'173@11.com',CONCAT('18',FLOOR(RAND()*100000000)),FLOOR(RAND()*2),UUID(),FLOOR(RAND()*100)),
        (CONCAT('用户',6),'173@11.com',CONCAT('18',FLOOR(RAND()*100000000)),FLOOR(RAND()*2),UUID(),FLOOR(RAND()*100));
 
SELECT * FROM `school`.`app_user` WHERE `name` = '用户1';
EXPLAIN SELECT * FROM `school`.`app_user` WHERE `name` = '用户1';
CREATE INDEX id_name ON `school`.`app_user`(`name`)
EXPLAIN SELECT * FROM `school`.`app_user` WHERE `name` = '用户1';

索引在小数据的时候,用处不打。但是在大数据的时候,区别十分明显~
5.索引原则
- 
索引不是越多越好。 
- 
不要对进程变动数据加索引。 
- 
小数据量的表不需要加索引。 
- 
索引一般加载常用来查询的字段上。 
索引的数据结构:
Hash 类型的索引
Btree:InnoDB的默认数据结构~
阅读:
数据库备份。权限管理。数据库的归约,三大范式。JDBC。
6.权限管理和备份
- 
用户管理: ![]() SQL命令操作: 1. 用户表:mysql.user
 1. 本质:读这张表进行增删改查
-- 创建用户
CREATE USER yuan1 IDENTIFIED BY '123456';
-- 修改密码 (修改当前用户密码)
SET PASSWORD = PASSWORD('123456');
-- 修改密码(修改指定用户密码)
SET PASSWORD FOR yuan =PASSWORD('111111');
-- 重命名 RENAME USER 原来名字 TO 新名字
RENAME USER yuan TO yuan2
-- 用户授权 ALL PRIVILEGES 全部的权限,库,表
-- ALL PRIVILEGES 除了给别人授权,其他都能干
GRANT ALL PRIVILEGES ON *.* TO yuan
-- 查询权限
SHOW GRANTS FOR yuan -- 查看指定用户权限
SHOW GRANTS FOR root@localhost
-- ROOT用户权限;GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION
-- 撤销权限  REVOKE 哪些权限,在哪个库撤销,给谁撤销
REVOKE ALL PRIVILEGES ON *.* FROM yuan
-- 删除用户
DROP USER yuan
7.MySQL备份
为什么要备份:
- 
保证重要的数据不丢失。 
- 
数据转移 
MySQL数据库备份的方式
- 
直接拷贝物理文件 
- 
在Sqlyog 这种可视化工具中手动导出: - 
在想要导出的表或者库中,右键,选择备份或导出。 ![]() 
- 
使用命令行到处 mysqldump 命令行使用 # mysqldump -h 主机 -u 用户名 -p密码 数据库 表名 > 物理磁盘位置、文件名
 mysqldump -h localhost -uroot -p123456 school student >D:/a.sql
 # mysqldump -h 主机 -u 用户名 -p密码 数据库 表1 表2 表3 > 物理磁盘位置、文件名
 
 # 导入
 # 登录的情况下,切换到指定的数据库
 # source 备份文件
 souce D:/a.sql
 
 #非登录情况下
 mysql -u用户名 -p密码 库名< 备份文件假设你要备份数据库,防止数据丢失。 把数据库给朋友!sql文件给别人即可 
 8.规范数据库设计- 
为什么需要设计? 当数据库比较复杂的时候,我们需要设计。 糟糕的数据库设计: - 
数据冗余,浪费空间。 
- 
数据插入和删除都会麻烦。异常【屏蔽使用物理瓦检】 
- 
程序性能差 
 良好的数据库设计: - 
节省内存空间 
- 
保证数据库完整性 
- 
方便我们开发系统 
 软件开发中,关于数据库的设计 * 分析需求:分析业务和需要处理的数据库的需求
 
 * 概要设计:设计关系图 E- R 图设计数据库步骤:(个人博客类似) - 
收集信息、分析需求 ** 用户表(用户登录注销,用户个人信息,写博客,创建分类) ** 分类表(文章分类,谁创建的) ** 文章表(文章的信息) ** 友链表(友链信息) ** 自定义表(系统信息,某个关键的字,或者一些主字段) ** 说说表(发表心情.. id... content ) key:value 
- 
标识实体(把需求落地到每个字段) 
- 
标识 实体之间的关系 ** 写博客:user—> blog ** 创建分类:user—> category ** 关注:user—>user ** 友链:links ** 评论:user-user-blog 
 
- 
 
- 
9.三大范式
为什么需要数据规范化?
- 
信息重复 
- 
更新异常 
- 
插入异常 - 
无法正常显示信息 
 
- 
- 
删除异常 - 
丢失有效的信息 
 
- 
三大范式:
第一范式(1NF):
原子性:保证每一列不可再分。
第二范式(2NF):
前提:满足第一范式。每张表只描述一件事情。
第三范式(3NF):
前提:满足第一范式和第二范式。
第三范式需要确保数据表中的每一列数据都和主键直接相关。而不能间接相关。
(规范数据库的设计)
规范性 和 性能的问题
关联查询的表不得超过三张表
- 
考虑商业化的需求和目标。(成本,用户体验!)数据库性能更加重要。 
- 
在规范性能问题的时候,适当考虑规范性。 
- 
故意给某些表增加一些字段(从多表查询变为单表查询) 
- 
故意增加一些计算列(从大数据量,降低为小数据量的查询:索引) 
10.JDBC(重点)
- 
数据库驱动:程序需要通过数据库驱动连接上数据库,再和数据库打交道! 
- 
JDBC:SUN公司为了简化开发人员的(对数据库的统一)操作,提供了一个(Java操作数据库)规范,俗称JDBC。这些规范的实现由具体的厂商去做! 对于开发人员,我们只需要掌握JDBC接口操作即可。 ![]() 
java.sql
javax.sql
还需要导入一个数据库驱动包 mysql-connector-java-5.1.47.jar
11.第一个JDBC程序
- 
创建一个项目 
- 
导入数据库 

copy进lib后右键 Add as library
- 
代码建立连接 import java.sql.*;
 
 // 我的第一个JDBC 程序
 public class JdbcFirst {
 public static void main(String[] args) throws ClassNotFoundException, SQLException {
 // 1.加载驱动
 Class.forName("com.mysql.cj.jdbc.Driver"); //固定写法,加载驱动
 // 2.连接信息 用户信息和 url
 String url = "jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&charcterEncoding=utf8&useSSL=true";
 // String url = "jdbc:mysql://localhost:3306";
 String username= "root";
 String password = "123456";
 // 3.连接成功,数据库对象 Connection 代表数据库
 Connection connection = DriverManager.getConnection(url,username,password);
 // 4.执行SQL的对象 Statement 执行sql对象
 Statement statement=connection.createStatement();
 // 5.执行SQL的对象 去 执行SQL,可能存在结果,查看返回的结果
 String sql = "SELECT * FROM `jdbcstudy`.`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("birth="+resultSet.getObject("birthday"));
 System.out.println("==========");
 }
 // 6.释放连接
 resultSet.close();
 statement.close();
 connection.close();
 }
 }
 步骤总结: - 
加载驱动。Class.forName("com.mysql.cj.jdbc.Driver") 
- 
连接数据库DriverManager。 Connection connection = DriverManager.getConnection(url,username,password); 
- 
获得sql的对象。 Statement Statement statement=connection.createStatement(); 
- 
获得返回的结果集。ResultSet resultSet=statement.executeQuery(sql); 
- 
释放连接。.close() 
 DriverManager 
- 
  //DriverManager.registerDriver(new com.mysql.cj.jdbc.Driver());
        Class.forName("com.mysql.cj.jdbc.Driver"); //固定写法,加载驱动
// 3.连接成功,数据库对象 Connection 代表数据库
        Connection connection = DriverManager.getConnection(url,username,password);
// connection 代表数据库
// 数据库设置自动提交
// 事务提交
// 事务回滚
// connection代表数据库所能干的事
connection.rollback();
connection.commit();
connection.setAutoCommit();
URL
// 2.连接信息 用户信息和 url
        String url = "jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&charcterEncoding=utf8&useSSL=true";
// mysql -- 3306
// jdbc:mysql://主机地址:端口号/数据库名?参数1&参数2&参数3
// oralce -- 1521
//jdbc:oracle:thin:@localhost:1521:sid
Statement 执行SQL的对象 PrepareStatement
String sql = "SELECT * FROM `jdbcstudy`.`users`"; //编写SQL
statement.executeQuery(); // 查询操作返回 Result
statement.execute(); // 执行任何SQL
statement.executeUpdate() // 更新、插入、删除,返回一个受影响的函数
ResultSet 查询的结果集:封装了所有的查询结果
resultSet.getObject() //在不知道列的类型
 // 如果知道列的类型就用指定类型
resultSet.getString() 
resultSet.getInt()
resultSet.getFloat()
resultSet.getDate()
resultSet.getObject()
...
遍历,指针
resultSet.beforeFirst() // 移动到最前面
resultSet.afterLast() // 移动到最后面
resultSet.next() // 移动到下一个数据
resultSet.previous() // 移动到前一行
resultSet.absolute(row) // 移动到指定行
释放资源
// 6.释放连接
resultSet.close();
statement.close();
connection.close();
12.statement对象
Jdbc中的statement对象用于向数据库发送SQL语句,想完成对数据库的增删改查,只需要通过这个对象向数据库发送增删改查语句即可。
Statement对象的executeUpdate方法,用于向数据库发送增、删、改的sql语句,executeUpdate执行完后,将会返回一个整数(即增删改语句导致了数据库几行数据发生了变化)。
Statement.executeQuery方法用于向数据库发送查询语句,executeQuery方法返回代表查询结果的ResultSet对象。
CRUD操作-create
使用executeUpdate(String sql)方法完成数据添加操作,示例操作:
Statement str = connection.createStatement();
String sql = "insert into user(...) values(...)";
int num = str.executeUpdate(sql);
if(num > 0){
    System.out.println("输入成功!!")
}
CRUD操作 - delete
使用executeUpdate(String sql)方法完成数据删除操作,示例操作:
Statement str = connection.createStatement();
String sql = "delete from user where id = 1";
int num = str.executeUpdate(sql);
if(num > 0){
    System.out.println("删除成功!!")
}
CRUD操作 - update
使用executeUpdate(String sql)方法完成数据修改操作,示例操作:
Statement str = connection.createStatement();
String sql = "update user set name='' where id = 1";
int num = str.executeUpdate(sql);
if(num > 0){
    System.out.println("修改成功!!")
}
CURD操作 - read
使用executeQuery(String sql)方法完成数据查询操作,示例操作:
Statement str = connection.createStatement();
String sql = "select * from users where id = 1";
int num = str.executeQuery(sql);
if(num.next()){
    System.out.println("查询成功!!")
}
代码实现
- 
提取工具类 driver=com.mysql.cj.jdbc.Driver
 url=jdbc:mysql://localhost:3306/jdbcstudy?userUnicode=true&characterEncoding=utf8&useSSL=true
 username=root
 password=123456package com.yuan.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 password = null;
 
 
 static {
 try {
 InputStream in = JdbcUtils.class.getClassLoader().getResourceAsStream("dp.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 (IOException e){
 e.printStackTrace();
 } catch (ClassNotFoundException e) {
 throw new RuntimeException(e);
 }
 }
 // 获取连接
 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) {
 throw new RuntimeException(e);
 }
 }
 if(st != null){
 try {
 st.close();
 } catch (SQLException e) {
 throw new RuntimeException(e);
 }
 }
 if(conn != null){
 try {
 conn.close();
 } catch (SQLException e) {
 throw new RuntimeException(e);
 }
 }
 }
 
 }
- 
编写增删改查 executeUpdate() package com.yuan.lesson02.utils;
 
 
 import java.sql.Connection;
 import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.sql.Statement;
 import com.yuan.lesson02.utils.JdbcUtils;
 
 public class TestInsert {
 public static void main(String[] args) {
 Connection conn = null;
 Statement st = null;
 ResultSet rs =null;
 JdbcUtils JdbcUtils = new JdbcUtils();
 try {
 conn = JdbcUtils.getConnection(); //获取数据库连接
 st = conn.createStatement(); // 获取SQL执行对象
 String sql = "INSERT INTO `jdbcstudy`.`users`(`id`,`name`,`password`,`email`,`birthday`) VALUES(5,'HEQI','123456','HQ@163.com','1990-11-11')";
 int i = st.executeUpdate(sql);
 if(i>0){
 System.out.println("插入成功");
 }
 } catch (SQLException e) {
 throw new RuntimeException(e);
 }finally {
 JdbcUtils.release(conn,st,rs);
 }
 
 }
 }package com.yuan.lesson02.utils;
 
 import com.yuan.lesson02.utils.JdbcUtils;
 
 import java.sql.Connection;
 import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.sql.Statement;
 
 public class TestDelete {
 public static void main(String[] args) {
 Connection conn = null;
 Statement st = null;
 ResultSet rs =null;
 JdbcUtils JdbcUtils = new JdbcUtils();
 try {
 conn = JdbcUtils.getConnection(); //获取数据库连接
 st = conn.createStatement(); // 获取SQL执行对象
 String sql = "DELETE FROM `jdbcstudy`.`users` WHERE `id`=5";
 int i = st.executeUpdate(sql);
 if(i>0){
 System.out.println("删除成功");
 }
 } catch (SQLException e) {
 throw new RuntimeException(e);
 }finally {
 JdbcUtils.release(conn,st,rs);
 }
 }
 }
 import java.sql.Connection;
 import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.sql.Statement;
 
 public class TestUpdate {
 public static void main(String[] args) {
 Connection conn = null;
 Statement st = null;
 ResultSet rs =null;
 JdbcUtils JdbcUtils = new JdbcUtils();
 try {
 conn = JdbcUtils.getConnection(); //获取数据库连接
 st = conn.createStatement(); // 获取SQL执行对象
 String sql = "UPDATE `jdbcstudy`.`users` SET `name`='nihao' WHERE `id`=4";
 int i = st.executeUpdate(sql);
 if(i>0){
 System.out.println("更新成功");
 }
 } catch (SQLException e) {
 throw new RuntimeException(e);
 }finally {
 JdbcUtils.release(conn,st,rs);
 }
 }
 
 }
- 
查询 import java.sql.Connection;
 import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.sql.Statement;
 
 public class TestSelect {
 public static void main(String[] args) {
 Connection conn = null;
 Statement st = null;
 ResultSet rs = null;
 try {
 conn = JdbcUtils.getConnection();
 st = conn.createStatement();
 
 // SQL
 String sql = "select * from `jdbcstudy`.`users` where id = 1";
 rs = st.executeQuery(sql);
 while(rs.next()){
 System.out.println(rs.getObject("name"));
 }
 } catch (SQLException e) {
 throw new RuntimeException(e);
 }finally {
 JdbcUtils.release(conn,st,rs);
 }
 
 }
 }SQL 注入问题 
sql存在漏洞,会被攻击导致内容泄露。SQL会被拼接 or
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class SQL注入 {
    public static void main(String[] args) {
        login(" 'or '1=1'","'or '1=1'");
    }
    // 登录业务
    public static void  login(String username,String password){
        Connection conn = null;
        Statement st = null;
        ResultSet rs = null;
        try {
            conn = JdbcUtils.getConnection();
            st = conn.createStatement();
            // SQL
            String sql = "select * from `jdbcstudy`.`users` where `name` = '"+username+"' AND `password`='"+password+"'" ;
            rs = st.executeQuery(sql);
            while(rs.next()){
                System.out.println(rs.getObject("name"));
                System.out.println(rs.getObject("password"));
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }finally {
            JdbcUtils.release(conn,st,rs);
        }
    }
}
13.PreparedStatement对象
PreparedStatement可以防止SQL注入,效率更好!
- 
新增 import java.sql.Connection;
 import java.sql.Date;
 import java.sql.PreparedStatement;
 import java.sql.SQLException;
 
 public class TestInsert {
 public static void main(String[] args) {
 Connection conn=null;
 PreparedStatement st = null;
 
 try {
 conn = JdbcUtils.getConnection();
 
 // 区别
 // 使用?占位符代替参数
 String sql = "INSERT INTO `jdbcstudy`.`users`(`id`,`name`,`password`,`email`,`birthday`) VALUES(?,?,?,?,?)";
 st = conn.prepareStatement(sql); //预编译SQL,先写sql,然后不执行
 
 // 手动给参数赋值
 st.setInt(1,5); //id
 st.setString(2,"heqi");
 st.setString(3,"123456");
 st.setString(4,"hq@163.com");
 //转化时间戳 sql.Date 数据库用的
 // util.Date Java new Date().getTime() 获得时间戳
 st.setDate(5,new java.sql.Date(new Date(1977,10,10).getTime()));
 
 // 执行
 int i= st.executeUpdate();
 if(i>0){
 System.out.println("插入成功");
 }
 } catch (SQLException e) {
 throw new RuntimeException(e);
 }finally {
 JdbcUtils.release(conn,st,null);
 }
 }
 }
 
- 
删除 import java.sql.Connection;
 import java.sql.Date;
 import java.sql.PreparedStatement;
 import java.sql.SQLException;
 
 public class TestDelete {
 public static void main(String[] args) {
 Connection conn=null;
 PreparedStatement st = null;
 
 try {
 conn = JdbcUtils.getConnection();
 
 // 区别
 // 使用?占位符代替参数
 String sql = "delete from `jdbcstudy`.`users` where id=?";
 st = conn.prepareStatement(sql); //预编译SQL,先写sql,然后不执行
 
 // 手动给参数赋值
 
 st.setInt(1,5);
 
 // 执行
 int i= st.executeUpdate();
 if(i>0){
 System.out.println("删除成功");
 }
 } catch (SQLException e) {
 throw new RuntimeException(e);
 }finally {
 JdbcUtils.release(conn,st,null);
 }
 }
 }
 
- 
改变 import java.sql.Connection;
 import java.sql.PreparedStatement;
 import java.sql.SQLException;
 
 public class TestUpdate {
 public static void main(String[] args) {
 Connection conn=null;
 PreparedStatement st = null;
 
 try {
 conn = JdbcUtils.getConnection();
 
 // 区别
 // 使用?占位符代替参数
 String sql = "update `jdbcstudy`.`users` set `name`=? where id=?";
 st = conn.prepareStatement(sql); //预编译SQL,先写sql,然后不执行
 
 // 手动给参数赋值
 st.setString(1,"heqi2");
 st.setInt(2,5);
 
 // 执行
 int i= st.executeUpdate();
 if(i>0){
 System.out.println("修改成功");
 }
 } catch (SQLException e) {
 throw new RuntimeException(e);
 }finally {
 JdbcUtils.release(conn,st,null);
 }
 }
 }
 
- 
查找 
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class TestSelect {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement st = null;
        ResultSet rs = null;
        try {
            conn=JdbcUtils.getConnection();
            String sql = "select * from `jdbcstudy`.`users` where id=?";
            st = conn.prepareStatement(sql);
            st.setInt(1,1);
            // 执行
            rs = st.executeQuery();
            if(rs.next()){
                System.out.println(rs.getObject("name"));
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            JdbcUtils.release(conn,st,rs);
        }
    }
}
14.使用IDEA连接数据库

连接成功后可以选择数据库。

双击数据库,查询数据内容

更新数据

编写SQL

切换数据库

连接失败,查看原因

要么都成功,要么都失败
ACID原则
原则性:要么全部完成,要么都不完成。
一致性:总数不变。
隔离性:多个进程互不干扰。
持久性:一旦提交不可逆,持久化到数据库。
隔离性问题:
脏读:一个事务读取了另一个没有提交的事务。
不可重复读:在同一个事务内,重复读取表中的数据,表数据发生改变。
虚读(幻读):在一个事务内,读取到了别人插入的数据,导致前后读出来的结果不一致。
代码实现
- 
开启事务(conn.setAutoCommit(false); //**开启事务) 
- 
一组业务执行完毕,提交事务。 
- 
可以在catch语句中显示的定义,回滚语句,但默认失败就会回滚 import java.sql.Connection;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.sql.SQLException;
 
 public class TestTransaction1 {
 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 `shop`.`account` set money = money-100 where id = 1";
 st=conn.prepareStatement(sql1);
 int i=st.executeUpdate();
 String sql2="update `shop`.`account` set money = money+100 where id = 2";
 st=conn.prepareStatement(sql2);
 int s=st.executeUpdate();
 
 //业务完成,提交事务
 conn.commit();
 if(i>0&&s>0){
 System.out.println("成功");
 }
 } catch (SQLException e) {
 try {
 conn.rollback(); // 如果失败回滚事务
 } catch (SQLException ex) {
 throw new RuntimeException(ex);
 }
 }finally {
 JdbcUtils.release(conn,st,rs);
 }
 }
 }
 
16.数据库连接池
数据库连接——执行完毕——释放
连接——释放 十分浪费系统资源
池化技术:准备一些预先的资源,过来连接预先准备好的
——开门——业务员:等待——服务——
常用连接数:10
最小连接数:10
最大连接数:15业务最高承载上线
等待超时:100ms
编写连接池,实现一个接口。DataSource
开源数据实现(拿来即用)
DBCP
C3P0
Druld:阿里巴巴
使用了这些数据库连接池之后,我们在项目中开发就不需要编写数据库代码了。
DBCP
需要用到的jar包
commons-dbcp-1.4 、commons-pool-1.6
C3P0
需要用到的jar包
c3p0-0.9.5.5、mchange-commons-java-0.2.19
结论
无论使用什么数据源,本质还是一样的。DataSource接口不会变,方法就不会变。
 
                    
                     
                    
                 
                    
                


 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号