JDBC(Java-Database-Connectivity)是一套用于执行SQL语句的Java的API。应用程序可通过这套API连接到关系型数据库,并使用SQL语句来完成对数据库中数据的查询、新增、更新和删除等操作。
通常情况下,JDBC的使用可以按照下面几个步骤进行:
简单模拟一下整个流程:将数据库test中的表sales中的“xiaohua”的sum值改为10000
import java.sql.DriverManager;
import java.sql.Statement;
import java.sql.Connection;
import java.sql.DriverManager;
public class Demo01 {
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/test", "root", "19991204");
// 4.定义SQL语句
String str = "update sales set sum = 10000 where name = 'xiaohua'";
// 5.获取执行sql对象Statement
Statement stmt= conn.createStatement();
// 6.执行SQL语句
int count = stmt.executeUpdate(str);
// 7.处理结果
System.out.println(count);
// 8.释放资源
stmt.close();
conn.close();
}
}
1
功能:注册驱动、获取数据库连接
(1)注册驱动:
static void registerDriver(Driver driver):注册与给定的驱动程序DriverManager
写代码使用:使用Class.forName("com.mysql.jdbc.Driver");
【说明】:通过查看源码发现:在com.mysql.jdbc.Driver类中存在静态代码块用来注册驱动,因此我们通过上面的代码会简单一些。
// 1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
【注意】:MySQL5之后的驱动jar包可以省略注册的步骤。
(2)获取数据库连接:
static Connection getConnection(String url, String user, String password),
// 3.获取数据库连接对象
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "19991204");
【注意】:如果连接的是本机mysql服务器,并且mysql服务器默认端口3306,则url可以简写为:jdbc:mysql://数据库名称。
功能:获取执行SQL对象、管理事务
(1)获取执行SQL对象:
(2)管理事务:
【注意】executUpdate的返回值:影响的行数,可以通过这个影响的行数判断DML语句是否执行成功,返回值>0的则执行成功。
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class Demo02 {
public static void main(String[] args) {
Statement stmt = null; //如果不在外面提前定义好,那么在finally代码块中无法看到stmt
Connection conn = null;
try {
// 1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 2.获取Connection对象
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "19991204");
// 3.定义SQL
String str = "insert into sales values('xiaoxiong', 10000)";
// 4.获取执行sql对象Statement
stmt = conn.createStatement();
// 5.执行SQL语句
int count = stmt.executeUpdate(str); //返回值是行数
// 6.处理结果
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{
//stmt.close();
// 7.释放资源
//避免空指针异常
if(stmt != null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
影响的行数一共有:1
添加成功!
【说明】:
【注意】:
流程步骤:
import java.sql.*;
public class Demo04 {
public static void main(String[] args) {
Statement stmt = null; //如果不在外面提前定义好,那么在finally代码块中无法看到stmt
Connection conn = null;
ResultSet rs = null;
try {
// 1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 2.获取Connection对象
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "19991204");
// 3.定义SQL
String str = "select * from sales";
// 4.获取执行sql对象Statement
stmt = conn.createStatement();
// 5.执行SQL语句
rs = stmt.executeQuery(str);
// 6.处理结果
// 6.1光标向下移动一行
rs.next();
// 6.2获取数据
String name = rs.getString("name");
double balance = rs.getDouble(2);
// 6.3打印数据
System.out.println(name + "---" + balance);
rs.next();
name = rs.getString("name");
balance = rs.getDouble(2);
System.out.println(name + "---" + balance);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}finally{
// 7.释放资源
//避免空指针异常
if(rs != null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(stmt != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
xiaohua---10000.0
zhoutong---1000.0
重新更改一部分代码,来打印表中的所有数据:
// 6.处理结果
// 判断光标是否为最后一行
while(rs.next()){
// 获取数据
//String name = rs.getString(1);
String name = rs.getString("name");
//double balance = rs.getDouble(2);
double balance = rs.getDouble("sum");
// 打印数据
System.out.println(name + "---" + balance);
}
xiaohua---10000.0
zhoutong---1000.0
roy---2000.0
xiaoxiong---10000.0
打印CHARACTER_SETS表中的数据:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class Demo06 {
public static void main(String[] args) {
Statement stmt = null;
Connection conn = null;
ResultSet rs = null;
try {
// 1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 2.获取Connection对象
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/information_schema", "root", "19991204");
// 3.定义SQL
String str = "SELECT * FROM CHARACTER_SETS;";
// 4.获取执行sql对象Statement
stmt = conn.createStatement();
// 5.执行SQL语句
rs = stmt.executeQuery(str);
// 6.处理结果
// 判断光标是否为最后一行
while(rs.next()){
// 获取数据
String str1 = rs.getString(1);
String str2 = rs.getString(2);
String str3 = rs.getString(3);
double num = rs.getDouble(4);
// 打印数据
System.out.println(str1 + "---" + str2 + "---" + str3 + "---" + num);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}finally{
// 7.释放资源
//避免空指针异常
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();
}
}
}
}
}
gb2312---gb2312_chinese_ci---GB2312 Simplified Chinese---2.0
greek---greek_general_ci---ISO 8859-7 Greek---1.0
cp1250---cp1250_general_ci---Windows Central European---1.0
gbk---gbk_chinese_ci---GBK Simplified Chinese---2.0
latin5---latin5_turkish_ci---ISO 8859-9 Turkish---1.0
armscii8---armscii8_general_ci---ARMSCII-8 Armenian---1.0
utf8---utf8_general_ci---UTF-8 Unicode---3.0
ucs2---ucs2_general_ci---UCS-2 Unicode---2.0
cp866---cp866_general_ci---DOS Russian---1.0
keybcs2---keybcs2_general_ci---DOS Kamenicky Czech-Slovak---1.0
macce---macce_general_ci---Mac Central European---1.0
macroman---macroman_general_ci---Mac West European---1.0
cp852---cp852_general_ci---DOS Central European---1.0
latin7---latin7_general_ci---ISO 8859-13 Baltic---1.0
import java.util.Date;
public class Emp {
private int employee_id;
private String first_name;
private String last_name;
private String email;
private String phone_number;
private String job_id;
private double salary;
private double commission_pct;
private int manager_id;
private int department_id;
private Date hiredate;
public Date getHiredate() {
return hiredate;
}
public void setHiredate(Date hiredate) {
this.hiredate = hiredate;
}
public int getEmployee_id() {
return employee_id;
}
public void setEmployee_id(int employee_id) {
this.employee_id = employee_id;
}
public String getFirst_name() {
return first_name;
}
public void setFirst_name(String first_name) {
this.first_name = first_name;
}
public String getLast_name() {
return last_name;
}
public void setLast_name(String last_name) {
this.last_name = last_name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPhone_number() {
return phone_number;
}
public void setPhone_number(String phone_number) {
this.phone_number = phone_number;
}
public String getJob_id() {
return job_id;
}
public void setJob_id(String job_id) {
this.job_id = job_id;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public double getCommission_pct() {
return commission_pct;
}
public void setCommission_pct(double commission_pct) {
this.commission_pct = commission_pct;
}
public int getManager_id() {
return manager_id;
}
public void setManager_id(int manager_id) {
this.manager_id = manager_id;
}
public int getDepartment_id() {
return department_id;
}
public void setDepartment_id(int department_id) {
this.department_id = department_id;
}
@Override
public String toString() {
return "Emp [employee_id=" + employee_id + ", first_name=" + first_name + ", last_name=" + last_name
+ ", email=" + email + ", phone_number=" + phone_number + ", job_id=" + job_id + ", salary=" + salary
+ ", commission_pct=" + commission_pct + ", manager_id=" + manager_id + ", department_id="
+ department_id + ", hiredate=" + hiredate + "]";
}
}
import java.sql.Connection;
import java.sql.Date;
import java.sql.DriverManager;
import java.util.ArrayList;
import java.util.List;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.ResultSet;
public class Demo07 {
public static void main(String[] args) {
List<Emp> list = new Demo07().findAll();
System.out.println(list);
System.out.println(list.size());
}
public List<Emp> findAll(){
Statement stmt = null;
Connection conn = null;
ResultSet rs = null;
List<Emp> list = null;
try {
// 1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 2.获取Connection对象
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/myemployees", "root", "19991204");
// 3.定义SQL
String str = "SELECT * FROM employees;";
// 4.获取执行sql对象Statement
stmt = conn.createStatement();
// 5.执行SQL语句
rs = stmt.executeQuery(str);
// 6.遍历结果集,封装对象,装在集合
Emp emp = null; //提前定义好,放置每次循环重复创建对象,占用过多的栈内存!
list = new ArrayList<Emp>();
while (rs.next()) {
// 获取数据
int employee_id = rs.getInt("employee_id");
String first_name = rs.getString("first_name");
String last_name = rs.getString("last_name");
String email = rs.getString("email");
String phone_number = rs.getString("phone_number");
String job_id = rs.getString("job_id");
double salary = rs.getDouble("salary");
double commission_pct = rs.getDouble("commission_pct");
int manager_id = rs.getInt("manager_id");
int department_id = rs.getInt("department_id");
Date hiredate = rs.getDate("hiredate");
// 创建对象并赋值
emp = new Emp();
emp.setEmployee_id(employee_id);
emp.setFirst_name(first_name);
emp.setLast_name(last_name);
emp.setEmail(email);
emp.setPhone_number(phone_number);
emp.setJob_id(job_id);
emp.setSalary(salary);
emp.setCommission_pct(commission_pct);
emp.setManager_id(manager_id);
emp.setDepartment_id(department_id);
emp.setHiredate(hiredate);
// 装载集合
list.add(emp);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally{
// 7.释放资源
// 避免空指针异常
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;
}
}
//略了一部分数据
[Emp [employee_id=100, first_name=Steven, last_name=K_ing, email=SKING, phone_number=515.123.4567, job_id=AD_PRES, salary=24000.0, commission_pct=0.0, manager_id=0, department_id=90, hiredate=1992-04-03], Emp [employee_id=101, first_name=Neena, last_name=Kochhar, email=NKOCHHAR, phone_number=515.123.4568, job_id=AD_VP, salary=17000.0, commission_pct=0.0, manage.............]
107
目的:简化书写。
分析:
配置文件:jdbc.properties
url=jdbc:mysql:///myemployees
user=root
password=19991204
driver=com.mysql.jdbc.Driver
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.net.URL;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
import java.sql.ResultSet;
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();
// //获取src路径下的文件的方式--->ClassLoader 类加载器
// ClassLoader classLoader = JDBCUtils.class.getClassLoader();
// URL res = ClassLoader.getSystemResource("jdbc.properties");
// String path = res.getPath();
// System.out.println(path);
//2.加载文件
pro.load(new FileReader("src/jdbc.properties")); //【注意】:路径可能出现问题,写绝对路径肯定正确,但是不合适
// 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();
}
}
// 获取链接,返回连接对象
public static Connection getConnection() throws SQLException{
return DriverManager.getConnection(url, user, password);
}
// 释放资源
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();
}
}
}
public static void close(ResultSet rs, 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();
}
}
if(rs != null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
import java.sql.Connection;
import java.sql.Date;
import java.sql.DriverManager;
import java.util.ArrayList;
import java.util.List;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.ResultSet;
public class Demo08 {
public static void main(String[] args) {
List<Emp> list = new Demo08().findAll2();
System.out.println(list);
System.out.println(list.size());
}
public List<Emp> findAll2(){
Statement stmt = null;
Connection conn = null;
ResultSet rs = null;
List<Emp> list = null;
try {
// // 1.注册驱动
// Class.forName("com.mysql.jdbc.Driver");
// // 2.获取Connection对象
conn = JDBCUtils.getConnection();
// 3.定义SQL
String str = "SELECT * FROM employees;";
// 4.获取执行sql对象Statement
stmt = conn.createStatement();
// 5.执行SQL语句
rs = stmt.executeQuery(str);
// 6.遍历结果集,封装对象,装在集合
Emp emp = null; //提前定义好,放置每次循环重复创建对象,占用过多的栈内存!
list = new ArrayList<Emp>();
while (rs.next()) {
// 获取数据
int employee_id = rs.getInt("employee_id");
String first_name = rs.getString("first_name");
String last_name = rs.getString("last_name");
String email = rs.getString("email");
String phone_number = rs.getString("phone_number");
String job_id = rs.getString("job_id");
double salary = rs.getDouble("salary");
double commission_pct = rs.getDouble("commission_pct");
int manager_id = rs.getInt("manager_id");
int department_id = rs.getInt("department_id");
Date hiredate = rs.getDate("hiredate");
// 创建对象并赋值
emp = new Emp();
emp.setEmployee_id(employee_id);
emp.setFirst_name(first_name);
emp.setLast_name(last_name);
emp.setEmail(email);
emp.setPhone_number(phone_number);
emp.setJob_id(job_id);
emp.setSalary(salary);
emp.setCommission_pct(commission_pct);
emp.setManager_id(manager_id);
emp.setDepartment_id(department_id);
emp.setHiredate(hiredate);
// 装载集合
list.add(emp);
}
} catch (SQLException e) {
e.printStackTrace();
} finally{
JDBCUtils.close(rs, stmt,conn);
}
return list;
}
}
//略了一部分数据
[Emp [employee_id=100, first_name=Steven, last_name=K_ing, email=SKING, phone_number=515.123.4567, job_id=AD_PRES, salary=24000.0, commission_pct=0.0, manager_id=0, department_id=90, hiredate=1992-04-03], Emp [employee_id=101, first_name=Neena, last_name=Kochhar, email=NKOCHHAR, phone_number=515.123.4568, job_id=AD_VP, salary=17000.0, commission_pct=0.0, manage.............]
107
【说明】:代码变得简洁干净。
数据库user中的账户及密码情况:
配置文件:
url=jdbc:mysql:///test
user=root
password=19991204
driver=com.mysql.jdbc.Driver
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Scanner;
import java.sql.PreparedStatement;
public class Demo09 {
public static void main(String[] args) {
//1.键盘录入,接受用户名和密码
Scanner sc = new Scanner(System.in);
System.out.println("请输入用户名: ");
String username = sc.nextLine();
System.out.println("请输入密码: ");
String password = sc.nextLine();
//2.调用方法
boolean flag = new Demo09().login(username, password);
//3.判断结果
if(flag){
System.out.println("登陆成功!");
}else{
System.out.println("用户名或密码错误!");
}
}
// 登陆方法
public boolean login(String username, String password){
if(username == null || password == null){
return false;
}
Statement stmt = null;
Connection conn = null;
ResultSet rs = null;
//连接数据库
//1.获取连接
try {
conn = JDBCUtils.getConnection();
//2.定义SQL
String sql = "select * from user where username = '"+username+"' and password = '"+password+"' ";
//3.获取执行SQL的对象
stmt = conn.createStatement();
//4.执行查询
rs = stmt.executeQuery(sql);
//5.判断
return rs.next(); //如果有下一行,则返回true
} catch (SQLException e) {
e.printStackTrace();
} finally{
JDBCUtils.close(rs, stmt,conn);
}
return false;
}
}
请输入用户名:
zt
请输入密码:
123456
登陆成功!
还在上面的案例中,用户名随机输入,在密码栏中输入a' or 'a' = 'a,发现竟然登陆成功!!!账户与密码信息没有出现在数据库中的user表中,却可以登陆成功!
请输入用户名:
123
请输入密码:
a' or 'a' = 'a
登陆成功!
【说明】:SQL语句变成了“select * from user where username = '123' and password = 'a' or 'a' = 'a'”
SQL注入问题:在拼接SQL时,有一些SQL的特殊关键字与字符串拼接,会造成安全问题。
预编译的SQL:参数使用?作为占位符
解决方案:使用PreparedStatement对象来解决
【注意】:参数1:?的位置编号,从1开始;参数2:?的值
再重新利用PreparedStatement来实现一个新的登陆方法:
// 登陆方法 【注意】:利用了PreparedStatement实现
public boolean login2(String username, String password) {
if (username == null || password == null) {
return false;
}
PreparedStatement pstmt = null;
Connection conn = null;
ResultSet rs = null;
// 连接数据库
// 1.获取连接
try {
conn = JDBCUtils.getConnection();
// 2.定义SQL
String sql = "select * from user where username = ? and password = ?";
// 3.获取执行SQL的对象
// stmt = conn.createStatement();
pstmt = conn.prepareStatement(sql);
//给?赋值
pstmt.setString(1, username);
pstmt.setString(2, password);
// 4.执行查询
// rs = stmt.executeQuery(sql);
rs = pstmt.executeQuery();
// 5.判断
return rs.next(); // 如果有下一行,则返回true
} catch (SQLException e) {
e.printStackTrace();
} finally {
JDBCUtils.close(rs, pstmt, conn);
}
return false;
}
请输入用户名:
123
请输入密码:
a' or 'a' = 'a
登陆失败!
事务:一个包含多个步骤的业务操作。如果这个业务操作被事务管理,则多个步骤要么同时成功,要么同时失败。
【说明】:例如如果在记账的时候,由于程序中间出现错误导致程序中断,就会造成一部分员工的工资改变,一部分人的工资没变,产生巨大的影响。
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Scanner;
public class Demo10 {
public static void main(String[] args) {
PreparedStatement pstmt1 = null;
PreparedStatement pstmt2 = null;
Connection conn = null;
ResultSet rs = null;
try {
// 1.获取连接
conn = JDBCUtils.getConnection();
//----------------------开启事务-----------------------
conn.setAutoCommit(false);
// 2.定义SQL
String sql1 = "update counts set balance = balance - ? where id = ?";
String sql2 = "update counts set balance = balance + ? where id = ?";
// 3.获取执行SQL的对象
pstmt1 = conn.prepareStatement(sql1);
pstmt2 = conn.prepareStatement(sql2);
// 4.给?赋值
pstmt1.setDouble(1, 500);
pstmt1.setInt(2, 1);
pstmt2.setDouble(1, 500);
pstmt2.setInt(2, 2);
// 5.执行sql
pstmt1.executeUpdate();
int i = 3/0; //故意写出的错误!!!!!
pstmt2.executeUpdate();
//----------------------提交事务-----------------------
conn.commit();
} catch (SQLException e) {
//事务回滚
try {
if(conn != null){
conn.rollback();
}
} catch (SQLException e1) {
e1.printStackTrace();
}
e.printStackTrace();
} finally {
JDBCUtils.close(pstmt1, conn);
JDBCUtils.close(pstmt2, conn);
}
}
}
Exception in thread "main" java.lang.ArithmeticException: / by zero
at Demo10.main(Demo10.java:33)
【说明】:程序中间出现错误,导致中断,两个SQL语句都不执行!
评论