1.JDBC基本概念
- 概念:Java DataBase Connectivity Java 数据库连接, Java语言操作数据库
- JDBC本质:是官方(sun公司)定义的一套操作所有关系型数据库的规则,即接口。各个数据库厂商去实现这套接口,提供数据库驱动jar包。我们可以使用这套接口(JDBC)编程,真正执行的代码是驱动jar包中的实现类。
- 主要步骤如下:
- 导入驱动jar包 mysql-connector-java-5.1.37-bin.jar
1.1复制mysql-connector-java-5.1.37-bin.jar到项目的libs目录下
1.2右键–>Add As Library - 注册驱动
- 获取数据库连接对象 Connection
- 定义sql
- 获取执行sql语句的对象 Statement
- 执行sql,接受返回结果
- 处理结果
- 释放资源
- 导入驱动jar包 mysql-connector-java-5.1.37-bin.jar
- 示例代码:
//1. 导入驱动jar包
//2.注册驱动
Class.forName("com.mysql.jdbc.Driver");
//3.获取数据库连接对象
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db3", "root", "root");
//4.定义sql语句
String sql = "update account set balance = 500 where id = 1";
//5.获取执行sql的对象 Statement
Statement stmt = conn.createStatement();
//6.执行sql
int count = stmt.executeUpdate(sql);
//7.处理结果
System.out.println(count);
//8.释放资源
stmt.close();
conn.close();
2. 各个对象详解(1)
先看一下这几个对象:
1. DriverManager:驱动管理对象
* 功能:
1. 注册驱动:告诉程序该使用哪一个数据库驱动jar
static void registerDriver(Driver driver) :注册与给定的驱动程序 DriverManager 。
写代码使用: Class.forName("com.mysql.jdbc.Driver");
通过查看源码发现:在com.mysql.jdbc.Driver类中存在静态代码块
static {
try {
java.sql.DriverManager.registerDriver(new Driver());
} catch (SQLException E) {
throw new RuntimeException("Can't register driver!");
}
}
注意:mysql5之后的驱动jar包可以省略注册驱动的步骤。
2. 获取数据库连接:
* 方法:static Connection getConnection(String url, String user, String password)
* 参数:
* url:指定连接的路径
* 语法:jdbc:mysql://ip地址(域名):端口号/数据库名称
* 例子:jdbc:mysql://localhost:3306/db3
* 细节:如果连接的是本机mysql服务器,并且mysql服务默认端口是3306,则url可以简写为:jdbc:mysql:///数据库名称
* user:用户名
* password:密码
2. Connection:数据库连接对象
1. 功能:
1. 获取执行sql 的对象
* Statement createStatement()
* PreparedStatement prepareStatement(String sql)
2. 管理事务:
* 开启事务:setAutoCommit(boolean autoCommit) :调用该方法设置参数为false,即开启事务
* 提交事务:commit()
* 回滚事务:rollback()
3. Statement:执行sql的对象
1. 执行sql
1. boolean execute(String sql) :可以执行任意的sql 了解
2. int executeUpdate(String sql) :执行DML(insert、update、delete)语句、DDL(create,alter、drop)语句
* 返回值:影响的行数,可以通过这个影响的行数判断DML语句是否执行成功 返回值>0的则执行成功,反之,则失败。
3. ResultSet executeQuery(String sql) :执行DQL(select)语句
3. 简单练习
3.1 DML(insert、update、delete)
DML语句是最常用的。
下面代码是插入练习,最主要的就是**String sql = “insert into account values(null,‘王五’,3000)”;**这条语句,update和delete操作只需修改这一句即可。
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class JdbcDemo02 {
public static void main(String[] args) {
Connection conn = null;
Statement stmt = null;
try {
// 1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 2.定义sql
String sql = "insert into account values(null,'Mike',3000)";
// 3.获取connection连接对象
conn = DriverManager.getConnection("jdbc:mysql:///db3", "root", "root");
// 4.获取执行sql的对象 Statement
stmt = conn.createStatement();
// 5.执行sql
int count = stmt.executeUpdate(sql);
System.out.println("一共"+count+"行语句受到影响");
if (count>0){
System.out.println("修改成功!");
}else {
System.out.println("修改失败");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
// 7.释放资源
//避免空指针异常
if(stmt != null) {
try {
stmt.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
if (conn != null){
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
}
}
3.2 DDL(create,alter、drop)
主要步骤与3.1中一致,只需修改sql语句即可,以create为例,示例代码如下:
package jdbc_01;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class JdbcDemo04 {
public static void main(String[] args) {
Connection conn = null;
Statement stmt = null;
try {
// 1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 2.获取连接对象
conn = DriverManager.getConnection("jdbc:mysql:///db3", "root", "root");
// 3.获取执行对象
stmt = conn.createStatement();
// 4.定义sql语句
String sql = "create table stu(id int,name varchar(10))";
// String sql = "CREATE TABLE REGISTRATION " +
// "(id INTEGER not NULL, " +
// " first VARCHAR(255), " +
// " last VARCHAR(255), " +
// " age INTEGER, " +
// " PRIMARY KEY ( id ))";
// 5.执行sql语句
int count = stmt.executeUpdate(sql);
// 6.处理结果
System.out.println("一共"+count+"行语句受到影响");
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
// 7.释放资源
if(stmt != null){
try {
stmt.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(conn != null){
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
}
4. 各个对象详解(2)
4.1 基本概念
再看一下这几个对象:
ResultSet:结果集对象,封装查询结果
* boolean next(): 游标向下移动一行,判断当前行是否是最后一行末尾(是否有数据),如果是,则返回false,如果不是则返回true
* getXxx(参数):获取数据
* Xxx:代表数据类型 如: int getInt() , String getString()
* 参数:
1. int:代表列的编号,从1开始 如: getString(1)
2. String:代表列名称。 如: getDouble("balance")
* 注意:
* 使用步骤:
1. 游标向下移动一行
2. 判断是否有数据
3. 获取数据
4.2简单练习
- 下面做一个练习:
定义一个方法,查询dept表的数据将其封装为对象,然后装载集合,返回。 - 实现步骤为:
1. 定义Dept类
2. 定义方法 public List findAll(){}
3. 实现方法 select * from Dept;
首先先看一下Dept表格数据:
id | dname | loc |
---|---|---|
10 | 教研部 | 北京 |
20 | 学工部 | 上海 |
30 | 销售 | 广州 |
40 | 财务部 | 深圳 |
然后是代码,需要先定义一个Dept类,类中参数与表格索引名称一致:
public class Dept {
private int id;
private String dname;
private String loc;
public Dept() {
}
public Dept(int id, String dname, String loc) {
this.id = id;
this.dname = dname;
this.loc = loc;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getDname() {
return dname;
}
public void setDname(String dname) {
this.dname = dname;
}
public String getLoc() {
return loc;
}
public void setLoc(String loc) {
this.loc = loc;
}
@Override
public String toString() {
return "Dept{" +
"id=" + id +
", dname='" + dname + '\'' +
", loc='" + loc + '\'' +
'}'+'\n';
}
}
然后可以在主函数中写一个findAll方法,将所有的数据装入集合中:
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
/**
* 定义一个放大,查询dept表的数据并将其封装为对象,然后装载集合,返回
*/
public class JdbcDemo06 {
public static void main(String[] args) {
List<Dept> list = new JdbcDemo06().findAll();
System.out.println(list);
}
/**
* 查询emp对象
* @return
*/
public List<Dept> findAll(){
Connection conn = null;
Statement stmt = null;
ResultSet res = null;
List<Dept> list = null;
try {
//1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2.获取连接
conn = DriverManager.getConnection("jdbc:mysql:///db3", "root", "root");
//3.获取执行对象
stmt = conn.createStatement();
//4.定义sql
String sql = "select * from dept";
//5.执行sql
res = stmt.executeQuery(sql);
//6.遍历结果,封装成对象,装载集合中
Dept dept = null;
list = new ArrayList<>();
while(res.next()){
//创建dept对象,并赋值
dept = new Dept();
int id = res.getInt("id");
String dname = res.getString("dname");
String loc = res.getString("loc");
dept.setId(id);
dept.setDname(dname);
dept.setLoc(loc);
//装载集合
list.add(dept);
}
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}finally {
//释放资源
if (res != null){
try {
res.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
//释放资源
if (stmt != null){
try {
stmt.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
//释放资源
if (conn != null){
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
return list;
}
}
执行结果如下:
[Dept{id=10, dname=‘教研部’, loc=‘北京’}
, Dept{id=20, dname=‘学工部’, loc=‘上海’}
, Dept{id=30, dname=‘销售部’, loc=‘广州’}
, Dept{id=40, dname=‘财务部’, loc=‘深圳’}
]
4.3 代码优化——工具类
4.2中存在大量重复代码,所以现在将其优化,方法:抽取JDBC工具类 ——JDBCUtils。
- 思路如下:
- 首先,将close方法提取出来,写成一个静态方法,放在JDBCUtils.java中。因为用不同的语句时需要释放的资源数量和内容也不同,所以需要写两个静态close方法
- 然后,考虑将注册驱动和获取连接也抽取出来。获取连接需要给DriverManager.getConnection()输入3个参数,注册驱动也需要给Class.forName()输入1个参数,所以根据之前反射内容的学习,设置一个.properties配置文件。
- 最后,考虑到如果对同一个数据库执行多个操作,不能每次都要注册驱动和获取连接对象,故需要采用静态代码块。
jdbc.properties文件内容如下:
url=jdbc:mysql:///db3
user=root
password=root
driver=com.mysql.jdbc.Driver
具体实现代码如下:
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 {
try {
// 1.创建propert集合类
Properties pro = new Properties();
//2.获取src路径下的文件的方式:用ClassLoader类加载器
//2.1获取文件路径
ClassLoader classLoader = JDBCUtils.class.getClassLoader();
URL resource = classLoader.getResource("jdbc.properties");
String path = resource.getPath();
//2.2加载文件
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 | ClassNotFoundException e) {
e.printStackTrace();
}
}
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(url,user,password);
}
/**
* 释放资源
* @param conn
* @param stmt
* @param res
*/
public static void close(Connection conn, Statement stmt, ResultSet res){
if(res != null){
try {
res.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(stmt != null){
try {
stmt.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(conn != null){
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
/**
* 释放资源
* @param conn
* @param stmt
*/
public static void close(Connection conn, Statement stmt){
if(stmt != null){
try {
stmt.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(conn != null){
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}