JDBC
JDBC概述
JDBC(Java DataBase Connectivity)Java数据库连接
利用java语言/java程序连接并访问数据库的一门技术
JDBC程序访问数据库
第一步:准备数据
第二步:创建工程并导入jar包
jar包:mysql-connector-java-8.0.11.jar
WEB项目:放到WebContent/WEB-INF/lib目录下
Java基础项目:可以在项目中建一个lib目录,上面的jar文件赋值到项目的lib目录下,在选中jar文件,右键—>Build Path–>Add to Build
第三步:创建测试类,实现JDBC程序(六个步骤)
//1.注册驱动
/* 将mysql驱动包中的"com.mysql.cj.JDBC.Driver"类加载到内存中,Driver类中的静态代码块就会执行,而在Driver类的静态代码块中由一行代码是用于注册驱动的,因此这行代码可以注册驱动!
注册驱动:将mysql驱动交给JDBC程序管理,以便于使用其中的功能
在JDBC4.0以后的版本中,这一步可以省略。
*/
Class.forname("com.mysql.cj.jdbc.Driver");
//2.获取数据库连接
/*
DriverManager.getConnection(url,user,password)
url:指定要链接的是哪一个位置的哪一个库
如果连接的数据库端口是3306,端口可以省略不写
如果是连接本机上的数据库,主机名/IP地址可以省略不写
getConnection方法返回一个Connection对象,用于表示Java程序和数据库服务器之间的连接
*/
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/jt_db?serverTimezone=Asia/Shanghai&CharacterEncoding=utf-8","root","root");
//3.获取传输器
/*
conn.createStatement():用于获取向数据库发送SQL语句的传输器对象
*/
Statement stat = conn.createStatement();
//4.发送SQL语句到服务器执行,并将结果返回
String sql ="";
//用于执行查询类型的SQL语句,返回的是一个ResultSet对象
ResultSet rs = stat.executeQuery(sql);
//用于执行新增、删除、修改类型的SQL语句,返回一个int值,表示影响的记录行数
int rows = stat.executeUpdate(sql);
//5.处理执行的结果
/*
rs.next():用于将指向数据行的箭头往下挪动一行,并且返回布尔值(true或false)
true表示箭头往下挪动一行后,指向的行有数据,false表示箭头往下挪动一行后,指向的行没有数据
*/
while(rs.next()){
}
//6.释放资源
rs.close();
stat.close();
conn.close();
SQL注入攻击
SQL注入攻击产生的原因:由于SQL语句中的参数是拼接而来的,其中的参数值是用户提交过来的,如果用户在提交参数时,在参数中参杂一些SQL关键字或特殊字符(or、#、-- 、/* */等)就可能回导致SQL语句的语义被篡改,从而执行一些意外的操作
SQL注入攻击解决的方法
方法一:
可以对用户提交过来的参数进行校验,如果用户名或密码中由类似于or、#、-- 等符号,就不再登陆,直接提示用户不合法,请重新登陆。
方法二:
使用JDBC中提供的PreparedStatement对象。
如何解决SQL注入攻击的?
1)PreparedStatement对象是先将SQL语句的骨架(不含参数)发送给服务器编译并确定下来。
String sql="select * from user where username=? and password=?";
PreparedStatement stat = conn.preparedStatement(sql);
2)在将SQL语句中的参数值传递给服务器
//设置SQL语句中的参数值
stat.setString(1,user);
stat.setString(2,psw);
ResultSet rs = stat.executeQuery(sql);
/*
由于前面SQL语句的骨架已经被确定了,因此SQL参数中即使在包含SQL关键字或者特殊符号,也不会影响SQL语句的骨架或语义,只会被当前普通的文本来处理,因此可以防止SQL注入!
*/
数据库连接池
连接池
池:常量池、线程池、连接池等中的池都是一个容器。是指内存中的一片空间
连接池:就是将一批连接资源存入到一个容器中。目的是为了实现连接的复用,减少连接创建和关闭的次数,以此来提高程序执行的效率!
为什么要使用连接池
传统方式中,每次需要连接都是直接创建一个连接(对象/资源),在基于这个创建的连接去访问数据库,最后用完连接还要关闭!
而每次【创建连接】和【关闭连接】相比使用连接是要消耗大量的时间和资源,导致程序的执行效率非常低下!
为了提高程序执行的效率,我们可以在程序启动时,就创建一批连接放在一个连接池中,供整个程序共享。
当用户需要连接时,不用再去创建连接,而是直接从连接池中获取一个连接进行使用,在用完连接后,也不需要关闭,而是直接将连接还回到连接池中。这样一来,用来用去都是连接池中的这一批连接,必然可以实现连接的复用,减少连接创建和关闭的次数。提高程序执行的效率!
如何使用C3P0连接池
第一步:导入c3p0的jar包:c3p0-0.9.1.2.jar
第二步:在程序中创建一个c3p0连接池对象(存放连接的容器)
ComboPooledDataSource pool = new ComboPooledDataSource();
第三步:设置连接数据库的基本信息(四个参数)
//方式一:将连接数据库的参数通过setXxx方法直接通过java代码写死在程序中
/*
这种方法不推荐使用,因为这种方式将连接参数写死在程序中了,将来一旦参数发生变化,就需要我们去改程序,改完之后需要对项目重新编译、打包、部署、运行等,会提高维护成本!
*/
pool.setDriverClass("com.mysql.cj.jdbc.Driver");
pool.setJdbcUrl("jdbc:mysql:///jt_db?serverTimezone=Asia/Shanghai");
pool.setUser("root");
pool.setPassword("root");
//方式二:将连接数据库的参数提取到c3p0.properties(文件名是固定的)文件中,并且需要将这个文件放在源码根目录(src根目录)下,文件内容如下:
c3p0.driverClass=com.mysql.cj.jdbc.Driver
c3p0.jdbcUrl=jdbc:mysql:///jt_db?characterEncoding=utf8&serverTimezone=Asia/Shanghai
c3p0.user=root
c3p0.password=root
//方式三:将连接数据库的参数提取到c3p0-config.xml(文件名也是固定的)文件中,并且需要将这个文件放在源码根目录(src根目录下),文件内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
<default-config>
<property name="driverClass">
com.mysql.jdbc.Driver
</property>
<property name="jdbcUrl">
jdbc:mysql:///jt_db?characterEncoding=utf-8&serverTimezone=Asia/Shanghai
</property>
<property name="user">
root
</property>
<property name="password">
root
</property>
</default-config>
</c3p0-config>
第四步:从连接池中获取一个连接对象进行使用
Connection conn = pool.getConnection();
第五步:将用完的连接对象还回到连接池中
pool.close();
xml文件和properties的区别
相同点:这两种文件在企业开发中都可以作为配置文件使用,而且用得特别多
不同点:
1)xml文件缺点:配置信息多,编写起来比较麻烦,如果需要通过java程序读取,代码也会比较麻烦
2)xml文件优点:可以保存由结构的数据
3)properties文件缺点:配置信息结构是key=value,无法保存有结构的数据
4)properties文件优点:配置信息简洁,如果需要通过java程序读取,读取起来也比较方便
数据库事物(Database Transaction)
概述
事物是将一堆的SQL语句绑定在一起执行,结果是要么全部执行成功,要么全部执行失败。而且是都成功了才算成功,但凡有一条执行失败,就按全失败来处理。
事物的四大特性
1)原子性
表示食物中的所有操作(SQL)是一个整体,不能被分割,要么全部执行成功,要么全部执行失败
2)一致性
在事物前后的业务数据之和是保持一致的
3)隔离性
是指所有的事物都是隔离开的,在一个事务中看不到另外一个事物正在进行中的状态
4)持久性
在事务提交后,对数据的更新操作才会持久的保存到数据库中
MySQL中的事物
在mysql中默认一条SQL语句就是一个事物
如果希望将多余SQL放在一个事务中执行,可以手动开启事物,并手动结束事物
开启事务
start transaction / begin
结束事物
提交 commit | 回滚 rollback
JDBC操作事物
在JDBC中默认是自动提交事务,所以需要关闭自动提交,改为手动提交事务
也就是说,关闭了自动提交后,事物就自动开启,但是执行完后需要手动提交或者回滚
//关闭JDBC自动提交事物
conn.setAutoCommit(false)
//手动提交事务
conn.commit()
//回滚事务
conn.rollback()