JDBC:Java Database Connectivity Java数据库连接
使用JDBC规范来实现对数据库的操作
JDBC测试:建立新的工程,然后再导入数据库连接包 mysql-connector-java-5.1.7-bin.jar
顺序依次是:
1、加载驱动
2、获得连接
3、创建执行SQL语句的对象并执行SQL语句
4、释放资源
package com.imooc.jdbc.demo1;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import org.junit.Test;
import com.mysql.jdbc.Driver;
public class JDBCDemo1 {
@Test
/**
* JDBC的入门程序
*/
public void demo1() {
Connection conn = null;
Statement stmt = null;
ResultSet resultSet = null;
try {
// 1、加载驱动
// DriverManager.registerDriver(new Driver());//本方式会导致驱动注册两次
// 常使用这个注册方法
Class.forName("java.sql.DriverManager");
// 2、获得连接
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbctest", "root", "mima19971009");
// 3、创建执行SQL语句的对象,并且执行SQL语句
// 3.1 创建执行sql语句的对象
String sql = "select * from user";
stmt = conn.createStatement();
// 3.2 执行sql
resultSet = stmt.executeQuery(sql);
while (resultSet.next()) {
int uid = resultSet.getInt("uid");
String username = resultSet.getString("username");
String password = resultSet.getString("password");
String name = resultSet.getString("name");
System.out.println(uid + " " + username + " " + password + " " + name + " ");
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
// 4、释放资源
// 4.1 释放结果集
if (resultSet != null) {
try {
//先释放
resultSet.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//设置为null,使得尽快被垃圾处理器进行处理
resultSet = null;
}
// 4.2 释放执行sql语句对象
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
stmt = null;
}
// 4.3 释放连接对象
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
conn=null;
}
}
}
}
JDBC的API--DriverManager:驱动管理类
主要作用:
1、注册驱动
//1、加载驱动
//DriverManager.registerDriver(new Driver());//本方式会导致驱动注册两次
//常使用这个注册方法
Class.forName("java.sql.DriverManager");
2、获得连接
Connection conn = DriverManager.getConnection(url,用户名,用户密码);
url:jdbc:mysql://localhost:3306/数据库名
jdbc:协议
mysql:子协议
localhost:主机名
3306:端口号
JDBC的API--Connection:连接对象
主要作用:
1、创建执行SQL语句的对象
Statement stmt = conn.createStatement();//执行SQL语句,有SQL注入漏洞存在
PreparedStament prepareStament(String sql); //预编译SQL语句,解决SQL注入漏洞
CallableStatement prepareCall(String sql);//执行SQL语句存储过程
2、进行事务的管理
setAutoCommit(boolean autoCommit);//设置事务自动提交
commit();//事务提交
rollback();//事务回滚
JDBC的API--Statement:执行对象
主要作用:
1、执行SQL语句
boolean execute(String sql);//执行SQL语句,执行select返回true,否则返回false
ResultSet executeQuery(String sql);//执行SQL中的select语句
Int executeUpdate(String sql);//执行SQL中的insert/update/delete语句,返回影响的行数
2、执行批处理操作
addBatch(String sql);//添加到批处理
executrBatch(String sql);//执行批处理
clearBatch(String sql);/清空批处理
JDBC的API--ResultSet:结果集
是select结果的封装
主要作用:
next();//判断是否有下一个记录
getObject();//在不清楚数据类型的时候可以使用
getXXX();//针对不同的数据类型来获取数据
JDBC资源的释放:
测试:
// 4.1 释放结果集
if (resultSet != null) {
try {
//先释放
resultSet.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//设置为null,使得尽快被垃圾处理器进行处理
resultSet = null;
}
JDBC的CRUD操作:
保存代码的操作:
@Test
/**
* 保存操作
*/
public void demo1(){
Connection conn = null;
Statement stmt = null;
try{
// 注册驱动:
Class.forName("com.mysql.jdbc.Driver");
// 获得连接:
conn = DriverManager.getConnection("jdbc:mysql:///jdbctest", "root", "abc");
// 获得执行SQL语句的对象:
stmt = conn.createStatement();
// 编写SQL:
String sql = "insert into user values (null,'eee','123','张三')";
// 执行SQL:
int i = stmt.executeUpdate(sql);
if(i > 0){
System.out.println("保存成功!");
}
}catch(Exception e){
e.printStackTrace();
}finally{
// 释放资源:
if(stmt != null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
stmt = null;
}
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
conn = null;
}
}
}
修改代码的实现:
@Test
/**
* 修改操作
*/
public void demo2(){
Connection conn = null;
Statement stmt = null;
try{
// 注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 获得连接
conn = DriverManager.getConnection("jdbc:mysql:///jdbctest", "root", "abc");
// 创建执行SQL语句的对象:
stmt = conn.createStatement();
// 编写SQL:
String sql = "update user set username = 'qqq',password='456' , name='赵六' where uid = 4";
// 执行SQL:
int i = stmt.executeUpdate(sql);
if(i>0){
System.out.println("修改成功!");
}
}catch(Exception e){
e.printStackTrace();
}finally{
// 释放资源
if(stmt != null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
stmt = null;
}
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
conn = null;
}
}
}
删除代码的实现:
@Test
/**
* 删除操作
*/
public void demo3(){
Connection conn = null;
Statement stmt = null;
try{
// 注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 获得连接
conn = DriverManager.getConnection("jdbc:mysql:///jdbctest", "root", "abc");
// 获得执行SQL语句的对象:
stmt = conn.createStatement();
// 编写SQL:
String sql = "delete from user where uid = 4";
// 执行SQL:
int i = stmt.executeUpdate(sql);
if(i > 0){
System.out.println("删除成功!");
}
}catch(Exception e){
e.printStackTrace();
}finally{
// 释放资源
if(stmt != null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
stmt = null;
}
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
conn = null;
}
}
}
查询代码的实现:
@Test
/**
* 查询所有记录
*/
public void demo4(){
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try{
// 注册驱动:
Class.forName("com.mysql.jdbc.Driver");
// 获得连接:
conn = DriverManager.getConnection("jdbc:mysql:///jdbctest", "root", "abc");
// 创建执行SQL语句的对象:
stmt = conn.createStatement();
// 编写SQL:
String sql = "select * from user";
// 执行SQL:
rs = stmt.executeQuery(sql);
// 遍历结果集:
while(rs.next()){
System.out.println(rs.getInt("uid")+" "+rs.getString("username")+" "+rs.getString("password")+" "+rs.getString("name"));
}
}catch(Exception e){
e.printStackTrace();
}finally{
// 释放资源
if(rs != null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
rs = null;
}
if(stmt != null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
stmt = null;
}
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
conn = null;
}
}
}
JDBC工具类的抽取:为了简化JDBC的开发,可以将一些重复的代码进行提取
package com.imooc.jdbc.utils;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
/**
* JDBC的工具类
* @author lcs
*
*/
public class JDBCUtils {
private static final String driverClass;
private static final String url;
private static final String username;
private static final String password;
static{
// 加载属性文件并解析:
Properties props = new Properties();
// 如何获得属性文件的输入流?
// 通常情况下使用类的加载器的方式进行获取:
InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("jdbc.properties");
try {
props.load(is);
} catch (IOException e) {
e.printStackTrace();
}
driverClass = props.getProperty("driverClass");
url = props.getProperty("url");
username = props.getProperty("username");
password = props.getProperty("password");
}
/**
* 注册驱动的方法
* @throws ClassNotFoundException
*/
public static void loadDriver() throws ClassNotFoundException{
Class.forName(driverClass);
}
/**
* 获得连接的方法:
* @throws SQLException
*/
public static Connection getConnection() throws Exception{
loadDriver();
Connection conn = DriverManager.getConnection(url, username, password);
return conn;
}
/**
* 资源释放
*/
public static void release(Statement stmt,Connection conn){
if(stmt != null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
stmt = null;
}
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
conn = null;
}
}
public static void release(ResultSet rs,Statement stmt,Connection conn){
if(rs!= null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
rs = null;
}
if(stmt != null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
stmt = null;
}
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
conn = null;
}
}
}
使用工具类进行测试:
package com.imooc.jdbc.demo1;
import java.sql.Connection;
import java.sql.Statement;
import org.junit.Test;
import com.imooc.jdbc.utils.JDBCUtils;
public class JDBCDemo3 {
@Test
// 保存记录
public void demo1(){
Connection conn = null;
Statement stmt = null;
try{
// 获得连接:
conn = JDBCUtils.getConnection();
// 创建执行SQL语句的对象
stmt = conn.createStatement();
// 编写SQL:
String sql = "insert into user values (null,'ggg','123','小六')";
// 执行SQL:
int num = stmt.executeUpdate(sql);
if(num > 0){
System.out.println("保存成功!");
}
}catch(Exception e){
e.printStackTrace();
}finally{
// 释放资源:
JDBCUtils.release(stmt, conn);
}
}
}
使用配置文件来对属性进行配置:
jdbc.properties:
driverClass=com.mysql.jdbc.Driver
url=jdbc:mysql:///jdbctest
username=root
password=abc
加载属性文件:
package com.imooc.jdbc.utils;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
/**
* JDBC的工具类
* @author lcs
*
*/
public class JDBCUtils {
private static final String driverClass;
private static final String url;
private static final String username;
private static final String password;
static{
// 加载属性文件并解析:
Properties props = new Properties();
// 如何获得属性文件的输入流?
// 通常情况下使用类的加载器的方式进行获取:
InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("jdbc.properties");
try {
props.load(is);
} catch (IOException e) {
e.printStackTrace();
}
driverClass = props.getProperty("driverClass");
url = props.getProperty("url");
username = props.getProperty("username");
password = props.getProperty("password");
}
/**
* 注册驱动的方法
* @throws ClassNotFoundException
*/
public static void loadDriver() throws ClassNotFoundException{
Class.forName(driverClass);
}
/**
* 获得连接的方法:
* @throws SQLException
*/
public static Connection getConnection() throws Exception{
loadDriver();
Connection conn = DriverManager.getConnection(url, username, password);
return conn;
}
/**
* 资源释放
*/
public static void release(Statement stmt,Connection conn){
if(stmt != null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
stmt = null;
}
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
conn = null;
}
}
public static void release(ResultSet rs,Statement stmt,Connection conn){
if(rs!= null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
rs = null;
}
if(stmt != null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
stmt = null;
}
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
conn = null;
}
}
}
JDBC的SQL注入漏洞:通过使用关键字,使得判断为真,类似与 用户名正确 or 密码错误,返回的仍然是true,所以要尽量避免使用动态拼接的SQL语句
package com.imooc.jdbc.demo2;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import org.junit.Test;
import com.imooc.jdbc.utils.JDBCUtils;
/**
* 演示JDBC的注入的漏洞
* @author lcs
*
*/
public class JDBCDemo4 {
@Test
/**
* 测试SQL注入漏洞的方法
*/
public void demo1(){
boolean flag = JDBCDemo4.login("aaa' or '1=1", "1fsdsdfsdf");
if(flag == true){
System.out.println("登录成功!");
}else{
System.out.println("登录失败!");
}
}
/**
* 产生SQL注入漏洞的方法
* @param username
* @param password
* @return
*/
public static boolean login(String username,String password){
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
boolean flag = false;
try{
conn = JDBCUtils.getConnection();
// 创建执行SQL语句的对象:
stmt = conn.createStatement();
// 编写SQL:
String sql = "select * from user where username = '"+username+"' and password = '"+password+"'";
// 执行SQL:
rs = stmt.executeQuery(sql);
// 判断结果集中是否有数据。
if(rs.next()){
flag = true;
}else{
flag = false;
}
}catch(Exception e){
e.printStackTrace();
}finally{
JDBCUtils.release(rs, stmt, conn);
}
return flag;
}
}
SQL注入漏洞的解决:使用prepareStatement,使得关键字变为普通字符串
package com.imooc.jdbc.demo2;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import org.junit.Test;
import com.imooc.jdbc.utils.JDBCUtils;
/**
* 演示JDBC的注入的漏洞
* @author lcs
*
*/
public class JDBCDemo4 {
@Test
/**
* 测试SQL注入漏洞的方法
*/
public void demo1(){
boolean flag = JDBCDemo4.login2("aaa' or '1=1", "1fsdsdfsdf");
if(flag == true){
System.out.println("登录成功!");
}else{
System.out.println("登录失败!");
}
}
/**
* 避免SQL注入漏洞的方法
*/
public static boolean login2(String username,String password){
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
boolean flag = false;
try{
// 获得连接:
conn = JDBCUtils.getConnection();
// 编写SQL:使用 ? 进行占位
String sql = "select * from user where username = ? and password = ?";
// 预处理SQL:
pstmt = conn.prepareStatement(sql);
// 设置参数:
pstmt.setString(1, username);
pstmt.setString(2, password);
// 执行SQL:
rs = pstmt.executeQuery();
// 判断结果街
if(rs.next()){
flag = true;
}else{
flag = false;
}
}catch(Exception e){
e.printStackTrace();
}finally{
JDBCUtils.release(rs, pstmt, conn);
}
return flag;
}
}
PreparedStatement的使用:保存操作
package com.imooc.jdbc.demo2;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import org.junit.Test;
import com.imooc.jdbc.utils.JDBCUtils;
/**
* PreparedStatement的使用
* @author lcs
*
*/
@Test
/**
* 保存数据
*/
public void demo1(){
Connection conn = null;
PreparedStatement pstmt = null;
try{
// 获得连接:
conn = JDBCUtils.getConnection();
// 编写SQL:
String sql = "insert into user values (null,?,?,?)";
// 预处理SQL:
pstmt = conn.prepareStatement(sql);
// 设置参数的值:
pstmt.setString(1, "qqq");
pstmt.setString(2, "123");
pstmt.setString(3, "张武");
// 执行SQL:
int num = pstmt.executeUpdate();
if(num > 0){
System.out.println("保存成功!");
}
}catch(Exception e){
e.printStackTrace();
}finally{
// 释放资源
JDBCUtils.release(pstmt, conn);
}
}
}
PreparedStatement的使用:修改操作
setXXX()第一个参数表示是第几个问号,第二个参数表示赋值的值
package com.imooc.jdbc.demo2;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import org.junit.Test;
import com.imooc.jdbc.utils.JDBCUtils;
/**
* PreparedStatement的使用
* @author lcs
*
*/
public class JDBCDemo5 {
@Test
/**
* 修改数据
*/
public void demo2(){
Connection conn = null;
PreparedStatement pstmt = null;
try{
// 获得连接:
conn = JDBCUtils.getConnection();
// 编写SQL:
String sql = "update user set username = ?,password = ?,name = ? where uid = ?";
// 预编译SQL:
pstmt = conn.prepareStatement(sql);
// 设置参数:
pstmt.setString(1, "www");
pstmt.setString(2, "123456");
pstmt.setString(3, "张六");
pstmt.setInt(4, 6);
// 执行SQL:
int num = pstmt.executeUpdate();
if(num > 0){
System.out.println("修改成功!");
}
}catch(Exception e){
e.printStackTrace();
}finally{
JDBCUtils.release(pstmt, conn);
}
}
}
PreparedStatement的使用:删除操作
package com.imooc.jdbc.demo2;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import org.junit.Test;
import com.imooc.jdbc.utils.JDBCUtils;
/**
* PreparedStatement的使用
* @author lcs
*
*/
public class JDBCDemo5 {
@Test
/**
* 删除数据
*/
public void demo3(){
Connection conn = null;
PreparedStatement pstmt = null;
try{
// 获得连接:
conn = JDBCUtils.getConnection();
// 编写SQL:
String sql = "delete from user where uid = ?";
// 预编译SQL:
pstmt = conn.prepareStatement(sql);
// 设置参数:
pstmt.setInt(1, 6);
// 执行SQL:
int num = pstmt.executeUpdate();
if(num > 0){
System.out.println("删除成功!");
}
}catch(Exception e){
e.printStackTrace();
}finally{
JDBCUtils.release(pstmt, conn);
}
}
}
PreparedStatement的使用:查询操作
package com.imooc.jdbc.demo2;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import org.junit.Test;
import com.imooc.jdbc.utils.JDBCUtils;
/**
* PreparedStatement的使用
* @author lcs
*
*/
public class JDBCDemo5 {
@Test
/**
* 查询一条记录
*/
public void demo5(){
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try{
// 获得连接:
conn = JDBCUtils.getConnection();
// 编写SQL:
String sql = "select * from user where uid = ?";
// 预编译SQL:
pstmt = conn.prepareStatement(sql);
// 设置参数:
pstmt.setObject(1, 3);
// 执行SQL:
rs = pstmt.executeQuery();
// 判断结果集:
if(rs.next()){
System.out.println(rs.getInt("uid")+" "+rs.getString("username")+" "+rs.getString("password")+" "+rs.getString("name"));
}
}catch(Exception e){
e.printStackTrace();
}finally{
JDBCUtils.release(rs, pstmt, conn);
}
}
@Test
/**
* 查询所有数据
*/
public void demo4(){
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try{
// 获得连接:
conn = JDBCUtils.getConnection();
// 编写SQL:
String sql = "select * from user";
// 预编译SQL:
pstmt = conn.prepareStatement(sql);
// 设置参数
// 执行SQL:
rs = pstmt.executeQuery();
while(rs.next()){
System.out.println(rs.getInt("uid")+" "+rs.getString("username")+" "+rs.getString("password")+" "+rs.getString("name"));
}
}catch(Exception e){
e.printStackTrace();
}finally{
JDBCUtils.release(rs, pstmt, conn);
}
}
}
数据库连接池:创建和管理一个连接的缓冲池的技术,这些连接准备好被任何需要的进程所使用。数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个;释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗漏。这项技术能明显提高对数据库操作的性能。
不使用连接池的技术:
使用连接池:
C3P0连接池:
首先引用C3P0的jar包: c3p0-0.9.1.2.jar
package com.imooc.jdbc.demo3;
import java.sql.ResultSet;
import org.junit.Test;
import com.imooc.jdbc.utils.JDBCUtils;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import com.mysql.jdbc.PreparedStatement;
/**
*连接池的测试类'
*@author lcs
*
*/
public class DataSourceDemo2() {
@Test
/**
* 使用xml配置文件设置连接池
*/
public void demo2(){
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
//获得连接
conn = JDBCUtils2.getConnection();
//编写SQL
String sql = "select * from user";
//预编译sql:
pstmt = conn.prepareStatement(sql);
//设置参数
//执行sql
rs = pstmt.executeQuery();
while(rs.next()) {
System.out.println(rs.getInt("uid"));
}
}catch(Exception e){
e.printStackTrace();
}
finally {
//释放资源
JDBCUtils.release(rs, pstmt, conn);
}
}
}
public class DataSourceDemo1() {
@Test
/**
* 手动设置连接池
*/
public void demo1(){
//创建连接池
ComboPooledDataSource dataSource = new ComboPooledDataSource();
//设置连接池的参数
dataSource.setDriverClass("com.mysql.jdbc.Driver");
dataSource.setJdbcUrl("jdbc:mysql///jdbctest");
dataSource.setUser("root");
dataSource.setPassword("thisismima");
//获得连接
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
//获得连接
conn = dataSource.getConnection();
//编写SQL
String sql = "select * from user";
//预编译sql:
pstmt = conn.prepareStatement(sql);
//设置参数
//执行sql
rs = pstmt.executeQuery();
while(rs.next()) {
System.out.println(rs.getInt("uid"));
}
}catch(Exception e){
e.printStackTrace();
}
finally {
//释放资源
JDBCUtils.release(rs, pstmt, conn);
}
}
}
xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
<default-config>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql:///jdbctest</property>
<property name="user">root</property>
<property name="password">abc</property>
<property name="initialPoolSize">5</property>
<property name="maxPoolSize">20</property>
</default-config>
</c3p0-config>