目录
JDBC基本介绍
1.什么是JDBC?
JDBC(Java Base Connection)是Java中提供的一套标准的应用程序接口,用来连接Java编程语言和数据库
2.JDBC常用组件
DriverManger
数据库驱动程序的管理类,匹配Java程序到数据库的驱动的协议(mysql,sqlserver…),识别出某个子协议与数据库服务器进行通信
Driver
处理与数据库服务器通信的,主要是DriverManger管理的对象,指具体的连接驱动(MySQL驱动)
Connection
接口形式,接触数据库的所有的方法,以及数据库对象的上下文
Statement
创建用于这个接口的对象将所有的SQL提交的数据库(SQL操作都是通过该对象)
ResultSet
使用SQL语句执行查询后,返回的结果都是保存在该对象中
SqlExeption
这个类是数据库应用程序中的任何错误
注意:JDBC是第三方提供的库,要使用JDBC必须先引入jdbc相关jar包(mysql-connection-jave)
idea上直接编写(ArrayList等)等可以直接使用,这是JDK提供的工具类
JDBC编程流程
先在自动生成的app同等路径下新建一个JDBCDemo类
1.加载MySQL驱动 com.mysql.jdbc.Driver
引入驱动包路径:Class.forName
2.获取connection对象
连接数据库 DriverManager.getConnection(url,name,passwd)获取Connection对象
连接数据库信息:
url:jdbc:mysql:ip(连接本地数据库是localhost)+端口(MySQL默认的是3306)+需要连接的数据库名。
例:jdbc:mysql://localhost:3306/mysqltest
username:用户名(需要连接的数据库的用户名)
password:密码(需要连接的数据库的密码)
代码实例:
package com.xiancaijing;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class JDBCDemo {
public static void main(String[] args){
//1.加载MySQL驱动 com.mysql.jdbc.Driver
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//连接数据库
try {
//获取Connection
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mysqltest","root","123456");
} catch (SQLException e) {
e.printStackTrace();
}
}
}
注意:
1.加载驱动com.mysql.jdbc.Driver适用于mysql5…版本;对于mysql8…要使用com.mysql.cj.jdbc.Driver
前两个步骤完成后可以运行测试一下,运行结果显示如下就成功
3.获取Statement
完成以上操作后,就可以在idea中对数据库进行增删改查操作
1.首先需要获取Statement
Statement
1.Statement
Statement是将拼接的SQL在服务端直接执行
Statement statement = connection.createStatement();
String sql = "select * from user where name = "+name+" and password = "+passwd;
ResultSet resultSet = statement.executeQuery(sql);
2.PreparedStatement
其中SQL中参数使用占位符"?"
和Statement不一样的地方是会先进行预编译,会先进行SQL语法的检查,SQL语法正确后才会执行
String sql = "select * from user where name = ? and password = ?";
PreparedStatement statement = connection.prepareStatement(sql);
statement.setString(1,name);
statement.setString(2,passwd);
ResultSet resultSet = statement.executeQuery(sql);
3.CallableStatement
回调函数
2.写sql命令
这里以SID=1为例来进行查询
//3.进行增删改查操作
//获取Statement
Statement statement = connection.createStatement();
String sql = "select * from student where SID = 1";
//查询操作使用executeQuery
//使用ResultSet表示返回的结果集
ResultSet resultSet = statement.executeQuery(sql);
//处理result结果
//需要判断是否有数据
while(resultSet.next()){
//在这里可以指定需要返回的数据类型
String SID = resultSet.getString("SID");
String Sname = resultSet.getString("Sname");
String Sage = resultSet.getString("Sage");
System.out.println("SID:"+SID+",Sname:"+Sname+",Sage:"+Sage);
}
注意:
1.Statement是一个接口
2.查询操作调用executeQuery
3.使用ResultSet表示返回的结果集,ResultSet可以包含一个对象,也可以包括多个对象。多个对象时,每调用一次next()方法,处理结果集的一行数据
通过.next()判断是否有数据(true:有数据)
4.ResultSet支持返回各种类型
5.获取数据时,getString里面的值必须和数据库中的属性名相同
数据库基本操作
1.查询:statement.executeQuery
2.修改and删除statement.executeUpdate或者statement.execute
4.关闭资源
关闭客户端和服务端的连接
//关闭资源
connection.close();
运行结果:
小结
总结一下JDBC编程流程:
1、引入驱动包路径 Class.fromName
2、连接数据库 DriverManager.getConnection(url,name,passwd)获取Connection对象
3、获取Statement对象,通过Connection对象来获取
4、通过Statement执行SQL语句
5、查询操作会获取ResultSet结果集对象
6、关闭资源(主要是connection)
上面主要说明了查询操作,下面我们对代码进行优化一下
package com.xiancaijing;
import java.sql.*;
public class JDBCDemo {
private static Connection connection;
public static void main(String[] args){
selectUserBySID("1");
}
public static void getConnection(){
//1.加载MySQL驱动 com.mysql.jdbc.Driver
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//2.连接数据库
try {
//获取Connection
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mysqltest","root","123456");
}catch (Exception e){
}
}
public static void close(){
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
public static void selectUserBySID(String SID) {
getConnection();
try {
Statement statement = connection.createStatement();
String sql = "select * from student where SID ="+SID;
ResultSet resultSet = statement.executeQuery(sql);
//处理result结果
//需要判断是否有数据
while(resultSet.next()){
String SID1 = resultSet.getString("SID");
String Sname = resultSet.getString("Sname");
String Sage = resultSet.getString("Sage");
System.out.println("SID:"+SID1+",Sname:"+Sname+",Sage:"+Sage);
}
//关闭资源
close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
上面这个代码就是对之前的代码进行了封装,这样的代码就不仅仅适用于查询,数据库中删除、修改操作都可以直接使用,使我们的代码更简洁
SQL注入
通过输入的参数和SQL进行拼接的查询数据库,为了绕开正常SQL逻辑而添加一些额外的SQL信息来来达到访问数据库的目的。
例:只知道账号,不知道密码,也可以登录成功
public static String login(String name ,String passwd){
getConnetion();
try {
Statement statement = connection.createStatement();
String sql = "select * from user where name = "+name+" and password = "+passwd;
// select * from user where name = XXX and password =XXX
//select * from user where name = XXX or 1=1 and password =XXX
ResultSet resultSet = statement.executeQuery(sql);
if (resultSet.next()) {
return "success";
} else {
return "fail";
}
} catch (SQLException e) {
e.printStackTrace();
}
close();
return "fail";
}
解决SQL注入
前面我也分别介绍了PreparedStatement和Statement,因为PreparedStatement将SQL和参数分别传递给服务端,先进行预编译,可以检查SQL语法,所以可以用PreparedStatement避免SQL注入问题
public static String login1(String name ,String passwd){
getConnetion();
try {
String sql = "select * from user where name = ? and password = ?";
PreparedStatement statement = connection.prepareStatement(sql);
statement.setString(1,name);
statement.setString(2,passwd);
ResultSet resultSet = statement.executeQuery(sql);
if (resultSet.next()) {
return "success";
} else {
return "fail";
}
} catch (SQLException e) {
e.printStackTrace();
}
close();
return "fail";
}
JDBC处理事务
jdbc操作事务在Connection实例下提供的方法来进行事务相关操作
提交事务
connection.commit();
事务回滚
connection.rollback();
保存点
connection.setSavepoint();
回滚到指定的保存点
Savepoint point1 = connection.setSavepoint("point1");
connection.rollback(point1);
连接池
在JDBC使用中,每次都需要连接数据库(获取connection对象),关闭资源,这次会造成一定浪费,为了把连接数据库进行一个复用,就有了连接池。
基本原理
在创建连接池时,就先初始化指定数量的连接,将建立的连接放入到池中,当有新的SQL操作请求时,可以在池中获取一个空闲的连接来执行SQL操作,当SQL执行完成后将连接放入池中重复使用。当池中的连接都在使用时,而且连接数没有到达最大的时候,就可以新创建一个连接来执行新的SQL请求操作,如果已经达到了最大的连接数且所有的连接都在使用时可以将新连接进行拒绝或者是通过缓存先存储等有空闲连接在此执行,有空闲时间阈值,当一个连接空闲的时间超过阈值,就自动进行销毁。
使用优势
1、对资源进行复用
2、对资源的进行统一的管理
3、提高了系统资源的利用率
常见的连接池
c3p0,Druid,dbcp…
连接池使用步骤
1.引入依赖
2.配置连接池
3.使用连接池
C3p0连接池
1.引入依赖
在pom.xml文件中引入依赖
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>
2.配置连接池
在main路径下的resources文件下创建c3p0-config.xml配置文件。
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
<!--配置连接池mysql-->
<named-config name="mysql">
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/ssms</property>
<property name="user">root</property>
<property name="password">123456</property>
<!-- 初始化连接数 -->
<property name="initialPoolSize">10</property>
<!--最大空闲时间,多少秒内未使用则连接被丢弃。若为0则永不丢弃。Default: 0 -->
<property name="maxIdleTime">30</property>
<!--连接池中保留的最大连接数。Default: 15 -->
<property name="maxPoolSize">100</property>
<!-- 最小连接数 -->
<property name="minPoolSize">10</property>
</named-config>
</c3p0-config>
3.C3p0连接池的使用
在java.com.xiancaijing路径下创建一个C3p0Demo类使用以下C3p0连接池
package com.xicai.mavontest;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class C3p0Demo {
public static void main(String[] args) {
//设置数据源DataSource
ComboPooledDataSource dataSource = new ComboPooledDataSource("mysqltest");
try {
//获取Connection
Connection connection = dataSource.getConnection();
//获取Statement对象
Statement statement = connection.createStatement();
String sql = "select * from user where id = 25";
ResultSet resultSet = statement.executeQuery(sql);
while (resultSet.next()) {
Integer id1 = resultSet.getInt("id");
String account = resultSet.getString("account");
String name = resultSet.getString("name");
System.out.println("Id:" + id1 + ",name:" + name);
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}