1. 概念
- Java DataBase Connectivity Java 数据库连接 Java语言操作数据库
- JDBC本质:其实是官方(sun)公司的一套操作所有关系型数据库的规则,即接口。各个数据库厂商去实现这套接口,提供数据库驱动jar包。我们可以使用这套接口(JDBC)编程,真正执行的代码是驱动jar包中的实现类 Person接口 Worker类 Person p=new Worker p.eat()
2.快速入门
2.1 步骤
* 导入驱动jar包
* 注册驱动
* 获取数据库连接对象 Connection
* 定义sql
* 注意:参数使用?作为占位符
* 获取执行sql语句的对象 Statement
* 执行sql 接受返回的结果
* 处理结果
* 释放资源
2.2 举例
package cn.itcast.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
//jdbc的快速入门
public class JdbcDemo1 {
public static void main(String[] args) throws Exception {
//1.导入驱动jar包
//2.注册驱动
Class.forName("com.mysql.jdbc.Driver");
//3.获取数据的链接对象
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/db3", "root", "123456");
//4.定义sql语句
String sql="UPDATE account set balance=500 WHERE id=1";
//5.获取执行sql的对象 Statement
Statement stmt= connection.createStatement();
//6.执行sql
int count=stmt.executeUpdate(sql);
//7.处理结果
System.out.println(count);
//8.释放资源
stmt.close();
connection.close();
}
}
3 详解各个对象
3.1 DriverManager:驱动管理对象
注册驱动:告诉程序该使用哪一个数据库驱动jar
static void registerDriver(Driver driver):注册与给定的驱动程序 DriverManager
写代码使用: Class.forName("com.mysql.jdbc.Driver");
通过查看源码发现:在com.mysql.jdbc.Driver类中存在静态代码块
static{
try{
java.sql.DriverManger.registerDriver(new Driver());
}catch(SQLException E){
throw new RuntimeException("Can‘t register driver!");
}
}
注意:mysql5之后的驱动jar包可以忽略注册驱动的步骤
获取数据库连接
- 方法:static Connection getConnection(String url,String user,String password)
- 参数:
- url:指定连接的路径
- 语法:jdbc:mysql://ip地址(域名):端口号/数据库名称
- 例子:jdbc:mysql://localhost:3306/db3
- user:用户名
- password:密码
- url:指定连接的路径
3.2 Connection:数据库连接对象
获取执行sql的对象
- Statement createStatement()
- PreparedStatement preparedStatement(String sql)
管理事务
- 开启事务:setAutoCommit(boolean autoCommit):调用该方法设置参数为false。即开启事务
- 提交事务:commit()
3.3 Statement:执行sql的对象
- 执行sql
- boolean excute(String sql):可以执行任意的sql语句
- int excuteUpdata(String sql):执行DDL语句(create,alter,drop),执行DML语句(insert,update,delete)
- 返回值:影响的行数,可以通过这个影响的行数来判断语句是否执行成功,返回值大于0则执行成功,反之,失败
- ResultSet excuteQuery(String sql):执行DQL语句(select)
举例
package cn.itcast.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class JdbcDemo5 {
public static void main(String[] args){
Statement stmt=null;
Connection connection=null;
//1.导入驱动jar包
//2.注册驱动
try {
Class.forName("com.mysql.jdbc.Driver");
//4.定义sql语句
String sql="CREATE TABLE studentone(id int,name varchar(20))";
//3.获取数据的链接对象
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/db3", "root", "123456");
//5.获取执行sql的对象 Statement
stmt= connection.createStatement();
//6.执行sql
int count=stmt.executeUpdate(sql);
//7.处理结果
System.out.println(count);
if (count>0){
System.out.println("添加成功");
}else{
System.out.println("添加失败");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}finally {
//8.释放资源
//避免空指针异常
// stmt.close();
if (stmt!=null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (connection!=null){
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
3.4 ResultSet:结果集对象
- Boolean next():游标向下移动一行
- getXxx(参数):获取数据
- Xxx:代表数据类型 如 int getInt(),String getString()
- 参数:
- 1.int:代表列的编号,从1开始 如:getString(1)
- 2.String:代表列名称,如:getDouble("balance")‘
- 注意:
- 使用步骤:
- 游标向下移动一行
- 判断是否有数据
- 获取数据
- 使用步骤:
举例
//6.执行sql
resultSet =stmt.executeQuery(sql);
//7.处理结果
//游标下移一行
while(resultSet.next()){
//获取数据
int id=resultSet.getInt(1);
String name=resultSet.getString("name");
double balance =resultSet.getDouble(3);
System.out.println(id+"-----"+name+"------"+balance);
}
3.5 PreparedStatement:执行sql的对象
- SQL注入问题:在拼接SQL时,有一些SQL的特殊关键字参与字符串的拼接。会造成安全性问题
- 输入用户随便,输入密码:‘a‘ or ‘a‘=‘a‘
- SQL:select * from user where username=‘FHDSJKF‘ and password=‘a‘ or ‘a‘=‘a‘
- 解决SQL注入问题:使用PreparedStatement对象来解决
- 预编译的SQL:参数使用?作为占位符
- 步骤:
- 步骤:
- 导入驱动jar包
- 注册驱动
- 获取数据库连接对象 Connection
- 定义sql
- 注意:参数使用?作为占位符 如:select * from user where username=? and password=?
- 获取执行sql语句的对象 PreparedStatement Connection.prepareStatement(String sql)
- 给?赋值
- 方法:setXxx(参数1,参数2)
- 参数1:?的1位置编号从1开始
- 参数2:?的值
- 方法:setXxx(参数1,参数2)
- 执行sql 接受返回的结果,不需要传递SQL语句
- 处理结果
- 释放资源
- 注意:后期都会使用ReparedStatement来完成增删查改的所有操作
- 可以防止SQL注入
- 效率更高
4.定义一种方法,查询emp表的数据将其封装成对象,然后装载集合,返回
4.1 定义emp类
package cn.itcast.domain;
import java.util.Date;
//封装Emp表的JavaBean
public class Emp {
private int id;
private String ename;
private int job_id;
private int mgr;
private Date joindate;
private double salary;
private double bounds;
private int dept_id;
public Emp(int id, String ename, int job_id, int mgr, Date joindate, double salary, double bounds, int dept_id) {
this.id = id;
this.ename = ename;
this.job_id = job_id;
this.mgr = mgr;
this.joindate = joindate;
this.salary = salary;
this.bounds = bounds;
this.dept_id = dept_id;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getEname() {
return ename;
}
public void setEname(String ename) {
this.ename = ename;
}
public int getJob_id() {
return job_id;
}
public void setJob_id(int job_id) {
this.job_id = job_id;
}
public int getMgr() {
return mgr;
}
public void setMgr(int mgr) {
this.mgr = mgr;
}
public Date getJoindate() {
return joindate;
}
public void setJoindate(Date joindate) {
this.joindate = joindate;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public double getBounds() {
return bounds;
}
public void setBounds(double bounds) {
this.bounds = bounds;
}
public int getDept_id() {
return dept_id;
}
public void setDept_id(int dept_id) {
this.dept_id = dept_id;
}
@Override
public String toString() {
return "Emp{" +
"id=" + id +
", ename=‘" + ename + ‘\‘‘ +
", job_id=" + job_id +
", mgr=" + mgr +
", joindata=" + joindate +
", salary=" + salary +
", bounds=" + bounds +
", dept_id=" + dept_id +
‘}‘;
}
}
4.2 定义方法 public List findAll(){}
package cn.itcast.jdbc;
import cn.itcast.domain.Emp;
import cn.itcast.utils.JDBCutils;
import java.sql.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
//定义一个方法,查询emp表的数据将其封装成对象,然后装载集合,返回
public class JdbcDemo9 {
public List
Statement stmt=null;
Connection connection=null;
ResultSet resultSet=null;
List
Emp emp=null;
//1.导入驱动jar包
//2.注册驱动
try {
// Class.forName("com.mysql.jdbc.Driver");
// //3.获取数据的链接对象
// connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/db3", "root", "123456");
connection=JDBCutils.getConnection();
//4.定义sql语句
String sql="select * from emp";
//5.获取执行sql的对象 Statement
stmt= connection.createStatement();
//6.执行sql
resultSet =stmt.executeQuery(sql);
//7.处理结果
//游标下移一行
while(resultSet.next()){
//获取数据
System.out.println("----------1-----------");
int id=resultSet.getInt("id");
String ename=resultSet.getString("ename");
int job_id=resultSet.getInt("job_id");
int mgr=resultSet.getInt("mgr");
Date joindate=resultSet.getDate("joindate");
double salary=resultSet.getDouble("sarlary");
double bounds=resultSet.getDouble("bonus");
int dept_id=resultSet.getInt("dept_id");
//创建emp对象
emp=new Emp(id,ename,job_id,mgr,joindate,salary,bounds,dept_id);
//装载集合
list.add(emp);
// System.out.println(list);
}
}catch (SQLException e) {
e.printStackTrace();
}finally {
//8.释放资源
//避免空指针异常
//未使用jdbcutil工具类简化
// stmt.close();
// if (resultSet!=null){
// try {
// resultSet.close();
// } catch (SQLException e) {
// e.printStackTrace();
// }
// }
// if (connection!=null){
// try {
// connection.close();
// } catch (SQLException e) {
// e.printStackTrace();
// }
// }
JDBCutils.close(resultSet,stmt,connection);
}
return list;
}
public static void main(String[] args) {
List<Emp> list=new JdbcDemo9().findAll();
System.out.println(list);
}
}
4.3 实现方法 select * from emp
public static void main(String[] args) {
List<Emp> list=new JdbcDemo8().findAll();
System.out.println(list);
}
}
5.抽取JDBC工具类:JDBCUTILS
package cn.itcast.utils;
import java.io.FileReader;
import java.io.IOException;
import java.net.URL;
import java.sql.*;
import java.util.Properties;
//jdbc工具类
public class JDBCutils {
private static String url;
private static String user;
private static String password;
private static String driver;
//文件的读取,只需读取一次就可的导这些值,使用静态代码块
static {
//读取资源文件,获取值
//1.创建Properties集合类
Properties properties=new Properties();
//获取src路径下的文件的方式--->ClassLoader 类加载器
ClassLoader classLoader=JDBCutils.class.getClassLoader();
URL res=classLoader.getResource("jdbc.properties");
String path=res.getPath();
System.out.println(path);
//加载文件
try {
properties.load(new FileReader("E:\\Idea Project\\yonghucase\\out\\production\\jdbc test\\jdbc.properties"));
// properties.load(new FileReader(path));
//获取属性赋值
url=properties.getProperty("url");
user=properties.getProperty("user");
password=properties.getProperty("password");
driver=properties.getProperty("driver");
//注册驱动
Class.forName(driver);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
//获取连接
public static Connection getConnection() throws SQLException{
return DriverManager.getConnection(url,user,password);
}
//释放资源
public static void close(Statement statement,Connection connection){
if(statement!=null){
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(connection!=null){
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public static void close(ResultSet resultSet,Statement statement, Connection connection){
if(resultSet!=null){
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(statement!=null){
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(connection!=null){
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
5.1 目的:简化书写
- 分析:
- 注册驱动也抽取
- 抽取一个方法获取连接对象
- 需求:不想传递参数,还得保证工具类的通用性
- 解决:配置文件
jdbc.properties
url=
user=
password=
- 抽取一个方法释放资源
5.2 练习:通过键盘录入用户名和密码,判断用户是否登录成功
package cn.itcast.jdbc;
import cn.itcast.domain.Emp;
import cn.itcast.utils.JDBCutils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Scanner;
public class JdbcDemo10 {
public static void main(String[] args){
//键盘录入,接受用户名和密码
Scanner scanner=new Scanner(System.in);
System.out.println("请输入用户名");
String username=scanner.nextLine();
System.out.println("请输入密码");
String password=scanner.nextLine();
//调用方法
boolean flag=new JdbcDemo10().login(username,password);
//判断结果,输出不同数据
if(flag){
System.out.println("登录成功");
}else{
System.out.println("登录失败");
}
}
//登录方法
public boolean login(String username,String password){
if(username==null||password==null){
return false;
}
Connection connection=null;
Statement stmt=null;
ResultSet resultSet=null;
// //3.获取数据的链接对象
try {
connection = JDBCutils.getConnection();
//定义sql
String sql="select * from user where username=‘"+username+"‘ and password=‘"+password+"‘";
//获取执行sql的对象
stmt=connection.createStatement();
//执行查询
resultSet=stmt.executeQuery(sql);
return resultSet.next();
} catch (SQLException e) {
e.printStackTrace();
}finally {
JDBCutils.close(resultSet,stmt,connection);
}
//连接数据库判断是否成功
return false;
}
}
6.JDBC控制事务
6.1 事务
- 一个包含多个步骤的业务操作。如果业务操作被事务管理,则多个步骤要么同时成功。要么同时失败
6.2 操作
- 开启事务
- 提交事务
- 回滚事务
6.3 使用Connection对象来管理事务
- 开启事务:setAutoCommit(boolean autoCommit):调用该方法设置参数为false。即开启事务
- 提交事务:commit()
- 回滚事务:rollback()
6.4 实例
package cn.itcast.jdbc;
import cn.itcast.utils.JDBCutils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class JdbcDemo12 {
public static void main(String[] args){
Connection connection=null;
PreparedStatement preparedStatement1=null;
PreparedStatement preparedStatement2=null;
ResultSet resultSet=null;
//获取连接
try {
connection= JDBCutils.getConnection();
String sql1="update account set balance=balance-? where id=?";
String sql2="update account set balance=balance+? where id=?";
preparedStatement1=connection.prepareStatement(sql1);
preparedStatement2=connection.prepareStatement(sql2);
//设置参数
preparedStatement1.setDouble(1,500);
preparedStatement1.setInt(2,1);
preparedStatement2.setDouble(1,500);
preparedStatement2.setInt(2,1);
preparedStatement1.executeUpdate();
preparedStatement2.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}finally {
JDBCutils.close(preparedStatement1,connection);
JDBCutils.close(preparedStatement2,connection);
}
}
}