Mysql学习(B站狂神说java的个人笔记二)
目录
一、事务
二、索引
三、权限管理和备份
四、规范数据库设计和三大范式
五、JDBC(重点)和第一个JDBC程序及解释
六、statement对象详解
七、SQL注入问题
八、PreparedStatement对象
九、使用IDEA连接数据库
十、JDBC操作事务
十一、数据库连接池
一、事务
1、什么是事务
要么都成功,要么都失败
(1)例子:(都针对同一个事物,要么都完成要么不完成)
SQL执行 A给 B转账 A1000 --> 200 B200
SQL执行 B收到A的钱 A 800 --> B200
(2)事务原则:ACID原则,原子性,一致性,隔离性,持久性
(3)以上面的例题来解说:
①原子性:上述转钱的步骤,要么一起成功,或者一起失败,不能只发生其中一个
②一致性:只对一个事务的一致性,即最终的一致性,可以理解为上面A和B怎么转钱,他们的钱加起来永远都是1000,不会变
③持久性:表示事务结束后的数据不随着外界原因导致数据丢失,如果数据库未提交,恢复到原来;如果事务已经提交,持久化到数据库,即事务一旦提交就不能变了
④隔离性:针对多个用户同时操作,主要是排除其他事务对本次事务的影响

(4)事务隔离的一些错误:
①脏读:指一个事务读取了另外一个事务未提交的数据
②不可重复度:在一个事务内读取表中的某一行数据,多次读取结果不同(这个不一定是错,只是某些场合不对)
③虚读(幻读)
是指在一个事务内读取到了别的事务插入的数据,导致前后读取不一致。
2、执行事务
(1)mysql是默认开启事务自动提交的
SET autocommit =0 /*关闭*/
SETautocommit = 1 /*开启(默认的)*/
--手动处理事务
SET autocommit =0 --关闭自动提交--事务开启
START TRANSACTION --标记一个事务的开始,从这个之后的 sql 都在同一个事务内
INSERT XX
INSERT XX(这两个事务要么同时成功,要么失败)--提交:持久化(成功!)
COMMIT--回滚:回到|的原来的样子(失败!)
ROLLBACK
--事务结束(以下内容先了解即可)
SAVEPOINT 保存点名 --设置一个事务的保存点
ROLLBACK TO SAVEPOINT保存点名 --回滚到保存点
RELEASE SAVEPOINT 保存点名 --撤销保存点
(2)顺序

(3)模拟场景
CREATE DATABASE shop CHARACTER SET utf8 COLLATE utf8_general_ci
--创建一个叫shop的数据库
USE shop --使用shop数据库
CREATE TABLE `account`(
`id` INT(3)NOT NULL AUTO_INCREMENT,'nameVARCHAR(30) NOT NULL,
`money DECIMAL(9,2) NOT NULL,PRIMARY KEY ( id )
)ENGINE=INNODB DEFAULT CHARSET=utf8
--创建一张account的表
INSERT INTO account(` name`, money `)VALUES ( 'A' ,2000.00),('B ',10000.00)
--给表插入一些数据--模拟转账:事务
SET autocommit = 0; --关闭自动提交
START TRANSACTION --开启一个事务(一组事务)
UPDATE account SET money=money-500 WHERE `name` = 'A' -- A减500
UPDATE account SET money=money+500 WHERE ‘name’ = 'B' -- A加500
COMMIT; --提交事务,就被持久化了!
ROLLBACK; --回滚
SET autocommit = 1; --恢复默认值
二、索引
MySQL官方对索引的定义为:索引 (Index)是帮助MySQL高效获取数据的数据结构。提取句子主干,就可以得到索引的本质:索引是数据结构。
1、主键索引(PRIMARY KEY )
唯一的标识,主键不可重复,只能有一个列作为主键
2、唯一索引(UNIQUE KEY)
避免重复的列出现,唯一索引可以重复,多个列都可以标识位唯一索引
3、常规索引(KEY/INDEX)
默认的, index或key关键字来设置
4、全文索引(FullText)
在特定的数据库引擎下才有,MylSAM。
快速定位数据
5、基础语法
(1)索引的使用
①在创建表的时候给字段增加索引
②创建完毕后,增加索引
(2)显示所有的索引信息
例:SHOW INDEX FROM student
(3)增加一个全文索引(索引名)列名
例:ALTER TABLE schoo1.student ADD FULLTEXT INDEX`studentName ` ( studentName );
(4)EXPLAIN分析sql执行的状况
EXPLAIN SELECT *FROM student; --非全文索引
EXPLAIN SELECT *FROM student WHERE MATCH(studentName) AGAINST('刘');
注:索引在小数据量的时候,用户不大,但是在大数据的时候,区别十分明显
(5)索引原则
索引不是越多越好
不要对进程变动数据加索引·小数据量的表不需要加索引
索引一般加在常用来查询的字段上!
(6)索引的数据结构
Hash类型的索引
Btree : lnnoDB的默认数据结构
三、权限管理和备份
1、SQLyog可视化管理
点击上面的小人或者按下CTRL+U

会出现一个弹窗,点击添加新用户

用户名密码自己取,主机选127.0.0.1或localhost都一样,选后之后点击创建

他会让你选一些权限,这些表的权限基本可以通过名字看出来,就是一些功能,能否创建一个表,删除,是否能够插入等等,如果点击选择全部,那么这个用户几乎可以干所有的事情
再点击保存改动这个用户就创建完了
试一下用这个用户链接,右键点击文件-新连接或者CTRL+M

注意MYSQL Host Address 这里,之前选的是上面,这里就填什么。如果选的是127.0.0.1这里就填127.0.0.1

之后不难发现,用户换了,之前的默认是root用户

如果要删除用户的话,点击用户管理或ctrl+U,在用户中选中要删除的用户,点击删除用户,用户就删除了

2、sql命令
(1)用户表:mysql.user
本质:就是对用户表这张表进行增删改查

这张表基本上就是一些权限,跟之前用户管理里面的权限一致

(2)创建用户CREATE USER用户名IDENTIFIED BY '密码’
例:
例:CREATE USER kuangshen IDENTIFIED BY '123456'
修改密码(修改当前用户密码)
SET PASSWORD = PASSWORD( '123456 ')
修改密码(修改指定用户密码)
SET PASSWORD FOR kuangshen = PASSWORD( '123456 ')
重命名: RENAME USER原来名字 To 新的名字
RENAME USER kuangshen To kuangshen2
用户授权: ALL PRIVILEGES 全部的权限,库.表
(注:ALL PRIVILEGES 除了给别人授权,其他都能够干)

GRANT ALL PRIVILEGES ON *. * To kuangshen2
--查询权限
SHOW GRANTS FOR kuangshen2 --查看指定用户的权限
SHOW GRANTS FORroot@1ocalhost
-- ROOT用户权限:GRANT ALL PRIVTLEGES ON *.* To 'root' @'loca1host' WITH GRANT OPTION
撤销权限:REVOKE哪些权限,在哪个库撤销,给谁撤销
REVOKE ALL PRIVILEGES ON*.*FROM kuangshen2
删除用户:
DROP USER kuangshen
3、MySQL备份
(1)为什么要备份:
①保证重要的数据
②不丢失数据转移
(2)MySQL数据库备份的方式
①直接拷贝物理文件
②在Sqlyog这种可视化工具中手动导出
③使用命令行导出mysqldump命令行使用
(3)sqlyog手动导出
右键需要到处的表后点击备份/导出,

点击备份表作为SQL 转储,就叫sql转储,,一般情况下就只要结构和数据,结构就代表创建表的那些语句,数据就代表那些insert语句

4、使用命令行导出mysqldump命令行使用
①语法: mysq1dump -h 主机 -u用户名-p 密码数据库﹑表名>物理磁盘位置/文件名
例:mysq1dump -hloca7host -uroot -p123456 school student >D:/a.sq1
②语法: mysq7dump -h 主机 -u用户名-p 密码数据库﹑表1表2表3>物理磁盘位置/文件
例:mysqldump -h1ocalhost -uroot -p123456 school student >D:/b.sq1
③语法:mysqldump -h主机 -u 用户名-p 密码数据库>物理磁盘位置/文件名例:mysq1dump -hlocalhost -uroot -p123456 schoo1 >D:/c.sq7
④导入数据
登录mysql的情况下,切换到指定的数据库#source备份文件(如果是要导入数据库就不用切换指定数据库,如果是导入表就需要)
切换后输入例子:source d : /a.sq1 I
不登入MySQL的情况下,输入语法:
mysql -u用户名-p密码库名<备份文件
注:还是推荐登入MySQL后再导入
⑤什么是使用使用备份:假设你要备份数据库,防止数据丢失。把数据库个朋友! sql文件给别人即可!
四、规范数据库设计和三大范式
1、为什么要设计数据库
当数据库比较复杂的时候,我们就需要设计了
糟糕的数据库设计:
数据冗余,浪费空间
数据库插入和删除都会麻烦、异常【屏蔽使用物理外键】
程序的性能差
良好的数据库设计:
节省内存空间
保证数据库的完整性
方便我们开发系统
软件开发中,关于数据库的设计:
分析需求:分析业务和需要处理的数据库的需求
概要设计:设计关系图E-R图
2、设计数据库额步骤(个人博客)
①收集信息,分析需求
用户表(用户登录注销,用户的个人信息,写博客,创建分类)。分类表(文章分类,谁创建的)
文章表(文章的信息)
评论表
友链表(友链信息)
自定义表(系统信息,某个关键的字,或者一些主字段)key : value。说说表(发表心情.. id... content....create_time)
②标识实体(把需求落地到每个字段)
③标识实体之间的关系
写博客: user --> blog
创建分类:user -> category。关注: user ->user
友链:links
评论: user-user-blog
3、三大范式
(1)
第一范式(1NF)
原子性:保证每一列不可再分
例如:

第二范式(2NF)
前提:满足第一范式每张表只描述—件事情
(第二范式需要确保数据库表中的每一列都和主键相关,而不能只与主键的某一部分相关(主要针对联合主键而言))

第三范式(3NF)
前提:满足第一范式和第二范式
第三范式需要确保数据表中的每一列数据都和主键直接相关,而不能间接相关。
(2)(规范数据库的设计)规范性和性能的问题:
关联查询的表不得超过三张表
①考虑商业化的需求和目标,(成本,用户体验!)数据库的性能更加重要。
②在规范性能的问题的时候,需要适当的考虑一下规范性!
③故意给某些表增加一些冗余的字段。(从多表查询中变为单表查询)
④故意增加一些计算列(从太数据量降低为小数据量的查询:索引)
五、JDBC(重点)和第一个JDBC程序及解释
1、数据库驱动
驱动:声卡,显卡,数据库

我们的程序会通过数据库驱动和数据库打交道
2、
SUN公司为了简化开发人员的(对数据库的统一)操作,提供了一个(Java操作数据库的)规范,俗称JDBC这些规范的实现由具体的厂商去做~
对于开发人员来说,我们只需要掌握JDBC接口的操作即可!

3、学习这个需要知道两个包:java.sql javax.sql
还需要导入一个数据库驱动包:mysql-connector-java-5.1.47.jar(中间的数字代表版本号,不同的版本对应的版本号不同)
4、第一个JDBC程序
(1)创建测试数据库
CREATE DATABASE jdbcstudy CHARACTER SET utf8 COLLATE utf8_general_ci;
USE jdbcstudy;
CREATE TABLE users(
id INT PRIMARY KEY,
NAME VARCHAR(40),
PASSwORD VARCHAR(40),
emai1 VARCHAR(60) ,
birthday DATE
);
INSERT INTO users(id ,NAME ,PASSWORD , emai1,birthday)
VALUES (1, 'zhansan ' , '123456' , 'zs@sina.com', '1980-12-04 '),
(2, '1isi' , '123456' , '1isi@sina.com ' , '1981-12-04 '),
(3 , 'wangwu ' , '123456' , 'wangwu@sina.com ' , '1979-12-04 ');
在sqlyog创建之后的的结果

(2)在JDBC下写代码
package com.kuang.lesson01;import java.sql.*;
//我的第一个JDBC程序
public class JdbcFirstDemo {
public static void main(String[] args) throws ClassNotFoundException,SQLException {
// 加载驱动
class.forName( "com.mysql.jdbc.Driver"); // 固定写法,加载驱动//用户信息和urL
//useUnicode=true&characterEncoding=utf8&useSSL=true
String url = "jdbc:mysq1://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=true";
String username = "root" ;
String password = "123456";//.连接成功,数据库对象Connection代表数据库
Connection connection = DriverManager.getConnection(url, username,password);//执行SQL的对象Statement执行sqL的对象
Statement statement = connection.createStatement();//执行SQL的对象去执行SQL,可能存在结果,查看返回结果
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("pwd=" + resultset.getobject("PASSWORD"));
System.out.println( "email=" + resultset.getobject("email"));
System.out.println("birth=" + resultset.getobject("birthday"));
System.out.println("====================================");
}//释放连接
resultset.close(;statement.close();connection.close();
}
}
执行之后输出的结果:

5、步骤总结:
①加载驱动
②连接数据库DriverManager
③获得执行sql的对象Statement
④获得返回的结果集
⑤释放连接
6、解释:
(1)DrivierManager
// Drive rManager.registerDriver(new com.mysql. jdbc.Driver());
class.forName("com.mysql.jdbc.Driver");//固定写法,加载驱动
connection connection = DriverManager.getconnection(url,username,password);
// connection代表数据库
//数据库设置自动提交//事务提交
//事务滚回
connection . rollback();
connection . commit();
connection . setAutocommit();
(2)URL
string ur1 = "jdbc :mysql: / /localhost: 3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&usessL=true ";
// mysql默认端口: 3306
//协议://主机地址:端口号/数据库名?参数1&参数2&参数3
// oralce 默认端口号: 1521
/ /jdbc:oracle:thin: @1ocalhost:1521:sid
(3)
Statement执行SQL的对象 PrepareStatement执行SQL的对象(这两个的作用都差不多)
string sql = "SELECT *FROM users"; //编写sQL
statement.executeQuery() ;//查询操作返回Resultset
statement.execute(); //执行任何SQL
statement.executeUpdate();//更新、插入、删除。都是用这个,返回一个受影响的行数
(4)
ResultSet查询的结果集:封装了所有的查询结果
获得指定的数据类型
resu1tset.getobject(); //在不知道列类型的情况下使用
//如果知道列的类型就使用指定的类型
Resultset.getstring();
resultset.getInt();
resultset. getFloat();
resultset. getDate();
resultset. getobject();
(5)遍历、指针
resultset.beforeFirst();//移动到最前面
resultset.afterLast();//移动到最后面
resultset.next();//移动到下一个数据
resultset.previous();//移动到前一行
resultset.absolute(row);//移动到指定行
(6)释放资源
//释放连接
resultset.close();
statement.close();
connection . close(); //产耗资源,用完关掉
六、statement对象详解
1、statement对象
Jdbc中的statement对象用于向数据库发送SQL语句,想完成对数据库的增删改查,只需要通过这个对象向数据库发送增删改查语句即可。
Statement对象的executeUpdate方法,用于向数据库发送增、删、改的sql语句,executelUpdate执行完后,将会返回一个整数((即增删改语句导致了数据库几行数据发生了变化)。
Statement.executeQuery方法用于向数据库发送查询语句,executeQuery方法返回代表查询结果的ResultSet对象。
2、 CRUD操作 create
使用executeUpdate(String sql)方法完成数据添加操作,示例操作:
statement st = conn.createstatement();
String sql= "insert into user(... ) values(.... . ) ";
int num = st.executeupdate(sql);
if(num>0){
System. out.println("插入成功! ! ! ");
}
3、CRUD操作 delete
使用executeUpdate(String sql)方法完成数据删除操作,示例操作:
statement st = conn.createstatement();
String sql = "delete from user where id=1";
int num = st.executepdate(sql);
if(num>0){
System.out.print1n(“删除成功!! ! ");
}
4、CRUD操作read
使用executeQuery(String sql)方法完成数据查询操作,示例操作:
statement st = conn.createstatement();
String sql = "select * from user where id=1";
Resultset rs = st.executeUpdate(sql);
while(rs.next()){
//根据获取列的数据类型,分别调用rs的相应方法映射到java对象中
}
5、代码实现
(1)提取工具类 (也就是正常情况下,在JDBC下写代码都应该包括以下步骤(上面有提到过):
①加载驱动
②连接数据库DriverManager
③获得执行sql的对象Statement
④获得返回的结果集
⑤释放连接
而每一次都要执行加载驱动,释放连接等操作,这个步骤变化的就只有sql和结果,其他都不变,如果每一次都要写一遍会降低写代码速度,因此,对这些不改变的步骤我们要提取工具(创建一个工具类),使用的时候直接链接即可
)
package com. kuang.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(" 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");//驱动只用加载一次
class.forName(driver);
}catch (Exception 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(;
}
}
}
}
(2)编写增删改的方法,executeupdate(以下都是例子)
(下面的代码将上面的工具封装到了名为 Jdbcutils的工具类中)
package com. kuang. lesson02;
import com. kuang.lesson02.utils . ]dbcutils;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 conn = null;
statement st = null;
Resultset rs = null;
try {
conn = Jdbcutils.getconnection(); //获取数据库连接,
st = conn . createstatement();//获得SQL的执行对象
String sql = "ITSERT INTo users(id,` NAME`,` PASSWORD`, `email `, `birthday` )" +
"VALUES(4, 'kuangshen ' , '123456' , '24736743@qq.com' , ' 2020-01-01')"int i = st.executeupdate(sql);
if (i>0){
System. out.println("插入成功!");
}}catch (sQLException e) {
e.printstackTrace(;finally {
dbcutils.release(conn , st,rs);
}
}
}
package com. kuang. lesson02;
import com. kuang. 1esson02.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;try {
conn = jdbcutils.getconnection(); //获取数据库连接
st = conn. createstatement();//获得SQL的执行对象
String sql = "DELETE FROM users WHERE id = 4";
Int i = st.executeupdate(sql);
if (i>0){
System.out.print1n("删除成功! ");
}
}catch (SQLException e) {
e.printstackTrace();
}finally {
Jdbcutils.release(conn , st,rs);
}
}
}
package com. kuang.lesson02;
import com. kuang.lesson02.uti1s . Jdbcutils;
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;try {
conn = jdbcutils.getconnection(); //获取数据库连接
st = conn. createstatement();//获得SQL的执行对象
String sql = "UPDATE users SET NAME*='kuangshen ' , email ='24736743@qq.com’ WHERE id=1";
int i = st.executeupdate(sql);
if (i>0){
System. out.print1n("更新成功! ");
}}catch(SQLException e) {
e.printstackTrace(;finally {
Jdbcutils.release(conn , st,rs);
}
}
}
(3)查询 executeQuery
package com. kuang. lesson02;
import com.kuang.lesson02.uti1s .Jdbcutils;
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;Resu7tset rs = null;
try {
conn = jdbcutils.getconnection();
st = conn . createstatement();/ / SQL
String sql = "select * from users where id = 1";
rs = st.executeQuery (sql);//查询完毕会返回一个结果集
while (rs.next()){
System. out. println(rs. getstring ( "NAME"));
}
}catch (SQLException e) {
e.printstackTrace();
}finally {
Jdbcutils.release(conn , st,rs);
}
}
}
七、SQL注入问题
sql存在漏洞,会被攻击导致数据泄露(SQL会被拼接)

八、PreparedStatement对象
1、PreparedStatement可以防止SQL注入。效率更好!
2、举例说明:
import java.sql.connection;import java.util.Date;
import java.sql.Preparedstatement;
import java.sql.sQLException;
public class TestInsert {
public static void main( String[] args) {
Connection conn = null;
Preparedstatement st = nul1;
try {
conn =. jdbcUtils.getConnection();//区别
//使用?占位符代替参数
String sql = "insert into users(id, `NAME`, `PASSWORD` , ' email `, `birthday`) values(?,?,?,?,?)st = conn.prepareStatement(sql);//预编译SsQL,先写sqL,然后不执行//手动给参数赋值
st.setInt( parameterlndex: 1, x:4); //id
st.setstring( parameterIndex: 2, x: "qinjiang" );
st.setstring( parameterlndex: 3,x: "1232112");
st.setstring( parameterIndex: 4, x: "24734673@qq.com") ;//注意点:sqL.Date 数据库专用的方法 java.sqL.Date()
// utiL.Date java专用的方法 new Date().getTime()获得时问戳
st.setDate( parameterIndex: 5,new java.sql.Date(new Date().getTime()));//执行
int i = st.executeUpdate();if (i>0)i
System.out.print1n("插入成功!");
}
}catch (SQLException e) i
e.printstackTrace();finally {
dbcUtils.reLease( conn,st, rs: null);
}
}
}
package com.kuang.lesson03;
import com.kuang.lesson02.utils.Jdbcutils;
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 users where id = ?";//编写SQLst = conn. prepareStatement(sq1); //预编译st. setInt( parameterlndex: 1, x:2); //传递参数,如果要查id=3就把x后面的数字改为3rs = st. executeQuery(); //执行
if (rs. next()){
System. out . println(rs. getString( columnLabel: "NAME"));
}
} catch (SQLException e) {
e.printstackTrace();finally {
dbcUtils.reLease( conn,st, rs: null);
}
}
}
注:PreparedStatement防止lsQL注入的本质,把传递进来的参数当做字符假设其中存在转义字符,就直接忽略,’会被直接转义
九、使用IDEA连接数据库
1、Database的隐藏问题
在JDBC里一般都会在右侧边会有,但是有的同学可能会没有

没有的同学可以看到下侧,有一个小电脑一样的东西,你点一下它就没有了,再点一下就又有了

2、
点击databases里面的+号,点击data source 里面会出现很多的数据源,选中我们的MySQL

会弹出一个熟悉的连接框,注意要把bin目录导入才能连接成功
如果出现下面这个driver是空的,那么你在点击测试连接的时候就会失败,因为没有导入bin目录

所以到记得导入bin目录

如果还是连接不上的话


出现successful代表连接成功

连接成功后选择数据库,打开这个设置

在schemas里面选中你要选择的数据库,再apply-OK

如果想要查看里面的表就直接双击该表即可
如果要修改里面的表,修改完成后记得点击绿色的箭头,否则会提示修改失败
如果要编写SQL的话

十、JDBC操作事务
1、成功案例:
import com.kuang.lesson02.utils. JdbcUtils;
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 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( sq12);
st.executeUpdate( );//业务完毕,提交事务conn. commit();
System.out.println("成功! ");}catch ( SQLException e) {
try {
conn. rol1back()//如果失败则回滚事务
}catch ( SQLException e1) {
e1.printStackTrace();
}
e. printStackTrace();
}finally {
JdbcUtils.release( conn, st,rs) ;
}
}
}
2、失败案例:
import com.kuang.lesson02.utils. JdbcUtils;
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 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( sq12);
st.executeUpdate( );int x=1/0;//这个语句本来就是错的,所以添加之后,会出错,出错就回滚//业务完毕,提交事务conn. commit();
System.out.println("成功! ");}catch ( SQLException e) {
try {
conn. rol1back()//如果失败则回滚事务
}catch ( SQLException e1) {
e1.printStackTrace();
}
e. printStackTrace();
}finally {
JdbcUtils.release( conn, st,rs) ;
}
}
}
解释:虽然执行了第一条语句A给B转了100块钱,但是由于加了一个报错的语句,导致回滚后,会回滚到执行第一条语句之前,所以不存在A给B转钱了B没给A转钱的情况
3、代码实现
①开启事务:conn .setAu toCommit(false);
②一组业务执行完毕,提交事务
③可以在catch 语句中显示的定义回滚语句,但默认失败就会回滚
十一、数据库连接池
1、池化技术:首先我们要知道数据库连接---执行完毕---释放 、 连接--释放是十分浪费资源的,而池化技术就是提前准备一些预先的资源,过来就连接预先准备好的。
就比如一个银行如果每次迎接一个人都要开门--等待--服务---关门,就会很浪费资源,所以我们在里面多加了业务员,让业务员对接顾客,等到完全没有顾客的时候再关门,此时就相当于关闭服务:开门---业务员---等待---服务---关门。此时就涉及到需要多少个业务员,也就是最小连接数
,一般情况下,会根据常用连接数来设置,常用链接数是10,那么最小连接数也设置为10;最大连接数,就可以理解为业务最高承载上线,如果超过最大连接数,那么剩下的人就只能排队等待;等待超时就是如果等待了超过这个时间,就让他自己走,也就告诉他我们这里有异常,不用来了
2、编写连接池,实现一个接口DataSource
(1)开源数据源实现
DBCP
C3PO
Druid: 阿里巴巴
使用了这些数据库连接池之后,我们在项目开发中就不需要编写连接数据库的代码了!
(2)DBCP:
需要用到的jar包
commons-dbcp-1.4.commons-pool-1.6
(3)C3PO
需要用到的jar包
c3pO-0.9.5.5、mchange-commons-java-0.2.19
(4)结论
无论使用什么数据源,本质还是一样的,DataSource接口不会变,方法就不会变
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
