JDBC数据库和连接池
JDBC概述
1.JDBC为访问不同的数据库提供了统一的接口,为使用者屏蔽了细节问题
2.Java程序员使用JDBC,可以连接提供任何了JDBC驱动程序的数据库系统,
从而完成对数据库的各种操作。
3.JDBC的基本原理
JDBC API
JDBC API是一系列的接口,它统一规范了应用程序与数据库的连接,执行SQL语句,
并得到返回结果等各类操作,相关类和接口在java.sql与javax.sql包中。
DriverManager驱动管理类
1.getConnection(url,user,pwd);获取连接
Connection接口
1.creatStatement():生成命令对象
2.prepareStatement(sql):生成预编译命令对象
JDBC快速入门
JDBC编写步骤
1.注册驱动-加载Driver类
2.获取连接-得到Connection
3.执行增删改查-发送SQL给mysql执行
4.释放资源-关闭相关连接
public class JDBC01 {
public static void main(String[] args) throws SQLException {
//1.注册驱动
Driver driver = new Driver();
//2.得到连接
//jdbc:mysql:规定好表示协议,通过jdbc的方式连接mysql
//localhost 主机,也可以时ip地址
//3306 表示mysql监听的端口
//new 表示连接到mysql dbms的哪个数据库
String url = "jdbc:mysql://localhost:3306/new";
//2.1将用户名和密码放入到Properties对象
Properties properties = new Properties();
properties.setProperty("user","root");//用户
properties.setProperty("password","340565");//密码
Connection connect = driver.connect(url, properties);
//3.执行sql
String sql = "insert into student values('10012','志成','18')";
//statement用于执行静态SQL语句并返回其生成的结果对象
Statement statement = connect.createStatement();
//执行修改sql的语句
int rows = statement.executeUpdate(sql);
//判定执行sql语句是否成功
System.out.println(rows>0?"成功":"失败");
//4.关闭连接资源
statement.close();
connect.close();
}
}
获取数据库连接五种方式
//获取Driver类实现对象
Driver driver1 = new com.mysql.cj.jdbc.Driver();
String url1 = "jdbc:mysql://localhost:3306/new";
Properties info = new Properties();
info.setProperty("user","root");
info.setProperty("password","340565");
Connection connection = driver1.connect(url1,info);
System.out.println(connection);
public class JDBC02 {
public static void main(String[] args) throws SQLException, ClassNotFoundException, InstantiationException, IllegalAccessException, IOException {
connect02();
connect03();
connect04();
connect05();
}
public static void connect02() throws ClassNotFoundException, InstantiationException, IllegalAccessException, SQLException {
//使用反射加载Driver,动态加载,更加灵活,减少依赖性
Class<?> aClass = Class.forName("com.mysql.cj.jdbc.Driver");
Driver driver = (Driver) aClass.newInstance();
String url1 = "jdbc:mysql://localhost:3306/new";
Properties info = new Properties();
info.setProperty("user","root");
info.setProperty("password","340565");
Connection connection = driver.connect(url1,info);
System.out.println("第二种"+connection);
}
public static void connect03() throws ClassNotFoundException, InstantiationException, IllegalAccessException, SQLException {
//使用DriverManger替换Driver
Class clazz = Class.forName("com.mysql.cj.jdbc.Driver");
Driver o = (Driver) clazz.newInstance();
String url2 = "jdbc:mysql://localhost:3306/new";
String user = "root";
String password = "340565";
DriverManager.registerDriver(o);
Connection conn = DriverManager.getConnection(url2,user,password);
System.out.println("第三种"+conn);
}
public static void connect04() throws ClassNotFoundException, SQLException {
//使用Class.forName自动完成注册驱动,简化代码=》分析原码
/**注意:1.mysql驱动5.1.6可以无需Class.forName("com.mysql.cj.jdbc.Driver");
* 2.从JDK1.5以后使用jdbc4,不再需要显示调用class.forname()注册驱动而是自动
* 调用驱动jar包下META-INF/services/java。sql。Driver文本中的类名称去注册
* 3.不过建议还是写上
*/
Class.forName("com.mysql.cj.jdbc.Driver");
String url2 = "jdbc:mysql://localhost:3306/new";
String user = "root";
String password = "340565";
Connection conn = DriverManager.getConnection(url2,user,password);
System.out.println("第四种"+conn);
}
/**
* 配置文件信息,保存为mysql.properties
* user=root
* password=340565
* url=jdbc:mysql://localhost:3306/new
* driver=com.mysql.cj.jdbc.Driver*/
public static void connect05() throws SQLException, IOException, ClassNotFoundException {
//使用配置文件,连接数据库更灵活
//通过Properties对象获取配置文件的信息
Properties properties = new Properties();
properties.load(new FileInputStream("src\\mysql.properties"));
//获取相关的值
String user= properties.getProperty("user");
String password = properties.getProperty("password");
String driver = properties.getProperty("driver");
String url= properties.getProperty("url");
Class.forName(driver);
Connection connection = DriverManager.getConnection(url, user, password);
System.out.println("第五种"+connection);
}
}
ResultSet[结果集]
基本介绍
1.表示数据库结果集的数据表,通常通过执行查询数据库的语句生成
2.Result对象保持一个光标指向当前的数据行。最初光标位于第一行之间
3.next方法将光标移动到下一行,并且由于在ResultSet对象中没有更多行时返回false
因此可以在while循环中使用循环来遍历结果集
常用方法
1.next()向下移动一行,同时如果没有下一行,则返回false
2.previous()向上移动一行
3.getXxx(列的索引|列名)返回对应列的值,,接收类型是Xxx
4.getObject(列的索引|列名)返回对应列的值,接收类型是Object
public class ResultSet_ {
public static void main(String[] args) throws IOException, ClassNotFoundException, SQLException {
//使用配置文件,连接数据库更灵活
//通过Properties对象获取配置文件的信息
Properties properties = new Properties();
properties. load(new FileInputStream("src\\mysql.properties"));
//获取相关的值
String user= properties.getProperty("user");
String password = properties.getProperty("password");
String driver = properties.getProperty("driver");
String url= properties.getProperty("url");
//注册驱动
Class.forName(driver);
//得到连接
Connection connection = DriverManager.getConnection(url, user, password);
//得到statement
Statement statement = connection.createStatement();
//组织sql语句
String sql = "select sid,sname,age from student";
//执行给定的SOL语句,该语句返回单个Resulset
ResultSet resultSet = statement.executeQuery(sql);
//使用while取出数据
while(resultSet.next()){
int id = resultSet.getInt(1);
String name = resultSet.getString(2);
int age = resultSet.getInt(3);
System.out.println(id+"\t"+name+"\t"+age);
}
//关闭连接
resultSet.close();
statement.close();
connection.close();
}
}
Statement
基本介绍
1.Statement对象用于执行创建静态SQL语句并返回其生成的结果的对象
2.在连接建立后,需要对数据库进行访问,执行命令或是sql语句,可以通过
Statement[存在SQL注入]、PreparedStatament[预处理]、CallableStatement[存储过程]
3.Statement对象执行SQL语句,存在SQL注入风险
4.SQL注入是利用某些系统没有对用户输入的数据进行充分的检查,而在用户输入数据中注入
非法的SQL语句段或命令,恶意攻击数据库。
5.要防范SQL注入,只要用PreparedStatement(从Statement扩展而来)取代Statement就可以了
常用方法
1.excuteUpdate(sql):执行dml语句,返回影响的行数
2.excuteQuery(sql):执行查询,返回ResultSet对象
3.excute(sql):执行任意的sql,返回布尔值
PreparedStatament[预处理]
基本介绍
1.PreparedStatament执行的SQL语句中的参数用问号(?)来表示,调用PreparedStatament
对象的setXxx()方法来设置这些参数。setXxx()方法有两个参数,第一个是设置SQL语句参数的索引
(从1开始),第二个是设置SQL语句中的参数的值
2.调用excuteQuery(),返回ResultSet对象
3.调用excuteUpdate():执行更新,包括增、删、修改
常用方法
1.excuteUpdate(sql):执行dml语句
2.excuteQuery(sql):执行查询,返回ResultSet
3.excute(sql):执行任意的sql,返回布尔值
4.setXxx(占位符索引,占位符的值),解决SQL注入
5.setObject(占位符索引,占位符的值)
预处理的优点
1.不再使用+拼接sql语句,减少语法错误
2.有效的解决了sql注入问题
3.大大减少了编译次数,效率较高
JDBC Utils
在JDBC操作中,获取连接和释放资源 是经常使用到,可以将其封装JDBC连接的,工具类JDBCUtils
,极大简便步骤使用更加灵活
import java.io.FileInputStream;
import java.io.IOException;
import java.sql.*;
import java.util.Properties;
public class JDBCUtils {
//定义相关属性,因为只需要一份,因此我们做出静态
private static String user;//用户名
private static String password;//密码
private static String url;//地址
private static String driver;//驱动名
static {
try {
Properties properties = new Properties();
properties.load(new FileInputStream("\"src\\\\mysql.properties"));
//读取相关的属性值
user = properties.getProperty("user");
password = properties.getProperty("password");
url = properties.getProperty("url");
driver = properties.getProperty("driver");
} catch (IOException e) {
//从实际开发中,我们可以这样处理
//1.将编译异常转换成运行异常
//2.这是调用者,可以选择捕获异常,也可以选择默认处理异常,比较方便
throw new RuntimeException(e);
}
}
//连接数据库,返回Connection
public static Connection getConnection(){
try{
return DriverManager.getConnection(url,user,password);
}catch (SQLException e){
throw new RuntimeException(e);
}
}
//关闭资源
/**
* 1.ResultSet结果集
* 2.Statement或者PrepareStatement
* 3.Connection
* 4.如果需要关闭资源,就传入对象否则传入null*/
public static void close(ResultSet set, PreparedStatement preparedstatement,Connection connection){
//判断是否为空
try {
if (set != null) {
set.close();
}
if (statement != null) {
statement.close();
}
if (connection != null) {
connection.close();
}
}catch (SQLException e){
throw new RuntimeException(e);
}
}
}
//该类显示如何使用JDBCUtils工具类,完成dml和select
public class JDBCUtils_use {
public static void main(String[] args) {
JDBCUtils_use jdbcUtils_use = new JDBCUtils_use();
jdbcUtils_use.testDML();
}
public void testDML() {//insert update,select
//1.得到连接
Connection connection = null;
//2.组织一个sql
String sql = "update stu set use = ? where pwd = ? ";
//3.创建PreparedStatement对象
PreparedStatement preparedStatement = null;
try {
connection = JDBCUtils.getConnection();
preparedStatement = connection.prepareStatement(sql);
preparedStatement.setInt(1, 10236);
preparedStatement.setString(2, "wang");
preparedStatement.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
//关闭资源
JDBCUtils.close(null, preparedStatement, connection);
}
}
}
批处理
1.当需要成批插入或者更新记录时,可以采用Java的批量更新机制,这一机制允许多条语句一次性提交给数据库
批量处理。通常情况下比单独处理更有效率
2.JDBC的批量处理语句包括下面方法:
addBatch():添加需要批量处理的sql语句或参数
executeBatch():执行批量处理语句
clearBatch():清空批处理包的语句
3.当JDBC连接MySQL时,如果使用批处理功能,请再url中添加参数?rewriteBatchedStatements=true;
4.批处理往往和PreparedStarement一起搭配使用,可以减少编译次数,又减少编译次数,效率大大提高
连接池
基本介绍
1.预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从缓冲池中取出一个,使用完毕之后再放回去。
2.数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是重新建立一个
3.当应用程序向连接池请求的连接数超过最大连接数量时,这些请求将被加入到等待队列中。
数据库连接池种类
1.JDBC的数据库连接池使用javax.sql.DataSource来表示,DataSource只是一个接口,该接口通常由第三方
提供实现
2.C3P0数据库连接池,速度相对较慢,稳定性不错(hibernate)
3.DBCP数据库连接池,速度相对较快,但不稳定
4.Proxool数据库连接池,有监控连接池状态的功能,稳定性c3p0差一点
5.BonCP数据库连接池,速度快
6.Druid(德鲁伊)是阿里提供的数据库连接池,集DBCP,c3p0,Proxool优点于一身的数据库连接池
Apache-DBUtils
基本介绍
1.commons-dbutils是Apache组织提供的一个开源JDBC工具类库,他是对JDBC的封装
使用dbutils能极大简化jdbc编码的工作量。DbUtils类
2.Query Runner类:该类封装了SQL的执行,是线程安全的。可以实现增、删、改、查批处理
3.使用QueryRunner类实现查询
4.ResultSetHandler接口:该接口用于处理java.sql.ResukSet.将数据按要求转换为另一种形式
较慢,稳定性不错(hibernate)
5.DBCP数据库连接池,速度相对较快,但不稳定
6.Proxool数据库连接池,有监控连接池状态的功能,稳定性c3p0差一点
7.BonCP数据库连接池,速度快
8.Druid(德鲁伊)是阿里提供的数据库连接池,集DBCP,c3p0,Proxool优点于一身的数据库连接池