概述
JDBC是一套标准,是Java与各大数据库厂商共同制定的一套接口,这套接口由各大数据库厂商进行了实现,JDBC不只是用于连接MySQL,而是任意的数据库
使用步骤
// 加载数据库驱动
// MySQL8.0以上的版本,驱动为com.mysql.cj.jdbc.Driver,否则驱动为com.mysql.jdbc.Driver
Class.forName("驱动名");
// 创建连接对象,getConnection()方法要传入三个参数
// 数据库连接地址的格式为:"主协议:子协议://ip地址:端口号/数据库名称?参数"
Connection conn = DriverManager.getConnection("数据库连接地址","账号","密码");
// 创建SQL执行对象
Statement state = conn.createStatement();
// 通过执行对象,传入sql语句
state.execute("需要执行的sql语句");
state.close();
conn.close();
JDBC里的常用类与方法
DriverMannager:驱动管理器
// 获取数据库连接
static Connection getConnection(String 数据库地址,String 账号 ,String 密码)
Connection:数据库连接对象
// 创建执行对象
Statement createStatement();
Statement:SQL执行对象
// 执行SQL语句(查询语句返回true, 其它语句返回false)
boolean execute(String sql);
// 执行DML语句(INSERT UPDATE DELETE) 和 DDL语句(create alter drop)
// 返回结果为一个int值, 表示语句对数据库表格的影响行数,通常情况如果>0,代表执行成功
int executeUpdate(String sql);
// 执行DQL语句(select),返回结果为一个ResultSet
ResultSet executeQuery(String sql);
ResultSet:结果集对象
// 使游标向下一行移动,成功返回true,下一行不存在返回false
boolean next()
// 使游标向上一行移动
boolean privious()
// 使游标移动至指定行
boolean absolute(int 行号)
// 使游标移动至第一行
boolean beforeFirst()
// 使游标移动至倒数第一行
boolean afterLast()
// 通过列名,获取字段内的值
XXX getXXX(String 列名)
// 通过字段的索引,获取字段内的值
XXX getXXX(int 字段的索引)
实例:通过结果集获取某行的某字段内的值
...
ResultSet rs = state.executeQuery("select * from student");
while(rs.next()){
int id = rs.getInt("id");
String info = rs.getString("info");
}
预编译处理
使用Statement作为SQL执行对象时,可能会遇到SQL注入的问题
...
state.execute("insert into xzk_user values('" + username + "','" + password + "')");
此时如果password传入1’ or ‘1’='1,SQL语句会产生歧义,导致程序出错
select * from xzk_user where username='hahahaheiheihei' and password='1' or '1'='1'
为了避免SQL注入的问题,JDBC可以使用预编译的语句,将SQL语句与参数分离
预编译的内部原理:
- 将未拼接参数的SQL语句作为SQL指令传递给数据库进行编译
- 再将参数传递给数据库,此时的参数只作为文本而不是指令
// 预编译的SQL语句,参数使用?来替代
state = conn.prepareStatement("select * from user where username=? and password=?");
// 向预编译的SQL语句中加入参数
state.setString(1,username);
state.setString(2,password);
// 执行
rs = state.executeQuery();
preparedStatement与Statement
理论上在任何情况下都应该使用preparedStatement,以防止SQL注入的问题产生,但是preparedStatement并不是在任何情况下性能都要优于Statement
在MySQL中,preparedStatement的原理是拼接SQL,因此Statement效率高
以上为使用两种SQL执行对象的处理时间记录,可以明显看出preparedStatement的平均执行时间是要大于Statement的,而这还只是处理10000条数据的情况
在Oracle中,preparedStatement的原理是对SQL语句进行预处理,再传递的参数不具备语义,因此拥有更好的缓存策略,执行效率要大于Statement
批处理
将多条SQL语句,放在一起进行批量处理,显著提高了大量SQL语句的执行效率
Statement对象的批处理使用流程:
Statement state = conn.createStatement();
// 向批处理加入一条sql语句
state.addBatch(String sql);
// 执行批处理内的sql语句
state.executeBatch();
// 清空批处理
state.clearBatch();
PreparedStatement对象的批处理使用流程:
PreparedStatement state = conn.prepareStatement("预编译的SQL");
state.setXXX(1,填充参数);
// 向批处理加入一条sql语句
state.addBatch();
// 执行批处理内的sql语句
state.executeBatch();
// 清空批处理
state.clearBatch();
数据库连接池
.properties配置文件,这里需要配置url,改为要连接的数据库名,加上时区等信息。username,还有password是连接数据库的用户名,密码,需要改为自己的
url=jdbc:mysql://localhost:3306/test?serverTimezone=UTC
username=root
password=111
#驱动类名。根据url自动识别,这一项可配可不配
#如果不配置druid会根据url自动识别相应的driverClassName
driverClassName=com.mysql.cj.jdbc.Driver
#初始化时建立物理连接的个数。初始化发生在显示调用init方法,或者第一次 getConnection时
initialSize=5
#最大连接池数量
maxActive=10
#最小连接池数量
minIdle=5
#获取连接时最大等待时间,单位毫秒。
maxWait=3000
DBCP连接池的使用步骤:
// 1.引入jar文件
// 2.引入配置文件,src目录下
// 3.将配置文件转化为Properties对象
Properties ppt = new Properties();
ppt.load(配置文件的输入流);
// 通过连接池的工厂类的获取连接池的方法,获取一个连接池
DataSource ds = BasicDataSourceFactory.createDataSource(ppt);
// 从连接池中,获取连接对象
Connection conn = ds.getConnection();
德鲁伊连接池的使用步骤:
// 1.引入jar文件
// 2.引入配置文件,src目录下
// 3.将配置文件转化为Properties对象
Properties ppt = new Properties();
ppt.load(配置文件的输入流);
// 通过连接池的工厂类的获取连接池的方法,获取一个连接池
DataSource ds = DruidDataSourceFactory.createDataSource(ppt);
// 从连接池中,获取连接对象
Connection conn = ds.getConnection();
上述输入流为类名.calss.getcalssloader().getResourceAsStream(".properties文件名")
,为了简化开发流程,增强代码的复用性,通常会写一个连接池工具类来获取连接对象