JDBC编程

  • 前言
  • 一、简介(面向接口编程)
  • 二、JDBC操作步骤
    • 2.1创建工程,导入驱动jar包
    • 2.2JDBC代码快速实现
  • 三、JDBC的API详解
    • 3.1DriverManager
    • 3.2Connection
      • 事务管理代码演示
    • 3.3Statement
    • 3.4ResultSet
    • 3.5PreparedStatement
    • 3.6PreparedStatement原理
  • 四、数据库连接池
    • 4.1简介
    • 4.2数据库连接池的实现
  • 总结

前言

本文主要介绍了java面向JDBC编程的基本知识和用到的接口和方法。

一、简介(面向接口编程)

JDBC概念:
JDBC就是使用Java语言操作关系型数据库的一套API
JDBC(Java Database Connectivity)全称为Java数据库连接。
JABC是一套连接数据库的标准接口,Java可以通过JDBC编程实现操作不同的数据库。
不同的数据库想要被Java代码操作,都要定义自己对于JDBC的实现类,也就是数据库驱动
JDBC本质:
官方(sun公司)定义的一套所有关系型数据库的规则,即接口
各个数据库厂商去实现这套接口,提供数据库驱动jar包
我们可以使用这套接口(JDBC)编程,真正执行的代码是驱动jar包中的实现类。
JDBC好处
各数据库厂商使用相同的接口,Java代码不需要针对不同数据库分别开发
可随时替换底层数据库,访问数据库的Java代码基本不变。
这种方式也叫面向接口编程。


二、JDBC操作步骤

2.1创建工程,导入驱动jar包

1.创建好工程后,右击工程名,点击New->Directory,创建一个lib目录



2.复制粘贴mysql驱动jar包到这个目录下

3.右击驱动jar包,点击Add as Library->Mudule Library->OK.导入成功



2.2JDBC代码快速实现

package com.practice;import java.sql.Connection;import java.sql.DriverManager;import java.sql.Statement;/** * @Author YJ * @Date 2023/7/19 10:06 * Description:JDBC编程 */public class JDBCDemo {public static void main(String[] args) throws Exception {//1.注册驱动Class.forName("com.mysql.jdbc.Driver");//2.获取连接//用户名和密码就是mysql注册时自己的用户名和密码//demo1表示要连接的数据库名String url = "jdbc:mysql://127.0.0.1:3306/demo1";String username = "root";String passWord = "123456";//DriverManager.getConnection有一个返回值Connection coon = DriverManager.getConnection(url, username, passWord);//3.定义sql语句String sql = "update emp set salary = 10000 where name='张三'";//4.获取执行sql的对象StatementStatement statement = coon.createStatement();//5.执行sql//返回影响的行数int count = statement.executeUpdate(sql);//6.处理结果System.out.println(count);//7.释放资源//倒着释放,先创建的后释放statement.close();coon.close();}}

上面的代码执行的sql语句是修改demo1数据库中的表emp中的内容,update emp set salary = 10000 where name='张三'表示将emp表中的姓名为张三的salary改为10000。
如下表示运行成功:

java运行结果

mysql表中原数据

代码执行后


三、JDBC的API详解

3.1DriverManager

DriverManager(驱动管理类):
1.注册驱动
2.获取数据库连接

1.注册驱动
在注册驱动时我们用到的是Class.forName("com.mysql.jdbc.Driver");而这段代码底层也是调用的DriverManager.registerDriver(),在mysql5之后的驱动jar包下,这段代码可以省略,这是因为在mysql驱动jar包目录下有一个META.INF文件夹,其中有一个services目录,里面有个文件java.sql.Driver,里面就记录了驱动的类的名称。

2.获取连接
getConnection​(String url, String user, String password)
1.url:连接路径
语法:jdbc:mysql://ip地址(域名):端口号/数据库名称" />3.2Connection

Connection(数据库连接对象):
1.获取执行sql的对象
2.管理事务

获取执行sql的对象
普通执行SQL对象
Statement createStatement()

**2.事务管理
MYSQL事务管理:
开启事务:BEGIN;/START TRANSACTION;
提交事务:COMMIT;
回滚事务:ROLLBACK;
MYSQL默认自动提交事务
JDBC事务管理:
通过Connection接口进行管理
开启事务:setAutoCommit(boolean autoCommit):true自动提交,false手动提交;
提交事务:commit()
回滚事务:rollback()


事务管理代码演示

package com.practice;import java.sql.Connection;import java.sql.DriverManager;import java.sql.SQLException;import java.sql.Statement;/** * @Author YJ * @Date 2023/7/19 10:36 * Description:JDBC编程--Connection */public class JDBCDemoConnection {public static void main(String[] args) throws Exception {//1.注册驱动//Class.forName("com.mysql.jdbc.Driver");//2.获取连接//用户名和密码就是mysql注册时自己的用户名和密码//demo1表示要连接的数据库名String url = "jdbc:mysql://127.0.0.1:3306/demo1?useSSL=false";String username = "root";String passWord = "123456";//DriverManager.getConnection有一个返回值Connection coon = DriverManager.getConnection(url, username, passWord);//3.定义sql语句String sql1 = "update emp set salary = 300 where name='张三'";String sql2 = "update emp set salary = 600 where name='李四'";//4.获取执行sql的对象StatementStatement statement = coon.createStatement();try {//开启事务coon.setAutoCommit(false);//5.执行sql//返回影响的行数int count1 = statement.executeUpdate(sql1);//5.执行sql//返回影响的行数int count2 = statement.executeUpdate(sql2);//6.处理结果System.out.println(count2);//提交事务coon.commit();} catch (Exception throwables) {//回滚事务coon.rollback();throwables.printStackTrace();}//7.释放资源 //倒着释放,先创建的后释放statement.close();coon.close();}}

结果

要注意的是:在进行事务回滚操作时,Java用的是异常处理机制。


3.3Statement

Statement作用:
执行sql语句
int executeUpdate(sql):执行DML、DDL语句
返回值:(1)DML语句影响的行数(2)DDL语句执行成功也可能返回0
ResultSet executeQuery(sql):执行DQL语句
返回值:ResultSet 结果集对象

package com.practice;import java.sql.Connection;import java.sql.DriverManager;import java.sql.Statement;/** * @Author YJ * @Date 2023/7/20 8:15 * Description:DML */public class JDBCDemo2 {public static void main(String[] args) throws Exception {//1.注册驱动//Class.forName("com.mysql.jdbc.Driver");//2.获取连接//用户名和密码就是mysql注册时自己的用户名和密码//demo1表示要连接的数据库名String url = "jdbc:mysql://127.0.0.1:3306/demo1" />;String username = "root";String passWord = "123456";//DriverManager.getConnection有一个返回值Connection coon = DriverManager.getConnection(url, username, passWord);//3.定义sql语句String sql = "update emp set salary = 300 where name='张三'";//4.获取执行sql的对象StatementStatement statement = coon.createStatement();//5.执行sql//返回影响的行数int count = statement.executeUpdate(sql);//6.处理结果if(count > 0) {System.out.println("修改成功~");} else {System.out.println("修改失败~");}//7.释放资源//倒着释放,先创建的后释放statement.close();coon.close();}}

3.4ResultSet

ResultSet(结果集对象)作用:
封装了DQL查询语句的结果
ResultSet stmt.executeQuery(sql):执行DQL语句,返回ResultSet对象
获取查询结果
boolean next():
(1)将光标从当前位置向前移动一行
(2)判断当前行是否为有效行
返回值:
true:有效行,当前行有数据
false:无效行,当前行无数据
xxx getXxx(参数):获取数据
xxx:数据类型;如int getInt(参数)
参数:
int :列的编号,从1开始
String:列的名称

package com.practice;import java.math.BigDecimal;import java.sql.Connection;import java.sql.DriverManager;import java.sql.ResultSet;import java.sql.Statement;/** * @Author YJ * @Date 2023/7/20 8:15 * Description:ResultSet执行DQL语句 */public class JDBCDemo5 {public static void main(String[] args) throws Exception {//1.注册驱动//Class.forName("com.mysql.jdbc.Driver");//2.获取连接//用户名和密码就是mysql注册时自己的用户名和密码//demo1表示要连接的数据库名String url = "jdbc:mysql://127.0.0.1:3306/demo1?useSSL=false";String username = "root";String passWord = "123456";//DriverManager.getConnection有一个返回值Connection coon = DriverManager.getConnection(url, username, passWord);//3.定义sqlString sql = "select * from emp";//4.获取Statement对象Statement stmt = coon.createStatement();//5.执行sqlResultSet resultSet = stmt.executeQuery(sql);//6.处理结果//6.1光标向下移动,判断是否有数据while (resultSet.next()) {//6.2获取数据String name = resultSet.getString(1);String sex = resultSet.getString(2);String depart = resultSet.getString(3);BigDecimal salary = resultSet.getBigDecimal(4);System.out.println(name);System.out.println(sex);System.out.println(depart);System.out.println(salary);System.out.println("-----------------------");}//也可在getXxx(参数)参数位置写sql中的字段名/*while (resultSet.next()) {//6.2获取数据String name = resultSet.getString("name");String sex = resultSet.getString("sex");String depart = resultSet.getString("depart");BigDecimal salary = resultSet.getBigDecimal("salary");System.out.println(name);System.out.println(sex);System.out.println(depart);System.out.println(salary);System.out.println("-----------------------");}*///7.释放资源resultSet.close();stmt.close();coon.close();}}

通过获取数据库的数据封装到一个集合中
1.创建一个类,与数据库数据类型相对应,创建一个该类的集合
2.获取数据库数据
3.将获取的数据封装到类中
4.将封装好的类添加到集合

package com.practice.pojo;import java.math.BigDecimal;/** * @Author YJ * @Date 2023/7/20 10:27 * Description:封装数据库数据的类 */public class Account {private String name;private String sex;private String depart;private BigDecimal salary;public Account() {}public Account(String name, String sex, String depart, BigDecimal salary) {this.name = name;this.sex = sex;this.depart = depart;this.salary = salary;}/** * 获取 * @return name */public String getName() {return name;}/** * 设置 * @param name */public void setName(String name) {this.name = name;}/** * 获取 * @return sex */public String getSex() {return sex;}/** * 设置 * @param sex */public void setSex(String sex) {this.sex = sex;}/** * 获取 * @return depart */public String getDepart() {return depart;}/** * 设置 * @param depart */public void setDepart(String depart) {this.depart = depart;}/** * 获取 * @return salary */public BigDecimal getSalary() {return salary;}/** * 设置 * @param salary */public void setSalary(BigDecimal salary) {this.salary = salary;}public String toString() {return "Account{name = " + name + ", sex = " + sex + ", depart = " + depart + ", salary = " + salary + "}";}}
package com.practice;import com.practice.pojo.Account;import java.math.BigDecimal;import java.sql.Connection;import java.sql.DriverManager;import java.sql.ResultSet;import java.sql.Statement;import java.util.ArrayList;/** * @Author YJ * @Date 2023/7/20 10:26 * Description:ResultSet封装到一个集合中 */public class JDBCDemo7 {public static void main(String[] args) throws Exception {//1.注册驱动//Class.forName("com.mysql.jdbc.Driver");//2.获取连接//用户名和密码就是mysql注册时自己的用户名和密码//demo1表示要连接的数据库名String url = "jdbc:mysql://127.0.0.1:3306/demo1?useSSL=false";String username = "root";String passWord = "123456";//DriverManager.getConnection有一个返回值Connection coon = DriverManager.getConnection(url, username, passWord);//3.定义sqlString sql = "select * from emp";//4.获取Statement对象Statement stmt = coon.createStatement();//5.执行sqlResultSet resultSet = stmt.executeQuery(sql);//创建集合ArrayList<Account> list = new ArrayList<>();//6.处理结果//6.1光标向下移动,判断是否有数据while (resultSet.next()) {Account account = new Account();//6.2获取数据String name = resultSet.getString("name");String sex = resultSet.getString("sex");String depart = resultSet.getString("depart");BigDecimal salary = resultSet.getBigDecimal("salary");//赋值account.setName(name);account.setSex(sex);account.setDepart(depart);account.setSalary(salary);//存入集合list.add(account);}System.out.println(list);//7.释放资源resultSet.close();stmt.close();coon.close();}}

3.5PreparedStatement

PreparedStatement作用:
1.预编译SQL语句并执行:预防SQL注入问题
SQL注入:是通过操作输入来修改事先定义好的SQL语句,用以达到执行代码对服务器进行攻击的方法。
SQL注入演示:

package com.practice;import com.practice.pojo.Account;import java.math.BigDecimal;import java.sql.Connection;import java.sql.DriverManager;import java.sql.ResultSet;import java.sql.Statement;import java.util.ArrayList;/** * @Author YJ * @Date 2023/7/20 10:26 * Description:ResultSetSQL注入演示 */public class JDBCDemo8 {public static void main(String[] args) throws Exception {//1.注册驱动//Class.forName("com.mysql.jdbc.Driver");//2.获取连接//用户名和密码就是mysql注册时自己的用户名和密码//demo1表示要连接的数据库名String url = "jdbc:mysql://127.0.0.1:3306/demo1?useSSL=false";String username = "root";String passWord = "123456";Connection coon = DriverManager.getConnection(url, username, passWord);String name = "afafafaf";String depart = "' or '1' = '1";String sql = "select * from emp where name = '"+name+"' and depart = '"+depart+"' ";//获取stmt对象Statement stmt = coon.createStatement();//执行sqlResultSet resultSet = stmt.executeQuery(sql);//判断登录是否成功if (resultSet.next()) {System.out.println("有数据~");} else {System.out.println("无数据!");}//7.释放资源resultSet.close();stmt.close();coon.close();}}


1.预编译SQL并执行SQL语句
(1)获取PreparedStatement对象
//SQL语句中的参数使用" />
//通过Connection对象获取,并传入对应的sql语句
PreparedStatement pstmt = coon.preparedStatement(sql);
(2)设置参数值
PreparedStatement 对象:setXxx(参数一,参数二):给?赋值
(3)执行sql
exxcuteUpdate():/executeQuery();:不需要在传递sql

package com.practice;import java.sql.*;/** * @Author YJ * @Date 2023/7/20 10:26 * Description:ResultSet解决SQL注入 */public class JDBCDemo9 {public static void main(String[] args) throws Exception {//1.注册驱动//Class.forName("com.mysql.jdbc.Driver");//2.获取连接//用户名和密码就是mysql注册时自己的用户名和密码//demo1表示要连接的数据库名String url = "jdbc:mysql://127.0.0.1:3306/demo1?useSSL=false";String username = "root";String passWord = "123456";Connection coon = DriverManager.getConnection(url, username, passWord);String name = "afafafaf";String depart = "' or '1' = '1";//定义sqlString sql = "select * from emp where name = ? and depart = ? ";//获取对象PreparedStatement prept = coon.prepareStatement(sql);//设置?的值prept.setString(1,username);prept.setString(2,depart);//执行sqlResultSet resultSet = prept.executeQuery();//判断登录是否成功if (resultSet.next()) {System.out.println("有数据~");} else {System.out.println("无数据!");}//7.释放资源resultSet.close();prept.close();coon.close();}}


3.6PreparedStatement原理

PreparedStatement好处:
1.预编译SQL,性能更高
2.预防SQL注入:将敏感字符进行转义
预编译功能开启:useServerPrepStmts=true
同时还要在mysql安装目录下的my.ini文件中设置一串代码:

log-output=FILEgeneral-log=1general_log_file="D:\MyApp\mysql.log"slow-query-log=1slow_query_log_file="D:\MyApp\mysql_slow.log"long_query_time=2

PreparedStatement原理:
1.在获取PreparedStatement对象时,将sql语句发送给mysql服务器进行检查、编译(很耗时)
2.执行时就不用在进行这些步骤了,速度很快
3.如果sql模板一样,则只需进行一次检查、编译
当预编译功能开启后,每次执行代码,都会在日志文件中记录。

四、数据库连接池

4.1简介

数据库连接池是个容器,负责分配、管理数据库连接(Connection)
它允许应用程序重复使用一个现有的数据库连接,而不是重新建立一个
释放空间时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗漏
好处:
资源重用
提升系统响应速度
避免数据库连接遗漏

4.2数据库连接池的实现

标准接口:DataSource
官方提供的数据库连接池标准接口,由第三方组织实现此接口。
功能:获取连接
Connection getConnection()
常见的数据库连接池
DBCP
C3P0
Druid
Druid(德鲁伊)
是阿里巴巴开源的数据库连接池项目
功能强大,性能优秀,时Java语言最好的数据连接池之一

1.导入druid.jar包,方法同mysql.jar包的导入
2.定义配置文件:
定义一个文件druid.properties并编写如下代码:

driverClassName=com.mysql.jdbc.Driverurl=jdbc:mysql///demo1useSSL=false&useServerPrepStmts=trueusername=rootpassword=123456# 初始化连接数量initialSize=5# 最大连接数maxActive=10# 最大等待时间maxWait=3000
package com.practice.druid;import com.alibaba.druid.pool.DruidDataSourceFactory;import javax.sql.DataSource;import java.io.FileInputStream;import java.sql.Connection;import java.util.Properties;/** * @Author YJ * @Date 2023/7/20 12:44 * Description:Druid 数据库连接池演示 */public class DruidDemo1 {public static void main(String[] args) throws Exception {//加载配置文件//获取连接池对象Properties prop = new Properties();prop.load(new FileInputStream("jdbc-7-20/src/druid.properties"));DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);//获取数据库连接Connection coon = dataSource.getConnection();System.out.println(coon);}}

总结

经过本文的学习,我们可以初步的掌握JDBC编程,来实现java与数据库的连接和管理,通过java实现对数据库的增删改查操作,欢迎小伙伴们点赞+评论,我会持续学习更新!!!