jdbc mysql事务源代码_JDBC深入理解

JDBC深入

1课程介绍

1.预编译语句对象

2.SQL注入问题

3.用户登录

4.事务

5.连接池

6.获得主键问题

2预编译语句对象

2.1回顾Statement执行SQL语句

2.1.1操作流程

i.加载驱动

ii.获得连接

iii.准备sql语句以及Statement对象

iv.执行sql语句

v.释放资源

2.1.2带来的问题

i.拼接sql语句容易出错,麻烦;

ii.存在sql注入问题;

2.1.3sql注入问题

1.使用Statement模拟sql注入问题

8ad373e6a4cc2a18c0a27e95392f1147.png

2.使用PreparedStatement解决sql注入问题

3.为什么PreparedStatement就解决了sql注入问题呢?

使用PrepareStatement 它的语句相当是一个模板,这个模板的基本结构我们是不能够进行更改的(不能拚接字符串),于是,它很好的解决了sql注入的问题

2.2使用PreparedStatement执行SQL语句

2.2.1概念

PreparedStatement:Statement的子接口,表示预编译SQL语句对象.

什么是预编译SQL语句?

预编译语句PreparedStatement 是java.sql中的一个接口,它是Statement的子接口。

通过Statement对象执行SQL语句时,需要将SQL语句发送给数据库,由数据库首先进行编译后再执行。

预编译语句和Statement不同,在创建PreparedStatement 对象时就指定了SQL语句,该语句立即发送给数据库进行编译。

当该编译语句被执行时,数据库直接运行编译后的SQL语句,而不需要像其他SQL语句那样首先将其编译,再执行。

2.2.2PreparedStatement使用

Api示例:

47ee9093efc2520d9d8682168a19f2bf.png

使用PreparedStatement的操作流程-完成update方法

027f871cbb32940dbd8e0187a10a9644.png

2.2.3注意事项

i.库连错了,表指定错了,列名指定错了,sql语句拼错了;

ii.上面的sql语句中的?代表就是一个任意类型的值,不需加' '

iii.PreparedStatement中是一个模板,而不是拼接字符串

iv.调用executeUpdate方法的时候不需要传入sql参数了,模板中已经有了;

v.set方法指定的列编号是从1开始

2.2.4PreparedStatement特点

i.代码可读性/维护性更高.

ii.PreparedStatement的执行性能更高.

iii.安全性更高,防止SQL注入问题.

a9585729496f918706b8cb1b0f69b2a7.png

2.2.5Statement和PreparedStatement区别(面试题)

第一:

数据库在执行sql语句的时候如果使用PreparedStatement语句会有一点优势:

因为数据库会preparedStatement   语句进行预编译,预编译的sql可以复用

下次执行相同的sql语句时,数据库端不会再进行预编译了,而直接用数据库的缓冲区,

提高数据访问的效率(尽量采用使用?号的方式传递参数).

第二:

极大地提高了安全性,防止sql注入。

第三:

增加代码的可读性 和 可维护性

最后:在JDBC应用中,如果是稍有水平开发者,你就应该始终以PreparedStatement代替Statement.也就是说,

在任何时候都不要使用Statement

3用户登录功能

登录界面a4a1ad0528634c407107b661542689e5.png

有如下几种登录方式:

--------------------------------------------------------------------------------------------

1.第一种

i.在外面的DAO层应该有这样的一条sql:

select * from student where username=? and password=?

549449bcaab20598cd13b0a4dd5b6577.png

ii.劣势 : 不能够独立判断出是用户名还是密码错误

iii.优势 : 简单

安全性更高,思考为什么?

2.第二种

i.在外面的DAO层应该有这样的一条sql:

select * from student where username=?

ii.如何判断重复的?

1.先使用户名从数据库中获得数据

a)如果没有返回东西,提示用户名错误

b)如果得到结果了,从结果中获得密码和前台传入的密码进行比较

c)如果相等  登陆成功

d)如果不相等,提示密码错误b64ac4c2cefcf06eefe3e964e0981dd0.png

625a19f532a2b771d4250508978393b0.png

iii.劣势 : 麻烦一点

iv.优势 : 可以单独判断是用户名还是密码错误

用户体验更好,安全性没那么好,因为直接告诉了用户是用户名错误 还是密码错误

4事务

4.1银行转账案例分析

1.需求:王麻子准备把1000元转给女朋友小花

2.数据准备-账户表account(id,name,balance)

3.步骤

1)查询 王麻子 的账户余额是否大于等于1000块钱.

SELECT  *  FROM account WHERE name = '王麻子' AND balance >= 1000;

①余额小于1000: 系统提示:亲,您的余额不足,把钱赚够了再转吧!!!

②余额大于等于1000: 继续后面的操作

2)从 王麻子 的账户上减少1000块钱.

UPDATE account SET balance = balance - 1000  WHERE name = '王麻子';

3)在 小花 的账户上增加1000块钱.

UPDATE account SET balance = balance + 1000  WHERE name = '小花';

4)那么问题来了:若在第二步和第三步操作之间,突然停电!!!--->程序中断(使用异常模拟.)

5)模拟代码:

c88a4dbce355d0a3d291d8194673c148.png

4.2事务概述和处理

4.2.1什么是事务

把多个操作单元看成是一个整体,全部的操作单元成功都才视为成功(commit),若有一个操作单元失败则,视为整个过程失败(rollback)。

为确保数据库中数据的一致性,数据的操纵应当是离散的成组的逻辑单元:当每个逻辑操作单元全部完成时,数据的一致性可以保持,而当这个单元中的一部分操作失败,整个事务应全部视为错误,所有从起始点以后的操作应全部回退到开始状态。

4.2.2事务的ACID属性(面试可能问到)

1.原子性(Atomicity)

指整个事务是不可以分割的工作单元。只有事务中所有的操作执行成功,才算整个事务成功,

事务中任何一个SQL语句执行失败,那么已经执行成功的SQL语句也必须撤销,数据库状态应该回到执行事务前的状态。

2.一致性(Consistency)

指数据库事务不能破坏关系数据的完整性以及业务逻辑上的一致性。

例如对于银行转账事务,不管事务成功还是失败,应该保证事务结束后两个转账账户的存款总额是与转账前一致的。

3.隔离性(Isolation):

指的是在并发环境中,当不同的事务同时操纵相同的数据时,每个事务都有各自的完整数据空间。

即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。

4.持久性(Durability)

指的是只要事务成功结束,它对数据库所做的更新就必须永久保存下来。

即使发生系统崩溃,重新启动数据库系统后,数据库还能恢复到事务成功结束时的状态。

4.2.3事务的处理机制

try{

//开启事务,设置为的手动提交

操作1

操作2

操作3

......

//提交事务:

}catch(Exception e){

//回滚事务

}

4.2.4JDBC事务细节

1.在JDBC中事务是默认自动提交的.

在执行DML语句的时候就已经提交事务了.

2.事务只对DML语句有效,对于DQL(查询)没效果,查询不会涉及到修改数据.

但是,以后在Spring设置的时候,往往把查询也放到事务中.

注意:以后做开发,方式代码没有报错,但是数据插入/修改/删除不成功,首先判断事务是否提交.

3.回滚事务之后再释放资源,释放锁机制(InnoDB:行锁).

4.在MySQL中,MyISAM不支持外键,不支持事务,InnoDB都支持.

在开发中,外键可以不要,但是事务必须得要.

在Spring中有专门的事务管理器(TransactionManager):

5获得主键问题(了解)

5.1获得主键的场景分析

新增一个产品 和 产品库存

1.从前台网页中录入数据的时候

a)录入产品

b)录入库存

2.后台新增数据到表product 和product_stock

a)先新增一条产品数据,数据库生成一个主键id

b)再新增库存记录(product_stock引用了product表的外键)

需要获得新增的product的id,应该怎么弄?

5.2Statement拿到主键的方式

Statement中有方法:

int executeUpdate(String sql)

返回的是影响的行数

int executeUpdate(String sql, int autoGeneratedKeys)

返回还是影响的行数

参数 : autoGeneratedKeys,表示可以设置是否可以去获得自动生成的主键

值: Statement.RETURN_GENERATED_KEYS

设置可以获取之后,如何获取?

ResultSet getGeneratedKeys() 获取由于执行此Statement对象而创建的所有自动生成的键

注意:

a6812d77f23afc076e40555e6b38acd9.png

分析:

1)表中明明是有id列

2)以前使用executeQuery查询的时候,返回的ResultSet中就是数据库表中的一条一条的数据,就是通过上面的方式来获得

3)getGeneratedKeys() 调用完毕之后返回的对象中只有键

4)怎么拿?调用ResultSet中通过索引来获得列数据的方法

58beffb31f8b45102faba201a7dcb1c9.png

5.3PreparedStatement 拿到主键的方式

de744f77d42d5999e13b7bd88fe107cd.png

Hibernate中可以自动返回,(底层已经封装OK)

6连接池

6.1什么是连接池

连接池:就是用来装连接对象connection的容器

连接池的技术比较多,java仅仅是提供了DataSource的接口(就是连接池),不提供任何实现.由各大服务器厂商来提供DataSource实现(Tomcat,WebLogic).

示例:

假设一个场景,火车站排队买票:

不管有没有人,都需要留一个两个窗口,--有个初始窗口

1.初始容量(5)

火车站刚开始需要有几个窗口

2.如果人变多的时候,窗口不够怎么办---需要增加窗口,但是这个窗口不是随便增加

当人数比较多的时候,添加窗口;

最大数量(10)

3.如果人变少的时候,只有几个窗口 -- 这时候需要最小窗口

最小数量(2)

4.如果有人占着窗口不放,怎么办?

一个人如果占着位置又不买票,比如占了3分钟,强制驱离不要占用窗口

最大连接时间(3)

5.票已经卖完的时候,还有人等待怎么办?

如果等待过长,断开连接,请求超时;

请求超时

这就是连接池的理解;

6.2为什么使用数据库连接池

普通的JDBC数据库连接使用DriverManager来获取,每次向数据库建立连接的时候都要将Connection加载到内存中,再验证用户名和密码(得花费0.05s~1s的时间)。

需要数据库连接的时候,就向数据库要求一个,执行完成后再断开连接。这样的方式将会消耗大量的资源和时间。

数据库的连接资源并没有得到很好的重复利用.若同时有几百人甚至几千人在线,频繁的进行数据库连接操作将占用很多的系统资源,严重的甚至会造成服务器的崩溃。

对于每一次数据库连接,使用完后都得断开。否则,如果程序出现异常而未能关闭,将会导致数据库系统中的内存泄漏,最终将导致重启数据库。

这种开发不能控制被创建的连接对象数,系统资源会被毫无顾及的分配出去,如连接过多,也可能导致内存泄漏,服务器崩溃.

使用连接池和不使用连接池在代码上的区别:

获取连接:

使用连接池之前:

使用DriverManager来获取Connection对象.

Connection  conn = DriverManager.getConnection(url,username,password);

使用连接池之后:

直接找连接池(DataSource对象),取出Connection即可.

如何创建DataSource对象,在创建DataSource的时候,就会设置连接数据库的url,user,password.

Connection conn = DataSource对象.getConnection();

接下来的代码和以前相同.

释放连接:

代码:connection对象.close();

使用连接池之前:

直接和数据库服务器建立连接关系,而断开也是和数据库服务器断开连接.

使用连接池之后:

直接和连接池建立连接关系,而断开也是把Connection对象还给连接池,供其他客户使用.

没有真正的和数据库断开. 如此一来,一个Connection对象就得到了充分的利用!!!

6.3常用连接池

DBCP 连接池

C3P0  连接池

Druid连接池 : 现在用的最多,是阿里巴巴开源的连接池。

排第一Druid

排第二tomcat 里面有个连接池

6.4DBCP连接池实现准备:

拷贝jar:

commons-dbcp-1.3.jar      commons-pool-1.5.6.jar .

查阅文档:commons-dbcp-1.3-src\doc\BasicDataSourceExample.java

---------------------------------------------------------------------------

解决DBCP的硬编码问题:

应该把连接信息放到配置文件中去:  配置文件的名词可以任意.

---------------------------------------------------------------------------

dbcp.properties

#连接字符串

url=jdbc:mysql://localhost:3306/jdbcdemo

#用户名

username=root

#密码

password=admin

#驱动的类路径

driverClassName=com.mysql.jdbc.Driver

#连接池启动时的初始值

initialSize=1

#连接池的最大值

maxActive=50

#连接池的最大空闲数

maxIdle=20

---------------------------------------------------------------------------

如何把dbcp.properties中的配置信息,设置到程序中去:

wKiom1ht-0nB0scqAACb***cJTo576.png-wh_500x0-wm_3-wmp_4-s_206745008.pngfde40c48b10e13217f5a71e2a7ca2c6f.png

直接读取资源文件的方式:d49777792caed40d58cf69262e79cf99.png

注意:在db.properties里的属性名称必须和set的属性名字的对应上

### 回答1: 图书管理系统是一个用于管理图书馆馆藏书籍、借阅情况、读者信息等的软件系统。基于Java和MySQL,结合JDBC技术,我们可以实现一个简单的图书管理系统。以下是一个简单的图书管理系统的源代码示例: 首先,我们需要建立一个名为“图书管理系统”的数据库,并创建三个表格:book(书籍信息)、reader(读者信息)和borrow(借阅情况)。 在Java中,我们可以使用JDBC来连接数据库并进行数据的增删改查操作。可以通过以下步骤来实现: 1. 导入JDBCMySQL相关的库 import java.sql.*; 2. 建立与数据库的连接 Connection conn = null; conn = DriverManager.getConnection("jdbc:mysql://hostname:port/dbname", "username", "password"); 3. 查询书籍信息 Statement stmt = null; stmt = conn.createStatement(); String sql = "SELECT * FROM book"; ResultSet rs = stmt.executeQuery(sql); while (rs.next()) { String bookId = rs.getString("book_id"); String bookName = rs.getString("book_name"); System.out.println("Book ID: " + bookId + ", Book Name: " + bookName); } 4. 插入书籍信息 String sql = "INSERT INTO book (book_id, book_name) VALUES (?, ?)"; PreparedStatement pstmt = conn.prepareStatement(sql); pstmt.setString(1, "1"); pstmt.setString(2, "Java入门指南"); pstmt.executeUpdate(); 5.更新书籍信息 String sql = "UPDATE book SET book_name = ? WHERE book_id = ?"; PreparedStatement pstmt = conn.prepareStatement(sql); pstmt.setString(1, "Java高级编程"); pstmt.setString(2, "1"); pstmt.executeUpdate(); 6.删除书籍信息 String sql = "DELETE FROM book WHERE book_id = ?"; PreparedStatement pstmt = conn.prepareStatement(sql); pstmt.setString(1, "1"); pstmt.executeUpdate(); 以上是一个简单的图书管理系统的源代码示例,通过使用Java编程语言和JDBC技术,结合MySQL数据库,我们可以实现对图书信息的增删改查操作。当然,实际的图书管理系统可能需要涉及更多的功能和表格,但这个例子可以作为一个起点来理解如何使用Java和JDBCMySQL来构建一个图书管理系统。 ### 回答2: 基于Java、JDBCMySQL的图书管理系统源代码主要涉及到数据库操作、用户界面设计和业务逻辑处理等方面。 首先,我们需要建立一个MySQL数据库,用于存储图书和用户信息。可以创建两个表,一个用于存储图书信息,包括图书编号、图书名称、作者、出版社等字段;另一个用于存储用户信息,包括用户编号、用户名、密码等字段。 接下来,我们使用JDBC连接数据库并进行相应的操作。可以通过编写Java代码实现数据库的增、删、改、查等功能。例如,可以编写一个类来处理图书的增加、删除和修改功能,通过输入图书信息和相应的SQL语句来执行对应的数据库操作。 同时,我们还需要设计一个用户界面,通过用户界面与数据库进行交互。可以使用Java的Swing或JavaFX等库来设计图形化界面,通过按钮、文本框等组件来与用户进行交互。例如,在图书添加功能中,用户可以通过界面输入图书信息,并点击“确认”按钮,将输入的图书信息添加到数据库中。 在业务逻辑处理方面,我们可以编写Java代码来实现用户登录、借阅图书、归还图书等功能。例如,用户登录时需要验证用户名和密码是否匹配,可以通过从数据库中查询用户信息,并进行验证。借阅图书时需要判断图书是否可借阅,可以通过查询图书信息并检查借阅状态来实现。归还图书时需要将借阅状态更新为已归还,并更新相应的数据库记录。 总结起来,基于Java、JDBCMySQL的图书管理系统源代码主要包括建立数据库、使用JDBC进行数据库操作、设计用户界面和编写业务逻辑处理等方面的内容。这些代码可以帮助实现一个功能完善的图书管理系统,提供方便快捷的图书管理服务。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值