JDBC
JDBC(java DataBase Connectivity)是Java和数据库之间的一个桥梁,是一个规范而不是一个实现,能够执行SQL语句。它由一组用Java语言编写的类和接口组成。各种不同类型的数据库都有相应的实现,我们所要学习的是通过jdbc连接MySQL数据库。
使用流程
1.导入依赖
2.参数配置
3.加载驱动
4.建立连接(登录mysql服务)
5.获取操作数据库的对象
6.通过statement/PreparedStatement操作数据库
a.executeQuery 读
b.executeUpdate 写
7.关闭mysql连接
JDBC实现原理
从connection获取到statement
public class Test {
private final String jdbcDriver = "com.mysql.jdbc.Driver"; //jdbc 驱动
private final String url = "jdbc:mysql://127.0.0.1:3306/school?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai";
private final String userName = "root";
private final String password = "123456";
private Connection connection; //连接对象
private Statement statement; //从connection获取到的statement
//增删改查操作
public Test() {
try {
Class.forName(jdbcDriver);
connection = DriverManager.getConnection(url, userName, password);
if (connection != null && !connection.isClosed()) {
System.out.println("与mysql服务建立连接成功");
statement = connection.createStatement();
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
public void selectTest() {
String sql = "select * from student where sid < 03";
try {
ResultSet resultSet = statement.executeQuery(sql);//
//ResultSet 结果集
while (resultSet.next()) {
System.out.println("SID: " + resultSet.getString(1)
+ " Sname: " + resultSet.getString(2)
+ " Sage: " + resultSet.getString(3) +
" Ssex: " + resultSet.getString(4));
}
} catch (SQLException e) {
e.printStackTrace();
}
}
//注册
public void insertTest(int id, String name, String password) {
//String sql = "insert user values(id,name,password)";
String sql = "insert user values(" + id + ",'" + name + "','"
+ password + "')";
System.out.println("sql: " + sql);
try {
statement.executeUpdate(sql);
} catch (SQLException e) {
e.printStackTrace();
}
}
public void login(String name, String password) {
// select password from user where id = id;
String sql = "select * from user where name = '" + name +
"'and password ='" + password + "'";
System.out.println("拼装好的sql: " + sql);
try {
ResultSet resultSet = statement.executeQuery(sql);
if (resultSet != null && resultSet.next()) {
System.out.println("登录成功");
} else {
System.out.println("登录失败");
}
} catch (SQLException e) {
e.printStackTrace();
}
}
public void close() {
try {
if (connection != null && !connection.isClosed()) {
connection.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Test test = null;
try {
test = new Test();
// test.selectTest();
// test.insertTest(7, "Sam", "123456");
test.login("zhangSan","1236'or ' 1 = 1");
System.out.println("*******************************************");
} finally {
if (test != null) {
test.close();
}
}
}
}
从connection获取到preparedstatement
public class Test1 {
private final String jdbcDriver = "com.mysql.jdbc.Driver"; //jdbc 驱动
private final String url = "jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai";
private final String userName = "root";
private final String password = "123456";
private Connection connection; //连接对象
private PreparedStatement pre;
private PreparedStatement pre1;
public Test1() {
try {
Class.forName(jdbcDriver);
connection = DriverManager.getConnection(url, userName, password);
if (connection != null && !connection.isClosed()) {
System.out.println("与mysql服务建立连接成功");
connection.setAutoCommit(false);
connection.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
public void tranTest() {
String sql = "update ac_a set money = money + ? where id = ?";
String sql1 = "update ac_b set money = money - ? where id = ?";
Savepoint p1 = null;
try {
pre = connection.prepareStatement(sql);
pre1 = connection.prepareStatement(sql1);
pre.setInt(1, 50);
pre.setInt(2, 1);
pre1.setInt(1, 50);
pre1.setInt(2, 1);
pre.executeUpdate();
p1 = connection.setSavepoint("p1");
pre1.executeUpdate();
int i = 4 / 0;
connection.commit();
} catch (Exception e) {
System.out.println("rollback 触发");
try {
// connection.rollback();
if (p1 != null) {
connection.rollback(p1);
}
} catch (SQLException e1) {
e1.printStackTrace();
}
e.printStackTrace();
}
}
public void selectTest() {
String sql = "select * from ac_a";
String sql1 = "select * from ac_b";
try {
pre = connection.prepareStatement(sql);
ResultSet resultSet = pre.executeQuery();
while (resultSet.next()) {
System.out.println("id: " + resultSet.getString(1)
+ "money: " + resultSet.getString(2));
}
System.out.println("******************************************");
pre = connection.prepareStatement(sql1);
ResultSet resultSet1 = pre.executeQuery();
while (resultSet1.next()) {
System.out.println("id: " + resultSet1.getString(1)
+ "money: " + resultSet1.getString(2));
}
} catch (SQLException e) {
e.printStackTrace();
}
}
public PreparedStatement createInserSQL() {
String sql = "insert user values(?,?,?)";
try {
pre = connection.prepareStatement(sql);
} catch (SQLException e) {
e.printStackTrace();
}
return pre;
}
//与statement用法比较
// String sql = "insert user values(" + id + ",'" + name + "','"
// + password + "')";
// System.out.println("sql: " + sql);
// try {
// statement.executeUpdate(sql);
public void insertTest(PreparedStatement pre, int id, String name, String password) {
//占位符 ?
try {
//参数传递mysql
pre.setInt(1, id);
pre.setString(2, name);
pre.setString(3, password);
pre.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
}
public void close() {
try {
if (connection != null && !connection.isClosed()) {
connection.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Test1 test1 = null;
try {
test1 = new Test1();
test1.tranTest();
test1.selectTest();
// PreparedStatement pre = test1.createInserSQL();
// test1.insertTest(pre, 8, "李四", "123456");
// test1.insertTest(pre, 9, "王五", "123456");
// test1.insertTest(pre, 10, "marry", "123456");
} finally {
if (test1 != null) {
test1.close();
}
}
}
}
SQL注入即是指web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息
statement和Preparedstatement使用的区别
1.PreparedStatement 代码结构可读性更高,编码的复杂程度更小
2.执行效率
(1)如果同结构的sql语句只执行一次 statement 效率更高
(2)如果同结构的sql语句执行多次 PreparedStatement 效率更高
3. PreparedStatement能避免sql注入的问题
连接池
为什么要使用连接池
普通的JDBC请求MySQL链接当完成所有SQL请求任务之后,MySQL连接就会关闭。这样一来MySQL的连接就变成了单次使用,每次使用前都需要重新创建,使用之后都需要将链接关闭。如果此时有多个用户使用JDBC的话,就会出现连接频繁的创建和关闭的过程。而链接池的出现就是为了让链接能够重复使用。
连接池的工作原理
数据库连接池的基本思想就是为数据库连接建立一个“缓冲池”。当用户第一次获取连接时,会先请求一定数量(初始链接数量)链接池中,并且会记录每个连接的初始(未使用)时间,然后再将链接池中的连接给有需要的用户。当缓冲池中初始连接用完了,链接池会判断所创建的连接数量是否大于最大链接数如果不大于则可以继续创建连接给请求的用户使用(创建的新连接的个数可自己控制,链接池中有相应的增长参数)。如果已经到到最大链接数则当前用户需要等待直到有用户使用完之后关闭连接,这个用户才可以重复使用。当我们开始使用链接池的时候链接池内部就会进行计时(超时时间),每隔空闲链接的存活时间就会对链接池内部的连接进行一次清理。把所有(当前时间 - 链接最后使用的时间 )> 空闲链接的存活时间的连接释放掉。
连接池使用流程
(1)导入依赖
(2)参数配置
(3)获取链接
(4)创建发送SQL请求的对象,进行相关操作
(5)关闭连接
以C3p0为例,常用配置参数介绍
1.driverClass : 数据库驱动(比如mysql,或者oracle数据库的驱动)
2.jdbcUrl: 数据库连接地址(例如jdbc:mysql://localhost:3306/zhanghanlun)
3.user:数据库用户名
4.password:和数据库用户名对应的数据库密码
基础的参数配置
管理池大小和连接时间的配置
配置连接测试
在这几个参数中,idleConnectionTestPeriod、testConnectionOnCheckout和testConnectuonOnCheckin控制什么时候连接将被校验检测。automaticTestTable、connectionTesterClassName和perferedTestQuery控制连接将怎么样被检测。
配置语句池
配置数据库的中断恢复
配置未解决的事务处理
其他数据源配置
C3p0连接池代码
import com.mchange.v2.c3p0.ComboPooledDataSource;
import java.beans.PropertyVetoException;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
public class MyC3p0 {
//数据源对象
private ComboPooledDataSource dataSource;
private MyC3p0() {
dataSource = new ComboPooledDataSource();
FileInputStream in = null;
try {
Properties pro = new Properties();
in = new FileInputStream("D:\\Java\\上课代码\\jsp_demo" +
"\\mysql_23\\src\\main\\resources\\db.properties");
pro.load(in);
dataSource.setDriverClass(pro.getProperty("jdbcDriver"));
dataSource.setJdbcUrl(pro.getProperty("jdbcUrl"));
dataSource.setUser(pro.getProperty("userName"));
dataSource.setPassword(pro.getProperty("password"));
dataSource.setMaxIdleTime(Integer.parseInt(pro.getProperty("maxIdleTime")));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (PropertyVetoException e) {
e.printStackTrace();
}
}
private static class Holder {
private static MyC3p0 c3p0 = new MyC3p0();
}
public static MyC3p0 getMyC3p0() {
return MyC3p0.Holder.c3p0;
}
public Connection getConnection() throws SQLException {
return dataSource.getConnection();
}
}
模拟用户使用Mysql连接
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
//模拟用户使用Mysql连接
public class C3p0App {
public static void main(String[] args) {
MyC3p0 c3p0 = MyC3p0.getMyC3p0();
PreparedStatement pre = null;
Connection connection = null;
try {
connection = c3p0.getConnection();
String sql = "select * from student where SID > ?";
pre = connection.prepareStatement(sql);
pre.setString(1, "01");
ResultSet resultSet = pre.executeQuery();
while (resultSet.next()) {
//hashnext next -1
System.out.println("SID:" + resultSet.getString(1) +
" SName:" + resultSet.getString(2)
+ " SAge:" + resultSet.getString(3)
+ " SSex:" + resultSet.getString(4));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
pre.close();
connection.close(); //将连接归还给链接池
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
DBCP连接池代码
package dbcp;
import org.apache.commons.dbcp.BasicDataSource;
import org.apache.commons.dbcp.BasicDataSourceFactory;
import javax.sql.DataSource;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
public final class MyDBCP {
private DataSource dataSource;
private MyDBCP() {
Properties pro = new Properties();
FileInputStream is = null;//方式 二
dataSource = new BasicDataSource();
try {
is = new FileInputStream(
"D:\\Java\\上课代码\\jsp_demo\\src\\main\\resources\\dbcp.properties");
pro.load(is); // 创建了一个DBCP数据库连接池
dataSource = BasicDataSourceFactory.createDataSource(pro);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
private static class Holder {
private static MyDBCP dbcp = new MyDBCP();
}
public static MyDBCP getDbcp() {
return Holder.dbcp;
}
public Connection getConnection() throws Exception {
Connection conn = dataSource.getConnection();
return conn;
}
// 方式一:
// public Connection testGetConnection() throws SQLException {
// // 创建DBCP数据库连接池
// BasicDataSource source = new BasicDataSource();
// // 设置基本信息
// source.setDriverClassName("com.mysql.jdbc.Driver");
// source.setUrl("jdbc:mysql://localhost:3306/school");
// source.setUsername("root");
// source.setPassword("123456");
// // 其他设置数据库连接池管理的相关属性
// source.setInitialSize(10);
// source.setMaxActive(20);
// Connection conn = source.getConnection();
// System.out.println(conn);
// return conn;
// }
// 方式二:推荐 使用配置文件
}
package dbcp;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class DbcpApp {
public static void main(String[] args) {
MyDBCP dbcp = MyDBCP.getDbcp();
PreparedStatement pre = null;
Connection connection = null;
try {
connection = dbcp.getConnection();
String sql = "select * from student where SID > ?";
pre = connection.prepareStatement(sql);
pre.setString(1, "01");
ResultSet resultSet = pre.executeQuery();
while (resultSet.next()) {
//hashnext next -1
System.out.println("SID:" + resultSet.getString(1) +
" SName:" + resultSet.getString(2)
+ " SAge:" + resultSet.getString(3)
+ " SSex:" + resultSet.getString(4));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
pre.close();
connection.close(); //将连接归还给链接池
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
Druid连接池代码
package druid;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.Connection;
import java.util.Properties;
public class MyDruid {
private DataSource dataSource;
private MyDruid() {
Properties pro = new Properties();
dataSource = new DruidDataSource();
FileInputStream is = null;//方式 二
try {
is = new FileInputStream(
"D:\\Java\\上课代码\\jsp_demo\\src\\main\\resources\\druid.properties");
pro.load(is);
dataSource = DruidDataSourceFactory.createDataSource(pro);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
private static class Holder {
private static MyDruid druid = new MyDruid();
}
public static MyDruid getdruid() {
return Holder.druid;
}
// // 方式一:
// public Connection testGetConnection() throws Exception {
// // 创建DBCP数据库连接池
// DruidDataSource dataSource = new DruidDataSource();
// dataSource.setDriverClassName("com.mysql.jdbc.Driver");
// dataSource.setUrl("jdbc:mysql://localhost:3306/school");
// dataSource.setUsername("root");
// dataSource.setPassword("123456");
// Connection conn = dataSource.getConnection();
// System.out.println(conn);
// return conn;
// }
// 方式二:推荐 使用配置文件
public Connection getConnection() throws Exception {
Connection conn = dataSource.getConnection();
System.out.println(conn);
return conn;
}
}
package druid;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class DruidApp {
public static void main(String[] args) {
MyDruid druid = MyDruid.getdruid();
PreparedStatement pre = null;
Connection connection = null;
try {
connection = druid.getConnection();
String sql = "select * from student where SID > ?";
pre = connection.prepareStatement(sql);
pre.setString(1, "01");
ResultSet resultSet = pre.executeQuery();
while (resultSet.next()) {
//hashnext next -1
System.out.println("SID:" + resultSet.getString(1) +
" SName:" + resultSet.getString(2)
+ " SAge:" + resultSet.getString(3)
+ " SSex:" + resultSet.getString(4));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
pre.close();
connection.close(); //将连接归还给链接池
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}