jdbc01

JDBC概述

​ JDBC(Java DataBase Connectivity):java连接数据库技术,是一项由sun(java创始公司)发布的用于java连接数据库的通用标准,这套标准由一系列的接口(Connection,Statement,ResultSet等)构成,旨在屏蔽不同数据库之间的差异,使得开发者无需关注不同数据库系统之间的差异,简化java连接数据库的步骤。

早期的连接方式如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3ki1dzhd-1613532776624)(assets/1565575778207.png)]

应用程序开发者需要关注不同数据库的连接方式,使得开发连接数据库的程序难度增大。因此JDBC标准只提供一套连接标准,由不同的数据库产商实现这套标准,从而简化开发者的开发难度:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-K6D00e9S-1613532776629)(assets/1565575872807.png)]

JDBC操作数据库步骤

JDBC操作数据库通常分为六个通用步骤:

  1. 加载驱动(JDBC4之后可以省略,需要导入相关数据库的驱动包)
  2. 获取连接
  3. 获取执行sql命令的对象
  4. 执行
  5. 处理结果
  6. 关闭资源

导入驱动包

由于连接数据库的具体驱动由不同数据库产商实现,因此,在连接对应数据库时需要提供不同数据库的驱动包:

  • mysql:mysql-connector-java-X.X.XX-bin.jar
  • sqlserver:sqljdbcXX.jar
  • oracle:ojdbcXX.jar

以mysql为例:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pfbSGWeE-1613532776632)(assets/1565600901118.png)]

案例如下:

//1.加载驱动(驱动数据库:有三种方式,常用反射加载)
Class.forName("com.mysql.jdbc.Driver");

//2.获取连接对象(建立从java到数据库的连接通道)
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "123456");

//3.获取处理命令的对象(通过连接对象向数据库发送并执行sql语句)
Statement stat = conn.createStatement();

//4.执行sql操作
boolean f = stat.execute("insert into dept values(7,'事业部','10986')"); // false

//5.处理结果
if(f){
    System.out.println("执行查询操作");
}else{
    System.out.println("执行非查询操作");
}

//6.资源关闭
stat.close();
conn.close();

execute方法详解

Statement接口主要用于执行sql语句对象,内部包含一些执行方法:

  • execute():用执行所有的sql语句,对于有结果集的sql会返回true,否则返回false
  • executeUpdate():用于执行DML语句中的更新语句(insert,delete,update),返回结果为影响的数据行数
  • executeQuery():用于执行查询语句(select),返回一个ResultSet(结果集)对象,内部存储的为查询的数据

基本CRUD操作

参考数据库表:

create table dept
(
dno int primary key auto_increment,
dname varchar(30),
tel varchar(16)
)

insert操作

//1.加载驱动(驱动数据库:有三种方式,常用反射加载)
Class.forName("com.mysql.jdbc.Driver");
//2.获取连接对象(建立从java到数据库的连接通道)
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "123456");
//3.获取处理命令的对象(通过连接对象向数据库发送并执行sql语句)
//Statement stat = conn.createStatement();
String sql = "insert into dept(dno,dname,tel) values(8,'市场部','10786')";
PreparedStatement ps = conn.prepareStatement(sql);
//4.执行sql操作
//int i = stat.executeUpdate("insert into dept(dno,dname,tel) values(8,'市场部','10786')");
int i = ps.executeUpdate();
//5.处理结果
if(i){
    System.out.println("执行成功,影响数据行数:"+i);
}
//6.资源关闭
stat.close();
conn.close();

delete操作

//1.加载驱动(驱动数据库:有三种方式,常用反射加载)
Class.forName("com.mysql.jdbc.Driver");
//2.获取连接对象(建立从java到数据库的连接通道)
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "123456");
//3.获取处理命令的对象(通过连接对象向数据库发送并执行sql语句)
//Statement stat = conn.createStatement();
String sql = "delete from dept where dno=1";
PreparedStatement ps = conn.prepareStatement(sql);
//4.执行sql操作
//int i = stat.executeUpdate("delete from dept where dno=1");
int i = ps.executeUpdate();
//5.处理结果
if(i>0){
    System.out.println("执行成功,影响数据行数:"+i);
}
//6.资源关闭
stat.close();
conn.close();

update操作

//1.加载驱动(驱动数据库:有三种方式,常用反射加载)
Class.forName("com.mysql.jdbc.Driver");
//2.获取连接对象(建立从java到数据库的连接通道)
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "123456");
//3.获取处理命令的对象(通过连接对象向数据库发送并执行sql语句)
//Statement stat = conn.createStatement();
String sql = "update dept set tel='123456' where dno=2";
PreparedStatement ps = conn.prepareStatement(sql);
//4.执行sql操作
//int i = stat.executeUpdate("update dept set tel='123456' where dno=2");
int i = ps.executeUpdate();
//5.处理结果
if(i>0){
    System.out.println("执行成功,影响数据行数:"+i);
}
//6.资源关闭
stat.close();
conn.close();

select操作

//1.加载驱动(驱动数据库:有三种方式,常用反射加载)
Class.forName("com.mysql.jdbc.Driver");
//2.获取连接对象(建立从java到数据库的连接通道)
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "123456");
System.out.println(conn);
//3.获取处理命令的对象(通过连接对象向数据库发送并执行sql语句)
//Statement stat = conn.createStatement();
String sql = "select dname as name,dno as no,tel as phone from dept";
PreparedStatement ps = conn.prepareStatement(sql);
//4.执行sql操作(查询)
//ResultSet rs = stat.executeQuery("select dname as name,dno as no,tel as phone from dept");
ResultSet rs = ps.executeQuery();
//5.处理结果
while(rs.next()){
    //已经获取一行数据
    String name = rs.getString("name");
    int no = rs.getInt("no");
    String tel = rs.getString("phone");
    System.out.println(no+"/"+name+"/"+tel);
}
//6.资源关闭
stat.close();
conn.close();

Statement & PreparedStatement

​ Statement是由JDBC接口提供的一个用于执行静态SQL语句的接口,但是通过Statement执行SQL语句时,会存在SQL注入的风险,因此JDBC还提供了另一个接口PreparedStatement,用于解决这一问题,使用PreparedStatement对象可以对sql语句预编译,从而防止sql注入。

//准备sql语句
String sql = "select * from emp where eno=?";
//获取连接
Connection conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mydb", "root", "123456");
//对SQL语句预处理(编译)并获取预处理对象
PreparedStatement ps = conn.prepareStatement(sql);
ps.setObject(1, 1001);
//执行查询
ResultSet rs = ps.executeQuery();
if(rs.next()){
    int no = rs.getInt("eno");
    String name = rs.getString("ename");
    BigDecimal sal = rs.getBigDecimal("sal");
    Date date = rs.getDate("hiredate");//java.sql.Date
    int dno = rs.getInt("dno");
    System.out.println(no+"/"+name+"/"+sal+"/"+date+"/"+dno);
}else{
    System.out.println("未查询到数据");
}
//关闭资源
rs.close();
ps.close();
conn.close();

getGeneratedKeys

​ 在执行某些插入语句时,由于数据库表的某些列设置过自动生成(主键列),因此使用JDBC代码执行插入操作时,也能同时获取被插入的数据自动生成的列值;这里需要在调用prepareStatement方法时,除了传入sql语句外,还需要传入一个参数:Statement.RETURN_GENERATED_KEYS,以表示要获取返回的自动生成的列值(主键)。

具体操作如下:

String sql = "insert into users(username,password,phone,status) values(?,?,?,?)";

Connection conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mydb", "root", "123456");

//获取预处理命令的对象,并且指示需要获取自动生成的键
PreparedStatement ps = conn.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS);
ps.setString(1, "hanmeimei");
ps.setString(2, "h123");
ps.setString(3, "10086");
ps.setInt(4, 1);
//执行更新
int i = ps.executeUpdate();
//获取包含了自动产生键的结果集
ResultSet rs = ps.getGeneratedKeys();
//将游标指针下移一次(否则无法获取数据)
rs.next();
//获取生成的主键值
int id = rs.getInt(1);
if(i>0){
    System.out.println("数据插入成功,ID:"+id);
}
//关闭资源
rs.close();
ps.close();
conn.close();

DBUtils封装(一)

通过对JDBC操作数据库的学习,我们会发现,由于JDBC操作数据库的步骤基本没有大的变化,针对所有的数据访问操作,都会存在大量重复代码,因此,对操作数据库的步骤封装就显得十分有必要了,如下:

准备属性文件

为了不用修改java源代码,可以将连接数据库的常见字符串直接配置到properties文件中:

jdbc.properties

#mysql connection config
driverClass=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/mydb
user=root
password=123456

#mssqlserver connection config
#driverClass=com.miscrosoft.jdbc.sqlserver.SQLServerDriver
#url=jdbc:sqlserver://127.0.0.1:1433;databaseName=test
#user=sa
#password=123456

#oracle connection config
#driverClass=oracle.jdbc.driver.OracleDriver
#url=jdbc:oracle:thin:@127.0.0.1:1521:orcl
#user=scott
#password=tiger

封装DBUtils

import java.io.*;
import java.sql*;
import java.util.*;

/**
 * 自己封装的数据库工具类,包含一些操作数据库的简便方法
 * 1. 获取连接
 * 2. 关闭资源
 * 3. 封装通用增删改操作
 * @author mrchai
 */
public class DBUtils {

    public static String driverClass;
    public static String url;
    public static String user;
    public static String password;


    static{
        try {
            Properties prop = new Properties();
            //加载属性文件
            prop.load(new FileInputStream("src/jdbc.properties"));
            //获取属性信息(连接数据库的相关字符串)
            driverClass = prop.getProperty("driverClass");
            url = prop.getProperty("url");
            user = prop.getProperty("user");
            password = prop.getProperty("password");

            //加载驱动
            Class.forName(driverClass);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    /**
	 * 获取连接
	 * @return
	 */
    public static Connection getConn(){
        try {
            return DriverManager.getConnection(url, user, password);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
	 * 关闭资源
	 * @param rs
	 * @param stat
	 * @param conn
	 */
    public static void close(ResultSet rs,Statement stat,Connection conn){
        try {
            if(rs != null){
                rs.close();
            }
            if(stat != null){
                stat.close();
            }
            if(conn != null){
                conn.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    /**
	 * 封装通用的增、删、改操作(针对任何数据库表的更新操作(DML语句)都能通过该方法实现)
	 * @param sql
	 * @return
	 */
    public static int exeUpdate(String sql,Object... params){
        Connection conn = null;
        PreparedStatement ps = null;
        try {
            //获取连接
            conn = getConn();
            //编译sql语句获取预处理对象
            ps = conn.prepareStatement(sql);
            if(Objects.nonNull(params)){				
                for(int i = 0;i<params.length;i++){
                    ps.setObject(i + 1, params[i]); 
                }
            }
            //执行更新
            int i = ps.executeUpdate();
            return i;
        } catch (SQLException e) {
            e.printStackTrace();
        }finally{
            close(null, ps, conn); 
        }
        return 0;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值