JDBC的全称
Java DataBase Connection
JDBC的作用
Java代码中可以使用JDBC完成对数据库中的数据的操作!
JDBC的本质
是一个数据库厂商提供的可以对其数据库进行操作的工具类的集合,也就是一个jar包。
JDBC的使用
1.增加数据;
2.删除数据;
3.更新数据;
4.查询数据。
JDBC的流程
1.导入jdbc的jar包;
2.使用jdbc提供的类和方法完成数据库操作。
JDBC的使用流程
1.加载驱动;
2.获取连接对象;
3.创建SQL命令;
4.获取SQL命令对象;
5.运输车;
6.关闭资源;
***注:***通过以上流程总结,JDBC使用的流程是固定的,只是SQL语句不同。
JDBC增加数据
示例代码如下:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class TestAdd {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//1、加载数据库驱动 资源准备—>造桥资源
Class.forName(“oracle.jdbc.driver.OracleDriver”);//数据库厂商提供的操作数据的类的全限定路径
//2、创建数据库连接对象------>桥
Connection connection = DriverManager.getConnection(“jdbc:oracle:thin:@localhost:1521:XE”, “scott”, “oracle”);
//3、创建SQL命令--------->声明运输资源
String sql=“insert into dept values (60,‘sxt1’,‘shenzhen1’)”;
//4、创建Statement对象—>创建车
Statement stmt = connection.createStatement();
int i = stmt.executeUpdate(sql);
//5、关闭资源
stmt.close();
connection.close();
System.out.println(i);
}
}
JDBC更新数据
示例代码如下:
package com.bjsxt.update;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class TestUpdate {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//1、加载驱动
Class.forName(“oracle.jdbc.driver.OracleDriver”);
//2、获取连接对象
Connection connection = DriverManager.getConnection(“jdbc:oracle:thin:@localhost:1521:XE”, “scott”, “oracle”);
//3、创建sql命令
String dname=“bjsxt”;
String sql=“update dept set dname=’”+dname+"’ where deptno=50";
//4、获取SQL命令对象
Statement stmt = connection.createStatement();
//5、执行SQL命令
int i = stmt.executeUpdate(sql);
//6、关闭资源
stmt.close();
connection.close();
System.out.println(i);
}
}
JDBC删除数据
示例代码如下:
package com.bjsxt.delete;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class TestDelete {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//1、加载驱动
Class.forName(“oracle.jdbc.driver.OracleDriver”);
//2、获取连接对象
Connection connection = DriverManager.getConnection(“jdbc:oracle:thin:@localhost:1521:XE”, “scott”, “oracle”);
//3、创建SQL命令
String sql=“delete from dept where deptno=60”;
//4、获取SQL命令对象
Statement stmt = connection.createStatement();
//5、执行
int i = stmt.executeUpdate(sql);
//6、关闭资源
stmt.close();
connection.close();
System.out.println(i);
}
}
JDBC查询数据
示例代码如下:
package com.bjsxt.select;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import com.bjsxt.pojo.Dept;
public class TestStatementSelect {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//声明List集合
ArrayList list=new ArrayList<>();
//1、加载数据库驱动 资源准备—>造桥资源
Class.forName(“oracle.jdbc.driver.OracleDriver”);//数据库厂商提供的操作数据的类的全限定路径
//2、创建数据库连接对象------>桥
Connection connection = DriverManager.getConnection(“jdbc:oracle:thin:@localhost:1521:XE”, “scott”, “oracle”);
//3、创建SQL命令--------->声明运输资源
String sql=“select * from dept”;
//4、创建Statement对象—>创建车
Statement stmt = connection.createStatement();
//5、执行
ResultSet rs = stmt.executeQuery(sql);
//6、遍历读取
while(rs.next()){
Dept d=new Dept();
d.setDeptno(rs.getInt(“deptno”));
d.setDname(rs.getString(“dname”));
d.setLoc(rs.getString(“loc”));
list.add(d);
}
//7、关闭资源
rs.close();
stmt.close();
connection.close();
}
}
JDBC常见异常
1.驱动类加载失败:
(a):java.lang.ClassNotFoundException: oracle.jdbc.driver.OracleDriver2222
原因:驱动类的全限定路径没有书写正确。
解决:重新检查驱动类的全限定路径。
(b):java.lang.ClassNotFoundException: oracle.jdbc.driver.OracleDriver
原因:驱动包没有正确加载。
解决:查看是否导入jdbc的jar包并添加到编译路径中。
2.数据库的连接的URL地址不正确:
java.sql.SQLException: No suitable driver found for jdbc:oracle111:thin:@localhost:1521:XE
原因:数据库的URL地址不正确
解决:检查URL地址的正确性
3.用户名和密码不正确:
java.sql.SQLException: ORA-01017: invalid username/password; logon denied
原因:用户名和密码不正确
解决:检查用户和密码的正确性
4.SQL语句异常:
原因:检查SQL语句的有问题
解决:检查sql 语句的正确性或者百度ORA-编号查询解决方案。
JDBC的事务管理
问题:
在使用JDBC完成数据的增删改操作时发现,每条SQL语句在执行成功后,直接变现到数据库中了,而在真实业务场景中,一个完整的功能操作会同时涉及到多条SQL语句的执行,全部执行成功,才算该功能执行完毕,而按照常规的执行机制会造成,一条SQL语句虽然执行失败,但是执行成功的SQL语句会被变现到数据库中,造成数据混乱,比如:银行转账。
解决:
一个功能中涉及的数据库操作,只有全部执行成功后,才会将其变现到数据库中,只要有一个不成功,就回滚(返回)到初始状态。
功能实现:
JDBC事务管理
JDBC事务管理概念:
一个功能的完成处理就是一个事务。
示例代码如下(银行转账:事务管理案例):
package com.bjsxt.transation;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class TestTransation {
public static void main(String[] args) {
//声明JDBC变量
Connection connection=null;
Statement stmt=null;
try {
//1、加载驱动
Class.forName(“oracle.jdbc.driver.OracleDriver”);
//2、获取连接对象
connection = DriverManager.getConnection(“jdbc:oracle:thin:@localhost:1521:XE”, “scott”, “oracle”);
//开启事务管理:
connection.setAutoCommit(false);//设置事务手动提交
//3、创建sql命令
String sql1=“update t_account set money=money-1000 where aid=1”;
String sql2=“update t_account set money=money+1000 where aid=2”;
//4、获取SQL命令对象
stmt = connection.createStatement();
//5、执行SQL命令
int i1 = stmt.executeUpdate(sql1);
int i2 = stmt.executeUpdate(sql2);
System.out.println(i1+" "+i2);
//提交事务
connection.commit();
} catch (Exception e) {
try {
connection.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
e.printStackTrace();
}finally {
//6、关闭资源
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
JDBC的参数操作和功能抽取
参数操作:
将数据库操作的代码封装成功能方法,然后所需数据以形参的形式对外暴露。调用者传入实参即可,使用的是Statement,参数直接拼接在SQL语句上即可。
功能抽取:
因为大型项目中对数据库操作的功能方法是非常多的,为了提升代码的重用性,我们需要将功能方法再次向上抽取为功能类,只需要获取数据库操作的功能类调用其方法即可完成数据库操作。
抽取规则:
1.数据库层接口:
规范化功能类的方法的命名规范便于代码的交流使用便于代码的迭代升级以及多态调用;
2.实现接口完成相关数据库功能方法编写。
真实开发:
1.确定数据库接口:一般来说一张表对应一个接口操作。
包名:com.bjsxt.dao
接口名:XXXDao
2.实现接口完成数据库功能类的开发:完成对数据库的增删改查操作。
包名:com.bjsxt.dao.impl
类名:XXXDaoImpl
3.创建表的对应的实体类:
包名:com.bjsxt.pojo
类名:表明首字母大写
字段名即为属性名
JDBC的多表联合查询
实体类的设计:
1.一对一关系:
A表和B表是一对一,A类中拥有B类属性即可将传查询结果一部门封装A对象,一部门封装B对象,将B对象封装到A对象中即可。
2.一对多关系:
A表和B表是一对多,A类中拥有B类的集合属性即可。使用业务装配方式。
示例代码如下:
//查询员工及其部门信息
@Override
public List selDeptEmp() throws ClassNotFoundException, SQLException {
//创建集合存储结果数据
ArrayList list=new ArrayList<>();
//1、加载驱动
Class.forName(“oracle.jdbc.driver.OracleDriver”);
//2、获取连接
Connection connection = DriverManager.getConnection(“jdbc:oracle:thin:@localhost:1521:XE”, “scott”, “oracle”);
//3、创建SQL命令
String sql=" select * from dept d "+
" join emp e "+
" on d.deptno=e.deptno";
//4、创建SQL命令对象
Statement stmt=connection.createStatement();
//5、执行
ResultSet rs=stmt.executeQuery(sql);
//6、遍历
while(rs.next()){
//创建员工实体类对象
Emp emp=new Emp();
emp.setEmpno(rs.getInt(“empno”));
emp.setEname(rs.getString(“ename”));
emp.setJob(rs.getString(“job”));
emp.setMgr(rs.getInt(“mgr”));
emp.setHiredate(rs.getDate(“hiredate”));
emp.setSal(rs.getDouble(“sal”));
emp.setComm(rs.getDouble(“comm”));
emp.setDeptno(rs.getInt(“deptno”));
//创建部门实体类对象
Dept dept=new Dept();
dept.setDeptno(rs.getInt(“deptno”));
dept.setDname(rs.getString(“dname”));
dept.setLoc(rs.getString(“loc”));
//将部门存储到员工对象中
emp.setDept(dept);
//将员工存储到list集合中
list.add(emp);
}
//7、关闭资源
rs.close();
stmt.close();
connection.close();
//8、返回
return list;
}
JDBC中的preparedStatement对象
Statement对象的特点
1.好处:
每次都将SQL语句和数据拼接好后发送数据库执行,特别便于SQL语句和参数的拼接,还可以根据需求动态的拼接不同的数据。
2.缺点:
当同类型的SQL语句被多次执行时效率比较低。
3.使用:
加载驱动;
获取连接;
创建SQL命令(字符串拼接赋值);
获取Statement对象;
执行;
遍历(查询);
PreparedStatement对象
1.本质: 是Statement对象的子类。
2.好处: 执行效率高
3.缺点: 不便于SQL语句的拼接操作。
4.使用:
加载驱动;
获取连接;
创建SQL命令(使用?作为参数的占位符);
获取PreparedStatement对象(需要将SQL语句传入);
给占位符赋值(根据占位符的角标来确定,从左往右从1开始计数);
执行;
遍历(查询);
示例代码如下:
package com.bjsxt.preparedstatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
public class TestPreparedStatement {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//1、使用Statement对象
//useStatement();
//2、preparedStatement对象
usePreparedStatement();
}
//使用preparedStatement对象
private static void usePreparedStatement() throws ClassNotFoundException, SQLException {
//1、加载数据库驱动 资源准备—>造桥资源
Class.forName(“oracle.jdbc.driver.OracleDriver”);//数据库厂商提供的操作数据的类的全限定路径
//2、创建数据库连接对象------>桥
Connection connection = DriverManager.getConnection(“jdbc:oracle:thin:@localhost:1521:XE”, “scott”, “oracle”);
//3、创建SQL命令
String sql=“insert into dept values (?,?,?)”;
//4、获取PreparedStatement对象(SQL命令对象)
PreparedStatement ps=connection.prepareStatement(sql);
//给占位符赋值
ps.setInt(1, 62);
ps.setString(2, “sxt”);
ps.setString(3, “shenzhen”);
int i = ps.executeUpdate();
//给占位符赋值
ps.setInt(1, 63);
ps.setString(2, “sxt”);
ps.setString(3, “shenzhen”);
int i1 = ps.executeUpdate();
//给占位符赋值
ps.setInt(1, 64);
ps.setString(2, “sxt”);
ps.setString(3, “shenzhen”);
int i2 = ps.executeUpdate();
//给占位符赋值
ps.setInt(1, 65);
ps.setString(2, “sxt”);
ps.setString(3, “shenzhen”);
int i3 = ps.executeUpdate();
System.out.println(i);
}
//使用Statement对象
private static void useStatement() throws ClassNotFoundException, SQLException {
//1、加载数据库驱动 资源准备—>造桥资源
Class.forName(“oracle.jdbc.driver.OracleDriver”);//数据库厂商提供的操作数据的类的全限定路径
//2、创建数据库连接对象------>桥
Connection connection = DriverManager.getConnection(“jdbc:oracle:thin:@localhost:1521:XE”, “scott”, “oracle”);
//3、创建SQL命令--------->声明运输资源
String sql=“insert into dept values (60,‘sxt1’,‘shenzhen1’)”;
String sql1=“insert into dept values (70,‘sxt1’,‘shenzhen1’)”;
String sql2=“insert into dept values (80,‘sxt1’,‘shenzhen1’)”;
String sql3=“insert into dept values (90,‘sxt1’,‘shenzhen1’)”;
String sql4=“insert into dept values (99,‘sxt1’,‘shenzhen1’)”;
//4、创建Statement对象—>创建车
Statement stmt = connection.createStatement();
int i = stmt.executeUpdate(sql);
int i1 = stmt.executeUpdate(sql1);
int i2 = stmt.executeUpdate(sql2);
int i3 = stmt.executeUpdate(sql3);
int i4 = stmt.executeUpdate(sql4);
//5、关闭资源
stmt.close();
connection.close();
System.out.println(i+" “+i1+” “+i2+” “+i3+” "+i4);
}
}
JDBC的封装
package com.bjsxt.util;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
public class DBUtil {
private static String driver;
private static String url;
private static String username;
private static String password;
static{
//获取配置文件的读取流对象
InputStream is=DBUtil.class.getClassLoader().getResourceAsStream(“db.properties”);
//加载配置文件中数据参数信息并赋值给属性
//获取properties类型文件的操作对象
Properties p=new Properties();
//加载配置文件
try {
p.load(is);
driver=p.getProperty(“driver”);
url=p.getProperty(“url”);
username=p.getProperty(“username”);
password=p.getProperty(“password”);
//加载数据库驱动 资源准备
Class.forName(driver);//数据库厂商提供的操作数据的类的全限定路径
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
//获取连接对象
public static Connection getConntion(){
Connection conn=null;
try {
conn = DriverManager.getConnection(url,username,password);
} catch (Exception e) {
e.printStackTrace();
}
return conn;
}
//封装公共增删改方法
public static int executeDML(String sql,Object…objs){
//声明jdbc变量
Connection connection=null;
PreparedStatement ps=null;
try {
//2、创建数据库连接对象------>桥
connection = DriverManager.getConnection(url,username,password);
//3、开启事务管理
connection.setAutoCommit(false);
//4、创建PreparedStatement对象—>创建车
ps=connection.prepareStatement(sql);
//5、给占位符赋值
if(objs!=null){
for(int i=0;i<objs.length;i++){
ps.setObject(i+1, objs[i]);
}
}
//提交
int i=ps.executeUpdate();
connection.commit();
//6、执行
return i;
} catch (Exception e) {
//回滚
try {
connection.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
e.printStackTrace();
}finally {//关闭资源
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return -1;
}
//功能关闭资源
public static void closeAll(Connection conn,Statement stmt,ResultSet rs){
try {
if(rs!=null){
rs.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if(stmt!=null){
stmt.close()
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if(rs!=null){
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
JDBC的MVC开发思想
1.问题:
在使用JDBC完成功能实现时开发的代码书写思路:直接声明将数据的处理和数据库操作的代码全部声明在一起,会发现一个功能的实现包括两大块:数据的处理和数据库的操作。将代码全部声明在一起会出现极大的冗余。不同的功能会不会使用相同的业务逻辑处理?不同的业务逻辑处理会不会使用相同的数据库操作?
2.解决:
1、将业务处理的代码向上抽取成一个功能类,该类中声明该模块的业务逻辑处理方法,其他模块如果要使用相同的逻辑操作,直接调用即可;
2、将数据库操作相关的代码向上抽取,抽取成对应的功能类,只要涉及数据库操作的时候只需调用数据库层的代码即可。
3.功能实现: MVC的分层开发设计思想
4.内容:
M:model 模块 : service ,pojo,dao
V:View 视图 : jsp,HTML
C:controller 控制器层: com.bjsxt.controller
5.代码结构:
com.bjsxt.pojo 实体类
com.bjsxt.dao 数据库操作
com.bjsxt.dao.impl
com.bjsxt.service 业务处理
com.bjsxt.service.impl
com.bjsxt.controller 控制转发
6.特点:
1、提升代码的重用性,降低冗余;
2、代码的结构层次更加清晰,责任划分更加明确;
7.总结:
MVC其实就是功能开发的一个代码分层的思想。