文章目录
- 1、概述
- 2、JDBC使用步骤
- 3、DriverManager
- 4、Connection
- 5、Statement
- 6、ResultSet
- 7、PreparedStatement
- 8、数据库连接池
- 8.1、概述
- 8.2、数据库连接池的实现
- 8.3、Druid的使用
1、概述
JDBC概念:
- JDBC就是使用Java语言操作关系型数据库的API。
- 全称:
Java DataBase Conectivity
,Java数据库连接
- 正常情况下,一套Java代码不能操作不同的关系型数据库,因为每种数据库底层都不同。JDBC就是为了解决这一问题而出现,一套JDBC代码可以操作MySQL、Oracle、IBM等不同的数据库。
- JDBC只是定义了一套接口(也就是规则),具体的实现类由不同的数据库厂商自己定义,厂商们将实现类称为
驱动
。
JDBC本质:
- 官方(sun公司)定义的一套操作所有关系型数据库的规则,即
接口
。 - 各个数据库厂商去实现这套接口,提供数据库驱动
jar包
,我们需要使用哪个数据库就要再项目导入对应的jar包。 - 我们可以使用这套接口(JDBC)编程,真正执行的代码是驱动jar包中的实现类。
JDBC好处:
- 我们通过一套Java代码可以操作不同的数据库。
- 可以随时替换底层数据库,访问数据库的Java代码基本不变。
2、JDBC使用步骤
代码语言:javascript复制public class JDBC {
public static void main(String[] args) throws Exception {
// 1. 注册驱动,此步骤在MySQL5.0版本后可省,因为在lib/META-INF/services/java.sql.Driver文件里记录了驱动的名称,会自动加载。
Class.forName("com.mysql.Driver");
// 2.获取连接
String url = "jdbc:mysql://ip地址(域名)/端口号/数据库名称[?参数键值对1&参数键值对2]";
// String url = "jdbc:mysql://ip地址(域名)/端口号/数据库名称?useSSl=false"解决控制栏警告提示
String username = "数据库账户名";
String password = "数据库密码";
Connection connection = DriverManager.getConnection(url,username,password);
// 此处可开启事务
// 3.定义sql
String sql = "update account set money = 20000 where id = 1";
// 4.获取执行sql的对象 statement
Statement statement = connection.createStatement();
// 5.执行sql
int count = statement.executeUpdate(sql);
// 6.处理结果
System.out.println(count);
// 此处可提交事务
// 7.释放资源
statement.close();
connection.close();
}
}
3、DriverManager
DriverManager(驱动管理类)作用:
- 注册驱动:
Class.forName("com.mysql.Driver")
此步骤在MySQL5.0版本后可省略
,因为在lib/META-INF/services/java.sql.Driver文件里记录了驱动的名称,会自动加载。 - 获取数据库连接:
Connection connection = DriverManager.getConnection(url,username,password);
- 其中url
="jdbc:mysql://ip地址(域名)/端口号/数据库名称?参数键值对1&参数键值对2"
- 若连接的是本机MySQL服务器,并且MySQL默认端口是3306,则俩可以简写为:
jdba:mysql:///数据库名称[?参数键值对1,参数键值对2]
- 在域名后面添加useSSl=false参数,禁用安全连接方式,解决控制栏警告提示。
jdbc:mysql://ip地址(域名)/端口号/数据库名称?useSSl=false
- 其中url
4、Connection
Connection(数据库连接对象)作用:
获取执行sql的对象
- 普通执行sql对象:
Statement createStatement()
- 预编译sql的执行失去了对象:防止sql注入:
PreparedStatement prepareStatement(sql)
- 执行存储过程的对象:
CallableStatement prepareCall(sql)
管理事务
- MySQL事务管理
开启事务:BEGIN或START TRANSACTION;
提交事务:COMMIT
回滚事务:ROLLBACK
- JDBC事务管理:Connection接口中定义了3个对应的方法,默认自动提交事务。
开启事务:setAutoCommit(true/false),true为自动提交,false为手动提交,即开启事务
提交事务:commit
回滚事务:rollback
开启事务
在定义sql之前
;提交事务
在处理完数据库返回的结果后
;回滚事务
在catch
中进行,用try-catch处理sql语句,若出现异常则进行相应的回滚操作。
示例:
try{
// 开启事务
connection.setAutoCommit(fale);
// 定义sql
String sql = "update account set money = 20000 where id = 1";
// 获取执行sql的对象 statement
Statement statement = connection.createStatement();
// 执行sql
int count = statement.executeUpdate(sql);
// 处理结果
System.out.println(count);
// 提交事务
connection.commit();
} catch(Exception throwables){
// 回滚事务
connection.rollback();
}
5、Statement
Statement作用:执行sql语句
int executeUpdate(sql)
:执行DML(对表的操作)、DDL(对数据的增删改)。 返回值:- DML语句影响的行数
- DDL语句执行后,执行成功也可能返回0
ResultSet executeQuery(sql)
:执行DQL(select查询语句)。 返回值:ResultSet结果集对象
6、ResultSet
ResultSet(结果集对象)作用:
- 封装了DQL查询语句的结果:
ResultSet statement.executeQuery(sql);
执行select语句,返回ResultSet对象
获取查询结果:
boolean next()
:- 将光标从当前位置向前移动一行。默认指向的表头行,非数据行;因而要获取数据需要将游标往下移动一行
- 判断当前行是否为有效行
- 返回值:
- 有效行,当前行由数据
- 无效行,当前行无数据
xxx getXxx(参数)
:获取数据,参数可以是具体的值,也可以是对应的字段。- xxx:数据类型。如:int getInt(参数);String getString(参数)
- int:列的编号(主键),从1开始。
- String:列的名称
我们查询出来的数据需要封装到ArrayList集合中,返回给前端,见以下案例:
需求:查询Account账户表数据,并将数据封装Account对象中,再将Account对象存入ArrayList集合。
创建Account实体类:
代码语言:javascript复制public class Account {
private in id;
private String name;
private double money;
public in getId(){
return id;
}
public void setId(int id){
this.id=id;
}
public String getName(){
return name;
}
public void setName(){
this.name=name;
}
public double getMoney(){
return name;
}
public void setMoney(){
this.money=money;
}
//这里只是为了查看效果
@Override
public String toString(){
return "Account{" "id="id ",name='" name ''' ",money="money '}';
}
}
JDBC,查询Account账户表数据,并将数据封装Account对象中,再将Account对象存入ArrayList集合
代码语言:javascript复制// 1.定义实体类Account
// 2.查询数据,封装到Account对象中
// 3.将Account对象存入ArrayList集合中
public class resultSet() {
public static void main(String[] args) throws Exception {
// 1. 注册驱动,此步骤在MySQL5.0版本后可省,因为在lib/META-INF/services/java.sql.Driver文件里记录了驱动的名称,会自动加载。
Class.forName("com.mysql.Driver");
// 2.获取连接
String url = "jdbc:mysql://ip地址(域名)/端口号/数据库名称[?参数键值对1&参数键值对2]";
// String url = "jdbc:mysql://ip地址(域名)/端口号/数据库名称?useSSl=false"解决控制栏警告提示
String username = "数据库账户名";
String password = "数据库密码";
Connection connection = DriverManager.getConnection(url,username,password);
// 3.定义sql
String sql = "select * from account";
// 4.获取执行sql的对象 statement
Statement statement = connection.createStatement();
// 5.执行sql
ResultSet res = statement.executeQuery(sql);
// 6.创建集合
List<Account> list = new ArrayList<>();
// 7.处理结果
// 光标向下移动一行,并判断当前行是否有数据
while(res.next()){
// 给每行记录创建一个Account对象
Account account = new Account();
// 获取数据
in id = res.getInt("id");
String name = res.getString("name");
double money = res.getDouble("money");
// 赋值
account.setId(id);
account.setName(name);
account.setMoney(money);
// 存入集合
list.add(account);
}
// 8.释放资源
res.close();
statement.close();
connection.close();
}
}
7、PreparedStatement
PreparedStatement作用:
- 预编译SQl语句并执行
- 防止SQL注入问题。
PreparedStatement优点:
- 预编译sql,性能更高
- 我们通过?来代替直接传入具体值,这一sql只需要编译一次sql语句。
- 若每次都直接传入具体值,sql就每次都要编译一次,而编译sql相对执行sql是比较耗时的。
- 防止sql注入
- 将敏感字符进行转义
开启PreparedStatement预编译功能:在url后面加上useServerPrepStmts=true
要查看日志,需要在MySQL配置文件中配置,然后重启服务器
代码语言:javascript复制log-output=FILE
general-log=1
gereral_log_file="D:mysql.log" #输出目录
slow-query-log=1
slow_query_log_file="D:mysql_slow.log"# 慢查询日志输出目录
long_query_time=2
PreparedStatement使用:
代码语言:javascript复制1.获取PrepareStatement对象
// SQL语句的参数设置为?,防止SQL注入
String sql="select * from user where username=? and password=?";
// 通过Connection对象获取,并传入对应的sql语句
PrepareStatement pstmt=connection.prepareStatement(sql);
2.设置?的值
//因为姓名和密码都是String类型,所以都是getString,根据值的数据类型来选择setXxx(parameterIndex,值),parameterIndex表示给第几个值设置值。
pstmt.setString(parameterIndex,name)
pstmt.setString(parameterIndex,pwd)
3.执行SQL
// 不需要将sql作为参数传入执行
executeQuery();//查询语句时使用
executeUpdate();//更新语句时使用
PreparedStatement原理:
- 在获取PreparedStatement对象时,将sql语句发送给MySQL服务器进行检查,编译。
- 执行时就不用再进行检查,编译。
- 如果sql模板一样,则只需要进行一次检查、编译。
SQL注入
- SQL注入是通过操作输入来修改事先定义好的SQL语句,用以达到执行代码对服务器进行攻击的方法。
- 简单的SQL注入代码,比如在登陆时密码框输入:
'' or '1'='1'
- 第一对’',表示截断sql查询的值,查询1=1也就是查询全表。
- 因为我们在查询账户密码的时候通过:
select * from user where username='" name "' and password='" pwd "'
这样的语句来拼接字符串,导致任何类型的值都可以被拼接成功。
- PreparedStatement解决sql注入原理:
- 通过
"select * from user where username=? and password=?"
用?代替值,在设置?的值的时候会对值进行转义。 - 比如:
'' or '1' = '1'
,把用户非法输入的单引号进行转义,最终传入参数作为一个整体执行,从而防止 SQL 注入,而 Statement 对象不会进行此操作。
- 通过
8、数据库连接池
8.1、概述
- 数据库连接池时一个容器,赋值分配、管理数据库连接(Connection)
- 即 将连接放入一个数据库连接池,当连接使用完后,不会立刻结束连接,而是将其放回连接池,供他人使用。
- 如果一个连接被占用的时间超过了规定时间,则会被释放,避免程序过多时引起数据库连接遗漏。就是连接池中的连接被全部占用,后来的程序找不到连接。
好处:
- 资源复用
- 提升系统响应速度,因为不用重复建立连接,建立网络连接是比较耗时的
- 避免数据库连接遗漏
8.2、数据库连接池的实现
- 标准接口:
DataSource
- 官方(SUN)提供的数据库连接池标准接口,由第三方组织实现此接口
- 功能:获取连接
Connection getConnection()
- 常见的数据库连接池:
- DBCP
- C3P0
- Druid
- Druid(德鲁伊)
- Druid连接池是阿里巴巴开源的数据库连接池i项目
- 功能强大,性能优秀,是Java最好的数据库连接池之一
8.3、Druid的使用
- 导入jar包到lib目录
- 在src下定义配置文件
druid.properties
driverClassName=com.mysql.jdbc.Driver
# 这里的url和JDBC连接数据库的url格式一样
url=jdbc:mysql://数据库ip
username=数据库账户
password=数据库密码
# 初始化连接数量
initialSize=5
# 最大连接数
maxActive=10
# 最大等待时间
maxWait=3000
- 加载配置文件
- 获取数据库连接池对象
- 获取连接
// 加载配置文件
Properties prop = new Properties();
// 路径不确定可以通过打印System.getProperty("user.dir")查看
prop.load(new FileInputStream("druid.properties配置文件路径"));
// 获取数据库连接池对象
// 这里可以传入不同参数创建连接池对象,使用的时候具体查看。可以先写该步骤再new相应的对象,也就是加载配置文件的步骤
DataSource dataSource = DruidDataSourceFactor.createDataSource(prop);
// 获取数据库连接connection
Connection connection = dataSource.getConnection();
System.out.println(connection);