目录
一.JDBC概述
概念:JDBC(Java DataBase Connectivity):Java数据库连接技术:具体就通过Java连接广泛的数据库,并对表中数据执行增删改查等操作的技术。作用是可以通过Java代码操作数据库。
本质:JDBC 的本质就是java官方提供的一套规范(接口)。用于帮助开发人员快速是实现不同关系型数据库的连接。
作用:本质上JDBC的作用和图形化客户端的作用相同,都是发送SQL操作数据库。差别在图形化界面的操作是图形化,傻瓜化的,而JDBC则需要通过编码完成图型操作时的效果。主要是通过JDBC技术与数据库进行交互,使用Java语言发送SQL语句到数据库中,可以实现对数据的增删改查等功能,可以更高效、安全的管理数据。JDBC也是数据库与Java代码的桥梁(链接)
好处:各数据库厂商使用不同的接口,Java代码不需要针对不同数据库分别开发。可以随时替换底层数据库,访问数据库的Java代码基本不变
二.JDBC技术的接口
接口 | 作用 |
Driver | 驱动接口 ,定义建立链接的方式 |
DriverManager | 工具类,用于管理驱动,可以获取数据库的链接 |
Connection | 表示Java与数据库建立的连接对象(接口) |
PreparedStatement | 发送SQL语句的工具 |
ResultSet | 结果集,用于获取查询语句的结果 |
三.JDBC模拟实现
package com.syxhhh.jbdc.myjdbc;
public interface jdbcinterface {
//连接
public Object getConnection();
//crud
public void crud();
//关闭连接
public void close();
}
package com.syxhhh.jbdc.myjdbc;
/**
* mysql数据库实现了jdbc接口(模拟)
*/
public class Mysqljdbc implements jdbcinterface {
@Override
public Object getConnection() {
System.out.println("得到mysql的连接");
return null;
}
@Override
public void crud() {
System.out.println("完成mysql的增删改查");
}
@Override
public void close() {
System.out.println("关闭mysql的连接");
}
}
package com.syxhhh.jbdc.myjdbc;
public class TestJDBC {
public static void main(String[] args) {
jdbcinterface Jdbcinterface=new Mysqljdbc();
Jdbcinterface.getConnection();//通过接口来调用实现类
Jdbcinterface.crud();
Jdbcinterface.close();
}
}
四.JDBC代码步骤
1.创建工程,导入驱动jar包
导入jar包之前要在MySQL官网下载对应版本的包
打开MySQL官网点击download
点击connector/J
windows系统在Select Operating System中选择Platform Independent,如果下载最新版本的就点击橙色的,这里我下载的是5.1.48版本,点击Archives可以选择以往的版本,最后点击zip文件下载即可。把下载好的文件复制粘贴给在idea中创建的模块中,最后右键找到Add as Library点击就完成了导包。
2.注册驱动
3.获取连接
获取连接时候一定要把连接,用户名和密码写对。连接一般是我写的那个,用户名和密码是自己设的。
4.定义SQL语句
5.获取执行SQL对象
6.执行SQL
7.处理返回的结果
8.释放资源
在idea中运行的结果是这样的就证明运行正确,这个时候在SQL中重新运行就会发现表中的数据也改变了,我写的案例的结果是id为1的员工的金额变成了3000
五.API详解
一.DriverManager驱动管理对象
概念:DriverManager 类是 JDBC 的管理层,作用于用户和驱动程序之间。它跟踪可用的驱动程序,并在数据库和相应驱动程序之间建立连接。另外,DriverManager 类也处理诸如驱动程序登录时间限制及登录和跟踪消息的显示等事务。对于简单的应用程序,一般程序员需要在此类中直接使用的唯一方法是 DriverManager.getConnection。正如名称所示,该方法将建立与数据库的连接。JDBC 允许用户调用 DriverManager 的方法 getDriver、getDrivers 和 registerDriver 及 Driv
作用:注册驱动,获取数据库连接
1.注册驱动:告诉程序该使用哪一个数据库驱动jar
Class.forName("com.mysql.jdbc.Driver");
Driver类源代码
public class Driver extends NonRegisteringDriver implements java.sql.Driver {
public Driver() throws SQLException {
}
static {
try {
DriverManager.registerDriver(new Driver());
} catch (SQLException var1) {
throw new RuntimeException("Can't register driver!");
}
}
}
提示:MySQL5之后的驱动包,可以省略注册驱动的步骤,自动加载jar包中的META-INF/services/java.sql.Driver文件中的驱动类
2.获取数据库连接
获取连接:static Connection getConnection(String url,String user,String password)
参数
1)url连接路径
语法:jdbc:mysql://ip地址(域名):端口号/数据库名称?参数键值对1&参数键值对2......
细节:如果连接的是本机mysql服务器,并且mysql服务默认端口是3306,则url可以简写为:jdbc:mysql:///数据库名称?参数键值对。配置useSSL=false参数,禁用安全连接方式解决警告问题
2)user:用户名
3)password:密码
package com.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
public class JDBCDemo {
public static void main(String[] args) throws Exception{
//1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2.获取连接
String url="jdbc:mysql:///db1?useSSL=false";
String username="root";
String password="123456";
Connection conn= DriverManager.getConnection(url,username,password);
//3.定义mysql
String sql="UPDATE jdbc SET money=3000 WHERE id='1'";
//4.获取执行sql的对象
Statement stmt=conn.createStatement();
//5.执行sql
int count=stmt.executeUpdate(sql);
//6.处理结果
System.out.println(count);
//7.释放资源
stmt.close();
conn.close();
}
}
结果是这样的
二、Connection 数据库连接对象
功能:获取执行SQL的对象,管理事务
1.获取执行SQL对象
普通执行SQL对象:Statement createStatement()
预编译SQL的执行SQL对象,防止SQL注入:PreparedStatement preparedStatement(sql)
执行存储过程的对象:CallableStatement prepareCall(sql)
2.事务管理
1)MySQL事务管理
开启事务:BEGIN;/START TRANSACTION;
提交事务:COMMIT;
回滚事务:ROLLBACK;
MySQL默认自动提交事务
2)JDBC事务管理:Connection接口中定义了3个对应的方法
开启事务:setAutoCommit(boolean autoCommit):true为自动提交事务,false为手动提交事务,即为开启事务
提交事务:commit()
回滚事务:rollback()
package com.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class JDBCDemo {
public static void main(String[] args) throws Exception{
//1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2.获取连接
String url="jdbc:mysql:///db1?useSSL=false";
String username="root";
String password="123456";
Connection conn= DriverManager.getConnection(url,username,password);
//3.定义mysql
String sql1="UPDATE jdbc SET money=3000 WHERE id='1'";
String sql2="UPDATE jdbc SET money=3000 WHERE id='2'";
//4.获取执行sql的对象
Statement stmt=conn.createStatement();
//5.执行sql
try {
//开启事务
conn.setAutoCommit(false);
int count1= stmt.executeUpdate(sql1);
System.out.println(count1);
int count2= stmt.executeUpdate(sql2);
System.out.println(count2);
conn.commit();
} catch (Exception e) {
//回滚事务
conn.rollback();
throw new RuntimeException(e);
}
//7.释放资源
stmt.close();
conn.close();
}
}
三.Statement
概念:Statement 是 Java 执行数据库操作的一个重要接口,用于在已经建立数据库连接的基础上,向数据库发送要执行的SQL语句。Statement对象,用于执行不带参数的简单SQL语句(用于执行静态 SQL 语句并返回它所生成结果的对象。
作用:执行SQL语句
1.执行SQL语句
int executeUpdate(sql):执行DML,DDL语句
返回值:(1)DML语句影响的行数(2)DDL语句执行后,执行成功也可能返回0
ResultSet executeQuery(sql):执行DQL语句
返回值:ResultSet结果及对象
package com.jdbc;
import org.junit.Test;
import javax.annotation.processing.SupportedAnnotationTypes;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class JDBCDemo {
@Test
public void testDML() throws Exception {
//1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2.获取连接
String url = "jdbc:mysql:///db1?useSSL=false";
String username = "root";
String password = "123456";
Connection conn = DriverManager.getConnection(url, username, password);
//3.定义mysql
String sql = "UPDATE jdbc SET money=3000 WHERE id='5'";
//4.获取执行sql的对象
Statement stmt = conn.createStatement();
//5.执行事务
int count = stmt.executeUpdate(sql);//执行完DML语句后受影响的行数
//6.处理结果
if(count>0) {
System.out.println("修改成功~");
}else{
System.out.println("修改失败~");
}
//7.释放资源
stmt.close();
conn.close();
}
}
四.ResultSet结果集对象
作用:封装了DQL查询语句的结果
1.封装了DQL查询语句的结果
ResultSet stmt.executeQuery(sql):执行DQL语句,返回ResultSet对象
1)获取查询结果
boolean next():将光标从当前位置向前移动一行,判断当前行是否为有效行
返回值:true是有效行,当前行有数据。false是无效行,当前没有行数据
*** get***(参数):获取数据
***:数据类型 如:int getInt(参数);
参数:int:列的编号,从1开始
String:列的名称
2)使用步骤
游标向下移动一行,并判断改行是否有数据:next()。使用get***(参数)获取数据
package com.jdbc;
import org.junit.Test;
import javax.annotation.processing.SupportedAnnotationTypes;
import java.sql.*;
public class JDBCDemo {
@Test
public void testResultSet() throws Exception {
//1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2.获取连接
String url = "jdbc:mysql:///db1?useSSL=false";
String username = "root";
String password = "123456";
Connection conn = DriverManager.getConnection(url, username, password);
String sql="select*from jdbc";
Statement stmt=conn.createStatement();
ResultSet rs=stmt.executeQuery(sql);
while(rs.next()){
String id=rs.getString(1);
String name=rs.getString(2);
int money=rs.getInt(3);
System.out.println(id);
System.out.println(name);
System.out.println(money);
}
rs.close();
stmt.close();
conn.close();
}
}
五.PreparedStatement
概念:我们写的SQL语句让数据库执行,数据库不是直接执行SQL语句字符串,数据库需要执行编译后的SQL语句
好处:预编译SQL,性能更高,防止SQL注入,将敏感字符进行转译
原理:在获取PreparedStatement对象时,将sql语句发送给mysql服务器进行检查,编译,执行时就不用进行这些步骤了,速冻很快,如果sql模板一样,则只需要进行一次检查,编译
作用:解决SQL注入问题。提高了程序的可读性。一条SQL语句重复执行多次的时候,可以提高效率。
1.SQL注入:SQL注入是通过操作输入来修改事先定义好的SQL语句,用以达到执行代码对服务器进行攻击的方法
需求:完成用户登录:select*from 表名 where 键值对 and 键值对;
package com.jdbc;
import org.junit.Test;
import javax.annotation.processing.SupportedAnnotationTypes;
import java.sql.*;
public class JDBCDemo {
@Test
public void testResultSet() throws Exception {
//1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2.获取连接
String url = "jdbc:mysql:///db1?useSSL=false";
String username = "root";
String password = "123456";
Connection conn=DriverManager.getConnection(url,username,password);
//接收用户输入 用户名和密码
String name="zhangsan";
String pwd="'or'1'='1";
String sql="select*from tb_user where username ='"+name+"' and password='"+pwd+"'";
//获取stmt对象
Statement stmt=conn.createStatement();
//执行sql
ResultSet rs=stmt.executeQuery(sql);
//判断是否登录成功
if(rs.next()){
System.out.println("登录成功");
}else{
System.out.println("登陆失败");
}
rs.close();
stmt.close();
conn.close();
}
}
2.PreparedStatement作用:预编译SQL并执行SQL语句
1)获取PreparedStatement对象
SQL语句中的参数值,使用?占位符代替
String sql=“select*from user where username=? and password=?”;
通过Connection对象获取,并传入对应的SQL语句
PreparedStatement pstmt=conn.preparedStatement(sql);
2)设置参数值
PreparedStatement对象:set***(参数1,参数2):给?赋值
***:数据类型;如setInt(参数1,参数2)
参数:参数1:?的位置编号,从1开始
参数2:?的值
3)执行SQL
executeUpdate();/executeQuery();:不需要再传递sql
package com.jdbc;
import org.junit.Test;
import javax.annotation.processing.SupportedAnnotationTypes;
import java.sql.*;
public class JDBCDemo {
@Test
public void testResultSet() throws Exception {
//1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2.获取连接
String url = "jdbc:mysql:///db1?useSSL=false";
String username = "root";
String password = "123456";
Connection conn=DriverManager.getConnection(url,username,password);
//接收用户输入 用户名和密码
String name="zhangsan";
String pwd="123";
String sql="select*from tb_user where username=? and password=?";
PreparedStatement pstmt=conn.prepareStatement(sql);
pstmt.setString(1,name);
pstmt.setString(2,pwd);
ResultSet rs=pstmt.executeQuery();
//判断是否登录成功
if(rs.next()){
System.out.println("登录成功");
}else{
System.out.println("登陆失败");
}
rs.close();
pstmt.close();
conn.close();
}
}
密码会被转译,所以输入’or‘1’=‘1’也是登陆失败
六.数据库连接池
概念:数据库连接池是用来分配、管理和释放数据库连接的,它允许应用程序重复使用一个现有的数据库连接,不需要重新创建,释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗漏,提高数据库操作的性能。
好处:节省资源,如果每次访问数据库都创建新的连接,创建和销毁都浪费系统资源。响应性更好,省去了创建的时间,响应性更好。统一管理数据库连接,避免因为业务的膨胀导致数据库连接的无限增多。便于监控。
1.数据库连接池实现
1)标准接口:DataSource
官方提供的数据库连接池标准接口,由第三方组织实现此接口,功能是获取连接
Connection getConnection()
2)常见的数据库连接池
DBCP,C3P0,Druid
3)Druid(德鲁伊)
是阿里巴巴开源的数据库连接池项目,功能强大,性能优秀,是Java语言最好的数据库连接池之一
2.Druid使用步骤
1)导入jar包
2)定义配置文件
3)加载配置文件
4)获取数据库连接池对象
5)获取连接
package druid.druid;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import java.io.FileInputStream;
import java.sql.Connection;
import java.util.Properties;
public class DruidDemo {
//定义配置文件
//加载配置文件
Properties prop=new Properties();
prop.load(new FileInputStream("jdbc-demo/src/druid.properties"));
//获取连接池对象
DataSourse dataSourse= DruidDataSourceFactory.createDataSource(prop);
//获取数据库连接
Connection connection=dataSourse.getConnection();
System.out.println(connection);
}