JDBC
- 概念:java databases connectivity (java数据库连接) ——java语言操作数据库
- JDBC本质: 官方定义的一套操作所有数据库的规则(接口),各个数据库厂商去实现这套接口,提供数据库驱动jar包,我们可以使用这套接口(JDBC)编程,真正执行的代码是驱动jar包中的实现类。
- 入门步骤
- 导入驱动jar包
- 复制mysql-connector-java-5.1.37-bin.jar到项目的libs目录下
- 右键Add As Library
- 注册驱动
- 获取数据库连接对象 Connection
- 定义sql
- 获取执行sql语句的对象 Statement
- 执行sql,接受返回结果
- 处理结果
- 释放结果
- 导入驱动jar包
//jdbc连接数据库修改内容
public class jdbcDemo01 {
public static void main(String[] args) throws Exception {
//1.导入驱动jar包
//2.注册驱动
Class.forName("com.mysql.jdbc.Driver");
//3.获取数据库连接对象
// Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db1","root", "root");
Connection conn = DriverManager.getConnection("jdbc:mysql:///db1","root", "root");
//4.定义sql语句
String sql = "update account set age = 00 where id = 12";
//5.获取执行sql的对象 Statement
Statement stmt = conn.createStatement();
//6.执行sql
int count = stmt.executeUpdate(sql);
//7.处理结果
System.out.println(count);
//8.释放资源
stmt.close();
conn.close();
}
}
- JDBC详解各个对象
- DriverManager:驱动管理对象 [
功能:注册驱动;获取数据库连接
]
* 注册驱动写代码:class.forName("com.mysql.jdbc.Driver");
* 获取数据库连接:DriverManager.getConnection("URL",mysql账户,密码)
* URL格式:协议名:子协议://服务器名或IP地址:端口号:/数据库
例:"jdbc:mysql://localhost:3306/db1"
默认本地主机localhost和端口号3306可以省略不写 - Connection:数据库连接对象(当前数据库和代码的桥梁)
- 获取执行sql的对象:
* Statament createStatement()
*PreparedStatement prepareStatement(String sql)
主要用此函数执行sql
- 管理事务:
* 开启事务 :setAutoCommit(boolean autoCommit) : 调用该方法设置参数为false,即开启事务
* 提交事务 :commit()
* 回滚事务 :rollback()
- 获取执行sql的对象:
- Statement:执行sql的对象
[其执行的只能是静态SQL语句,返回其生成的结果对象]
int executeUpdate(String sql)
:用于发送DML语句,增删改的操作,insert、update、delete;参数:SQL语句
;返回值:返回对数据库影响的行数
ResultSet executeQuery(String sql)
:用于发送DQL语句,执行查询的操作。select;参数:SQL语句
;返回值:查询的结果集
- ResultSet:结果集对象(封装查询结果)
boolean next():
游标向下移动1行;返回boolean类型,如果还有下一条记录,返回true,否则返回false
数据类型 getXxx():
通过字段名,参数是String类型。返回不同的类型;通过列号,参数是整数,从1开始。返回不同的类型 - PreparedStatement:执行sql的对象,是statement的子接口 [与statement不同的是其执行的是预编译之后的SQL语句]
SQL注入 问题:在拼接sql语句时,有一些sql的特殊关键字参与字符串的拼接。会造成安全性问题
预编译的sql:参数使用?作为占位符
步骤:
1) 编写 SQL 语句,未知内容使用?占位:“SELECT * FROM user WHERE name=? AND password=?”;
2) 获得 PreparedStatement 对象
3) 设置实际参数:setXxx(占位符的位置, 真实的值)
4) 执行参数化 SQL 语句
5) 关闭资源
//jdbc添加语句
public class jdbcDemo02 {
public static void main(String[] args) {
Connection conn = null;
Statement stmt = null;
try {
//注册驱动
Class.forName("com.mysql.jdbc.Driver");
//定义sql语句
String sql = "insert into account values(11,'ben',22)";
//获取Connection对象
conn = DriverManager.getConnection("jdbc:mysql:///db1","root","root");
//获取执行sql的对象Statement
stmt = conn.createStatement();
//执行sql
int count = stmt.executeUpdate(sql);
//处理结果
System.out.println(count);
if (count > 0){
System.out.println("添加成功");
}else {
System.out.println("添加失败");
}
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
} finally {
// stmt.close();
// conn.close();
//避免空指针(stmt=null)异常
if (stmt != null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null){
try {
conn.close();
} catch (SQLException e){
e.printStackTrace();
}
}
}
}
}
//jdbc查看数据元素
//ResultSet executeQuery() getXxx() next()
public class jdbcDemo04 {
public static void main(String[] args) {
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql:///db1","root","root");
String sql = "select * from account";
stmt = conn.createStatement();
rs = stmt.executeQuery(sql);
while (rs.next()){
System.out.println(rs.getInt(1) + "---" + rs.getString("name") + "----" + rs.getInt(3));
}
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
} finally {
if (rs != null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (stmt != null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
//打印结果
12---lulu----22
13---zhang----33
11---ben----22
//数据库表创建为一个类
public class emp {
private int id;
private String name;
private int age;
private String dep_name;
private String dep_location;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getDep_name() {
return dep_name;
}
public void setDep_name(String dep_name) {
this.dep_name = dep_name;
}
public String getDep_location() {
return dep_location;
}
public void setDep_location(String dep_location) {
this.dep_location = dep_location;
}
@Override
public String toString() {
return "emp{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", dep_name='" + dep_name + '\'' +
", dep_location='" + dep_location + '\'' +
'}';
}
}
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
//jdbc练习
public class jbdc_test {
public static void main(String[] args) {
List li = new jbdc_test().findAll();
System.out.println(li);
System.out.println(li.size());
}
public List<emp> findAll() {
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
List<emp> list = null;
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql:///db1", "root", "root");
String sql = "select * from emp";
stmt = conn.createStatement();
rs = stmt.executeQuery(sql);
emp emp = null;
list = new ArrayList<emp>();
while (rs.next()) {
int id = rs.getInt("id");
String name = rs.getString("name");
int age = rs.getInt("age");
String dep_name = rs.getString("dep_name");
String dep_location = rs.getString("dep_location");
//生成对象 并赋值
emp = new emp();
emp.setId(id);
emp.setName(name);
emp.setAge(age);
emp.setDep_name(dep_name);
emp.setDep_location(dep_location);
list.add(emp);
}
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
} finally {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
return list;
}
}
JDBC工具类
- 将jdbc练习中繁琐的代码块抽象出来
//jdbc工具类
import java.io.FileReader;
import java.io.IOException;
import java.net.URL;
import java.sql.*;
import java.util.Properties;
public class jdbcUtils {
private static String url;
private static String user;
private static String password;
private static String driver;
/**
* 文件的读取,只需要读取一次即可拿到这些值,使用静态代码块
*/
static {
try {
//1、创建properties集合类
Properties pro = new Properties();
//2、加载文件
//pro.load(new FileReader("src/jdbc.properties"));
//获取src路径下的文件的方式-->ClassLoader 类加载器
ClassLoader classLoader = jdbcUtils.class.getClassLoader();
URL res = classLoader.getResource("jdbc.properties");
String path = res.getPath();
System.out.println("配置文件路径:" + path);
pro.load(new FileReader(path));
//3、获取数据 赋值
url = pro.getProperty("url");
user = pro.getProperty("user");
password = pro.getProperty("password");
driver = pro.getProperty("driver");
//4、注册驱动
Class.forName(driver);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e){
e.printStackTrace();
}
}
/**
* 获取连接对象
*
* @return 连接对象
*/
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(url,user,password);
}
/**
* 释放资源
* @param stmt
* @param conn
*/
public static void close(Statement stmt, Connection conn) {
if (stmt!=null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
/**
* 释放资源
* @param stmt
* @param conn
* @param rs
*/
public static void close(Statement stmt, Connection conn, ResultSet rs) {
if (stmt!=null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (rs != null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
import JDBC_test.JDBCutil.jdbcUtils;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
//演示使用jdbc的工具类
public class jdbc_test1 {
public static void main(String[] args) {
List li = new jdbc_test1().findAll2();
System.out.println(li);
System.out.println(li.size());
}
public List<emp> findAll2() {
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
List<emp> list = null;
try {
conn = jdbcUtils.getConnection();
String sql = "select * from emp";
stmt = conn.createStatement();
rs = stmt.executeQuery(sql);
emp emp = null;
list = new ArrayList<emp>();
while (rs.next()) {
int id = rs.getInt("id");
String name = rs.getString("name");
int age = rs.getInt("age");
String dep_name = rs.getString("dep_name");
String dep_location = rs.getString("dep_location");
//生成对象 并赋值
emp = new emp();
emp.setId(id);
emp.setName(name);
emp.setAge(age);
emp.setDep_name(dep_name);
emp.setDep_location(dep_location);
list.add(emp);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
jdbcUtils.close(stmt, conn, rs);
}
return list;
}
}
练习:
- 需求:
- 通过键盘录入用户名和密码
- 判断用户是否登录成功
使用的Statement执行sql语句 :存在一定的安全隐患
import JDBC_test.JDBCutil.jdbcUtils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Scanner;
public class jdbc_test2 {
public static void main(String[] args) {
//1、键盘录入接受用户名和密码
Scanner sc = new Scanner(System.in);
System.out.print("请输入用户名:");
String username = sc.nextLine();
System.out.print("请输入密码:");
String password = sc.nextLine();
//调用方法
jdbc_test2 jt = new jdbc_test2();
boolean result = jt.login(username,password);
if (result){
System.out.println("登陆成功");
}else
System.out.println("登录失败");
}
/**
* 登录方法(使用Statement执行sql对象)
*/
public boolean login(String username, String password){
if (username == null || password == null){
return false;
}
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
//连接数据库判断是否成功
try {
conn = jdbcUtils.getConnection();
String sql = "select * from user where username = '"+ username +"' and password = '"+ password +"'";
stmt = conn.createStatement();
rs = stmt.executeQuery(sql);
return rs.next();
} catch (SQLException e) {
e.printStackTrace();
}finally {
jdbcUtils.close(stmt,conn,rs);
}
return false;
}
}
使用PreparedStatement执行sql语句 :使用?作为占位符
import JDBC_test.JDBCutil.jdbcUtils;
import java.sql.*;
import java.util.Scanner;
public class jdbc_preparedStatement {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("请输入用户名:");
String username = sc.nextLine();
System.out.print("请输入密码:");
String password = sc.nextLine();
jdbc_preparedStatement jt = new jdbc_preparedStatement();
boolean result = jt.login2(username,password);
if (result){
System.out.println("登陆成功");
}else
System.out.println("登录失败");
}
/**
* 登录方法(使用preparedStatement执行sql对象)
*/
public boolean login2(String username, String password){
if (username == null || password == null){
return false;
}
Connection conn = null;
// Statement stmt = null;
ResultSet rs = null;
PreparedStatement pstmt = null;
//连接数据库判断是否成功
try {
conn = jdbcUtils.getConnection();
String sql = "select * from user where username = ? and password = ?";
pstmt = conn.prepareStatement(sql);
//给?赋值
pstmt.setString(1,username);
pstmt.setString(2,password);
rs = pstmt.executeQuery();
return rs.next();
} catch (SQLException e) {
e.printStackTrace();
}finally {
jdbcUtils.close(pstmt,conn,rs);
}
return false;
}
}
JDBC控制事务
事务:一个包含多个步骤的业务操作。如果这个业务操作被事务管理,则这多个步骤要么同步成功,要么同步失败
- 操作管理事务(使用Connection对象):
- 开启事务 :setAutoCommit(boolean autoCommit) : 调用该方法设置参数为false,即开启事务
- 在执行sql之前开启事务
- 提交事务 :commit()
- 当所有sql都执行完提交事务
- 回滚事务 :rollback()
- 在catch中回滚事务
- 开启事务 :setAutoCommit(boolean autoCommit) : 调用该方法设置参数为false,即开启事务
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import JDBC_test.JDBCutil.jdbcUtils;
public class jdbc_transaction {
/**
* 事务操作
* @param args
*/
public static void main(String[] args) {
Connection conn = null;
PreparedStatement pstmt1 = null;
PreparedStatement pstmt2 = null;
try {
conn = jdbcUtils.getConnection();
//开启事务
conn.setAutoCommit(false);
String sql1 = "update account set balance = balance - ? where id = ?";
String sql2 = "update account set balance = balance + ? where id = ?";
pstmt1 = conn.prepareStatement(sql1);
pstmt2 = conn.prepareStatement(sql2);
pstmt1.setDouble(1,500);
pstmt1.setInt(2,1);
pstmt2.setDouble(1,500);
pstmt2.setInt(2,2);
pstmt1.executeUpdate();
pstmt2.executeUpdate();
// int i = 3/0; //制造异常
//提交事务
conn.commit();
} catch (SQLException e) {
//事务回滚
try {
if (conn != null){
conn.rollback();
}
} catch (Exception e1) {
e1.printStackTrace();
}
e.printStackTrace();
}finally {
jdbcUtils.close(pstmt1,conn);
jdbcUtils.close(pstmt2,null);
}
}
}