JavaEE学习日志持续更新----> 必看!JavaEE学习路线(文章总汇)
Java学习日志(三十二)
JDBC
JDBC的概念和原理
JDBC使用步骤
JDBC:使用java程序执行sql语句,对数据库表进行增删改查(CURD)
使用步骤:固定
-
注册驱动,告之JVM我们使用的是哪种数据库驱动程序(mysql,oracle…)
-
获取数据库连接对象
Connection
java程序:TCP客户端 数据库:TCP服务器 使用客户端访问服务器,和服务器经过3次握手建立一个连接通路 这个连接通路中有一个IO流对象,用于客户端和服务器交互数据
-
获取执行者对象
Statement
,用于执行sql语句,把sql语句发送到数据库中执行 -
执行sql语句,获取结果集
- 增删改:int affected(受影响的) 影响数据库的有效行数
- 查询:ResultSet结果集,把查询的多行结果存储到一个结果集中 -
处理结果集
- 增删改:不用处理
- 查询:遍历结果集 -
释放资源
注意:1,2,3,6固定不变,4,5根据增删改查不同而不同
第一步:注册驱动
使用java.sql.DriverManager
类中的方法实现:管理一组JDBC驱动程序的基本服务。
静态方法:
static void registerDriver(Driver driver)
使用 DriverManager注册给定的驱动程序。
参数:
java.sql.Driver:是一个接口,每个驱动程序类必须实现的接口。
传递Driver接口的实现类对象,由mysql驱动提供
com.mysql.jdbc.Driver
public class Demo01JDBC {
public static void main(String[] args) throws SQLException {
DriverManager.registerDriver(new Driver());
}
}
查看com.mysql.jdbc.Driver
的源码发现,有一个静态代码块,已经注册了驱动,我们再注册一个驱动,就注册了两次,会产生浪费。
static {
try {
DriverManager.registerDriver(new Driver());
} catch (SQLException var1) {
throw new RuntimeException("Can't register driver!");
}
}
解决方案:使用反射技术,获取class文件,会执行类中的静态代码块
格式:Class.forName("foo.bah.Driver")
public class Demo01JDBC {
public static void main(String[] args) throws ClassNotFoundException {
Class.forName("com.mysql.jdbc.Driver");
}
}
第二步:获取数据库连接对象Connection
使用java.sql.DriverManager类
中的方法实现
静态方法:
static Connection getConnection(String url, String user, String password)
尝试建立与给定数据库URL的连接。
参数:
String url:数据库服务器的地址,固定格式
- jdbc:mysql://ip:端口号/数据库名称
- jdbc:mysql://localhost:3306/day03
String user:数据库用户名
String password:数据库密码
返回值:
java.sql.Connection是一个接口,返回的是Connection接口的实现类对象
由mysql驱动提供,我们可以使用Connection接口来接收这个实现类对象(多态)
public class Demo01JDBC {
public static void main(String[] args) throws ClassNotFoundException {
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/day03", "root", "root");
//System.out.println(conn);com.mysql.jdbc.JDBC4Connection@28f67ac7
}
}
第三步:获取执行者对象Statement
使用Connection接口
中提供的方法实现:
Statement createStatement()
创建一个 Statement对象,用于将SQL语句发送到数据库。
返回值:
java.sql.Statement是一个接口,返回的是Statement接口的实现类对象
由mysql驱动提供,我们可以使用Statement接口来接收这个实现类对象(多态)
public class Demo01JDBC {
public static void main(String[] args) throws ClassNotFoundException {
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/day03", "root", "root");
//System.out.println(conn);com.mysql.jdbc.JDBC4Connection@28f67ac7
Statement stat = conn.createStatement();
//System.out.println(stat);//com.mysql.jdbc.StatementImpl@28f67ac7
}
}
第四步:执行sql语句,获取结果集
使用Statement接口
中的方法实现:
int executeUpdate(String sql)
执行给定的SQL语句,这可能是 INSERT , UPDATE ,或 DELETE语句,或者不返回任何内容,如SQL DDL语句的SQL语句。ResultSet executeQuery(String sql)
执行给定的SQL语句,该语句可能为SELECT
public class Demo01JDBC {
public static void main(String[] args) throws ClassNotFoundException {
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/day03", "root", "root");
//System.out.println(conn);com.mysql.jdbc.JDBC4Connection@28f67ac7
Statement stat = conn.createStatement();
//System.out.println(stat);//com.mysql.jdbc.StatementImpl@28f67ac7
int row = stat.executeUpdate("INSERT INTO products(pid, pname,price,flag,category_id) "+
"VALUES('p012','键盘',500,'1','c001');");
}
}
完整代码
public class Demo01JDBC {
public static void main(String[] args) throws ClassNotFoundException {
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/day03", "root", "root");
//System.out.println(conn);com.mysql.jdbc.JDBC4Connection@28f67ac7
Statement stat = conn.createStatement();
//System.out.println(stat);//com.mysql.jdbc.StatementImpl@28f67ac7
int row = stat.executeUpdate("INSERT INTO products(pid, pname,price,flag,category_id) "+
"VALUES('p012','键盘',500,'1','c001');");
//5.处理结果集
System.out.println(row);//1
//6.释放资源
stat.close();
conn.close();
}
}
创建JDBCUtils工具类并测试
创建JDBC工具类,工具类中的方法都是静态方法,方便直接通过类名使用
- 定义一个静态方法,获取Collection对象并返回
- 定义一个静态方法,释放资源
代码示例:JDBCUtils工具类创建
import java.sql.*;
public class JDBCUtils {
//定义4个静态的成员变量,用于存储数据库连接的相关信息
//注册驱动的地址
private static String driver = "com.mysql.jdbc.Driver";
//数据库的url地址
private static String url = "jdbc:mysql://localhost:3306/day03";
//数据库用户名
private static String user = "root";
//数据库的密码
private static String password = "root";
//静态代码块:优先执行,只执行一次
static {
//注册驱动
try {
Class.forName(driver);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
//定义一个静态方法,获取Collection对象并返回
public static Connection getConnection(){
Connection conn = null;
try {
//获取Connection对象并返回
conn = DriverManager.getConnection(url, user, password);
} catch (Exception e) {
/*
如果获取数据库连接对象失败,那么程序就没有必要继续执行了
所以可以把编译异常转换为运行时异常,让程序停止下来
*/
throw new RuntimeException("获取数据库连接对象失败"+e);
}
return conn;
}
//定义一个静态方法,释放资源
public static void close(ResultSet rs, Statement stat, Connection conn){
if(rs!=null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(stat!=null){
try {
stat.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
测试类
/*
测试JDBCUtils工具类
*/
public class Demo02testJDBCUtils {
public static void main(String[] args) {
//使用JDBCUtil工具类中的方法getConnection获取数据库连接对象
Connection conn = JDBCUtils.getConnection();
System.out.println(conn);//com.mysql.jdbc.JDBC4Connection@256216b3
}
}
使用JDBC技术对数据库进行操作
增删改
@Test
public void testInsert() {
//使用JDBCUtils工具类中的方法getConnection获取数据库连接对象
Connection conn = JDBCUtils.getConnection();
//获取执行者对象
Statement stat = null;
try {
stat = conn.createStatement();
//执行sql语句,获取结果
//增加数据
int row = stat.executeUpdate("INSERT INTO products(pid, pname,price,flag,category_id)"+
" VALUES('p014','鼠标',500,'1','c001'),('p015','鼠标',500,'1','c001');");
//修改数据
//int row = stat.executeUpdate("UPDATE products SET price = 7999 WHERE pid = 'p013';");
//删除数据
//int row = stat.executeUpdate("DELETE from products where pid in('p001','p002','p003');");
//处理结果
System.out.println(row+"行数据添加成功!");
} catch (SQLException e) {
e.printStackTrace();
} finally {
//释放资源
JDBCUtils.close(null,stat,conn);
}
}
查询
执行sql语句,获取结果集:
ResultSet executeQuery(String sql)
执行给定的SQL语句,该语句可能为SELECT
返回值:
java.sql.ResultSet是一个接口,返回的是ResultSet接口的实现类对象。
由mysql驱动提供,我们可以使用ResultSet接口来接收这个实现类对象(多态)
处理结果集,遍历结果集:和迭代器的使用方式一模一样
- ResultSet中有一个方法叫next判断有没有下一行数据;有返回true,没用返回false
boolean next()
将光标从当前位置向前移动一行。 - ResultSet中有一个方法叫getXXX(列的索引/列名)取出结果
int getInt(int columnIndex)
:列的索引,从1开始
int getInt(String columnLabel)
:列名
注意:数据库的列是什么类型,就用get类型的方法获取这个字段
也可以使用getObject
来获取所有类型的字段,返回值是Object类型
代码示例:
@Test
public void testSelect() throws SQLException {
//使用JDBCUtils工具类中的方法getConnection获取数据库连接对象
Connection conn = JDBCUtils.getConnection();
//获取执行者对象
Statement stat = conn.createStatement();
/*
执行sql语句,获取结果集
ResultSet executeQuery(String sql) 执行给定的SQL语句,该语句可能为SELECT
返回值:
java.sql.ResultSet是一个接口,返回的是ResultSet接口的实现类对象
由mysql驱动提供,我们可以使用ResultSet接口来接收这个实现类对象(多态)
*/
ResultSet rs = stat.executeQuery("select * from products;");
//System.out.println(rs);//com.mysql.jdbc.JDBC42ResultSet@3224f60b
/*
处理结果集,遍历结果集
和迭代器的使用方式一模一样
ResultSet中有一个方法叫next判断有没有下一行数据;有返回true,没用返回false
boolean next() 将光标从当前位置向前移动一行。
ResultSet中有一个方法叫getXXX(列的索引/列名)取出结果
int getInt(int columnIndex):列的索引,从1开始
int getInt(String columnLabel):列名
注意:数据库的列是什么类型,就用get类型的方法获取这个字段
也可以使用getObject来获取所有类型的字段,返回值是Object类型
*/
while(rs.next()){
/*String pid = rs.getString(1);
String pname = rs.getString(2);
int price = rs.getInt(3);
String flag = rs.getString(4);
String category_cid = rs.getString(5);*/
String pid = rs.getString("pid");
String pname = rs.getString("pname");
int price = rs.getInt("price");
String flag = rs.getString("flag");
String category_cid = rs.getString("category_id");
System.out.println(pid+"\t"+pname+"\t"+price+"\t"+flag+"\t"+category_cid);
}
//释放资源
JDBCUtils.close(rs,stat,conn);
}