JDBC详解

目录

1.JDBC简介

二、JDBC的编码步骤

三 JDBC代码实现

3.1 注册驱动,获取连接,完成查询操作

3.2 创建statement或者preparedstatement接口,来执行SQL语句:

使用statement接口:

使用preparedstatement接口:

四 JDBC中常用接口或类详解

Statement类讲解:

ResultSet类讲解:

数据库的URL:

五 事务

事务概述

事务的特性

事务的隔离级别:

六 工具类配置


1.JDBC简介

JDBC:Java DataBase Connectivity

数据JavaEE开发技术之一

相关的API在JDK中:java.sql.*   javax.sql.*

作用:编写数据库相关代码有一个统一标准

还需要数据库的驱动

二、JDBC的编码步骤

0、搭建开发环境:把数据库驱动jar包加入到应用的构建路径(classpath)

需要的jar包https://download.csdn.net/download/mocas_wang/12430202

1、注册驱动

2、获取与数据库的连接

3、创建代表SQL语句的对象

4、执行SQL语句

5、如果执行的查询语句,返回结果集,遍历结果集

6、释放占用的资源

三 JDBC代码实现

3.1 注册驱动,获取连接,完成查询操作

/*1 准备四大参数*/
String driveClassName="com.mysql.jdbc.Driver";
/*jdbc的格式有规范,固定格式,但数据库是自己创建的//jdbc协议:子协议://ip:端口号/数据库名*/
String url = "jdbc:mysql://localhost:3306/mysql2?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=UTC";//数据库自己创建,使用这个长字符串可以一劳永逸解决版本问题
//数据库用户名
String name = "root";//将要连接数据库的账户
String password = "*****";//将要连接数据库的密码

/*2 加载驱动类*/
Class.forName(driveClassName);
/* 3 利用DriverManager 得到connection*/
Connection con= DriverManager.getConnection(url,name,password);

/*
* 完成查询*/
/*1 通过connection创建statement*/
Statement stmt=con.createStatement();
/*2 调用statement的ResultSet rs=stmt.executeQuery()*/
ResultSet rs=stmt.executeQuery("select * from tb_stu");
System.out.println(rs);
/*3 解析ResultSet查询结果集*/
/*循环结果集,不断使用rs.next指向下一行*/
while (rs.next())
{
  String number=rs.getString(1);//列索引
  String ename=rs.getString("name");//列标签索引
  int age=rs.getInt(3);
  System.out.println(number+","+ename+","+age);


}

/*
* 关闭资源
* */

rs.close();
stmt.close();
con.close();

3.2 创建statement或者preparedstatement接口,来执行SQL语句:

使用statement接口:

statement接口创建完成后,可以执行SQL语句,对数据库的增删改查,其中查略显麻烦。在statement中使用字符串拼接的方式,该方式存在句法复杂容易出错的缺点,所以statement在实际使用中用的非常少。

字符串拼接方式的SQL语句是非常繁琐的,中间有很多的单引号,双引号极易出错。

Statement s = conn.createStatement();
//准备SQL语句
//注意:' 字符串要用单引号 '
String sql = "insert into t_course values (null,"+"'数学')";
//在Statement中使用字符串拼接的方式,存在诸多的问题
s.execute(sql);
System.out.println("执行插入语句成功!");

使用preparedstatement接口:

与statement一样,preparedStatement也是执行SQL的,不过需要根据SQL语句创建preparedstatement。除此之外,还能够通过设置参数来指定相应的值,而不是statement那样进行字符串的拼接。

 /*1 得到连接对象*/
Connection con=jdbcUtils.getConnection();
/*2 给出sql模板,创建pstmt*/
String sql="update account set balance=balance+? where name=?";
 PreparedStatement pstmt=con.prepareStatement(sql);
/*3 对参数赋值*/
pstmt.setDouble(1,balance);
pstmt.setString(2,ename);
 /*4 执行*/
pstmt.executeUpdate();

四 JDBC中常用接口或类详解

Statement类讲解:

Jdbc程序中的Statement对象用于向数据库发送SQL语句, Statement对象常用方法:
Ø executeQuery(String sql) :用于向数据发送查询语句。 Ø executeUpdate(String sql):用于向数据库发送insert、update或delete语句 Ø execute(String sql):用于向数据库发送任意sql语句 Ø addBatch(String sql) :把多条sql语句放到一个批处理中。 Ø executeBatch():向数据库发送一批sql语句执行。

ResultSet类讲解:

l Jdbc程序中的ResultSet用于代表Sql语句的执行结果。Resultset封装执行结果时,采用的类似 于表格的方式。ResultSet 对象维护了一个指向表格数据行的游标,初始的时候,游标在第一 行之前,调用ResultSet.next() 方法,可以使游标指向具体的数据行,进行调用方法获取该行 的数据。
l ResultSet既然用于封装执行结果的,所以该对象提供的都是用于获取数据的get方法: l 获取任意类型的数据 : Ø getObject(int index) Ø getObject(string columnName) l 获取指定类型的数据 : Ø getString(int index) Ø getString(String columnName)

ResultSet还提供了对结果集进行滚动的方法:
Ø next():移动到下一行
Ø Previous():移动到前一行
Ø absolute(int row):移动到指定行
Ø beforeFirst():移动resultSet的最前面。
Ø afterLast() :移动到resultSet的最后面。

数据库的URL:

URL用于标识数据库的位置,通过URL地址告诉JDBC程序连接哪个数据库,URL的写法为:
依次为 : 协议 + 子协议 + 主机:端口 + 数据库 + 参数
常用数据库URL地址的写法:
Ø Oracle写法:jdbc:oracle:thin:@localhost:1521:sid Ø SqlServer写法:jdbc:microsoft:sqlserver://localhost:1433; DatabaseName=sid Ø MySql写法:jdbc:mysql://localhost:3306/sid
如果连接的是本地的Mysql数据库,并且连接使用的端口是3306 那么的url地址可以简写为: jdbc:mysql:///数据库

常用的url:jdbc:mysql://localhost:3306/mysql2?useUnicode=true&characterEncoding=utf8

jdbc:mysql://localhost:3306/mysql2?seUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&se

客户端与数据库所有的交互都是通过 Connection 来完成的。
常⽤的⽅法:
//创建向数据库发送sql的statement对象。
createcreateStatement()
//创建向数据库发送预编译sql的PrepareSatement对象。
prepareStatement(sql)
//创建执⾏存储过程的callableStatement对象
prepareCall(sql)
//设置事务⾃动提交
setAutoCommit(boolean autoCommit)
//提交事务
commit()
//回滚事务
rollback()

JDBC使⽤的⼀些细节

1.PreparedStatement 对象
PreparedStatement 对象继承 Statement 对象,它⽐ Statement 对象更强⼤,使⽤起来更简单
1. Statement 对象编译 SQL 语句时,如果 SQL 语句有变量,就需要使⽤分隔符来隔开,如果变量⾮常
多,就会使 SQL 变得⾮常复杂。 PreparedStatement 可以使⽤占位符,简化 sql 的编写
2. Statement 会频繁编译 SQL PreparedStatement 可对 SQL 进⾏预编译,提⾼效率,预编译的
SQL 存储在 PreparedStatement 对象中
3. PreparedStatement 防⽌ SQL 注⼊ 。【 Statement 通过分隔符 '++', 编写永等式,可以不需要密码
就进⼊数据库】
//模拟查询id为2的信息
 String id = "2";
 Connection connection = UtilsDemo.getConnection();
 String sql = "SELECT * FROM users WHERE id = ?";
 PreparedStatement preparedStatement =
connection.preparedStatement(sql);
 //第⼀个参数表示第⼏个占位符【也就是?号】,第⼆个参数表示值是多少
 preparedStatement.setString(1,id);
 ResultSet resultSet = preparedStatement.executeQuery();
2.批处理
当需要向数据库发送⼀批SQL语句执⾏时,应避免向数据库⼀条条发送执⾏,采⽤批处理以提升执⾏效
率
批处理有两种⽅式:
1. Statement
2. PreparedStatement
通过executeBath()⽅法批量处理执⾏SQL语句,返回⼀个int[]数组,该数组代表各句SQL的返回值
以下代码是以Statement⽅式实现批处理
 if (resultSet.next()) {
 System.out.println(resultSet.getString("name"));
 }
 //释放资源
 UtilsDemo.release(connection, preparedStatement, resultSet);
2. 批处理
当需要向数据库发送⼀批 SQL 语句执⾏时,应避免向数据库⼀条条发送执⾏, 采⽤批处理以提升执⾏效
批处理有两种⽅式:
1. Statement
2. PreparedStatement
通过 executeBath() ⽅法批量处理执⾏ SQL 语句,返回⼀个 int[] 数组,该数组代表各句 SQL 的返回值
/*
 * Statement执⾏批处理
 *
 * 优点:
 * 可以向数据库发送不同的SQL语句
 * 缺点:
 * SQL没有预编译
 * 仅参数不同的SQL,需要重复写多条SQL
 * */
 Connection connection = UtilsDemo.getConnection();
 Statement statement = connection.createStatement();
 String sql1 = "UPDATE users SET name='zhongfucheng' WHERE id='3'";
 String sql2 = "INSERT INTO users (id, name, password, email,
birthday)" +
 " VALUES('5','nihao','123','ss@qq.com','1995-12-1')";
 //将sql添加到批处理
 statement.addBatch(sql1);
 statement.addBatch(sql2);
 //执⾏批处理
 statement.executeBatch();
 //清空批处理的sql
 statement.clearBatch();
 UtilsDemo.release(connection, statement, null);

以下⽅式以PreparedStatement⽅式实现批处理

/*
 * PreparedStatement批处理
 * 优点:
 * SQL语句预编译了
 * 对于同⼀种类型的SQL语句,不⽤编写很多条
 * 缺点:
 * 不能发送不同类型的SQL语句
 *
 * */
 Connection connection = UtilsDemo.getConnection();
 String sql = "INSERT INTO test(id,name) VALUES (?,?)";
 PreparedStatement preparedStatement =
connection.prepareStatement(sql);
 for (int i = 1; i <= 205; i++) {
 preparedStatement.setInt(1, i);
 preparedStatement.setString(2, (i + "zhongfucheng"));
 //添加到批处理中
 preparedStatement.addBatch();
 if (i %2 ==100) {
 //执⾏批处理
 preparedStatement.executeBatch();
 //清空批处理【如果数据量太⼤,所有数据存⼊批处理,内存肯定溢出】
 preparedStatement.clearBatch();
 }
 }
 //不是所有的%2==100,剩下的再执⾏⼀次批处理
 preparedStatement.executeBatch();
 //再清空
 preparedStatement.clearBatch();
 UtilsDemo.release(connection, preparedStatement, null);

五 事务

事务概述

1、MySQL:事务默认是自动提交的。即一条语句就是出于独立的事务之中。

2、MySQL:SQL(TPL)

start transaction:开启事务。后面的语句处于同一个事务之中。

rollback:回滚。事务结束

commit:提交事务。事务结束

事务的特性

1、原子性:原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。 

2、一致性:事务必须使数据库从一个一致性状态变换到另外一个一致性状态。比如转账:转账前aaa+bbb=2000;转账后aaa+bbb=2000;

3、隔离性:事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离。

4、持久性:指一个事务一旦被提交,它对数据库中数据的改变就是永久性的。

事务的隔离级别:

1、如果不考虑事务的隔离性,会出现什么问题?

脏读:一个线程中的事务读到了另一个线程中事务未提交的数据

例⼦: A B 转账, A 执⾏了转账语句,但 A 还没有提交事务, B 读取数据,发现⾃⼰账户钱变多了 B
A 说,我已经收到钱了。 A 回滚事务【 rollback 】,等 B 再查看账户的钱时,发现钱并没有多。
 

不可重复读:一个线程中的事务读到了另一个线程中提交的update的数据,前后两次读到的内容不一致。

注: A 查询数据库得到数据, B 去修改数据库的数据,导致 A 多次查询数据库的结果都不⼀样【危害: A
每次查询的结果都是受 B 的影响的,那么 A 查询出来的信息就没有意思了】
 

虚读:一个线程中的事务读到了另一个线程中提交的insert或delete的数据,前后读到的记录条数不一致。

注: 和不可重复读类似,但虚读 ( 幻读 ) 会读到其他事务的插⼊的数据,导致前后读取不⼀致
 
简单总结: 脏读是不可容忍的,不可重复读和虚读在⼀定的情况下是可以的【做统计的肯定就不⾏】

2、事务的隔离级别:

READ UNCOMMITTED  脏读、不可重复读、虚读都有可能发生

READ COMMITTED 能避免脏读;不可重复读、虚读有可能发生(Oracle默认)

REPEATABLE READ 能避免脏读、不可重复读;虚读有可能发生(MySQL默认)

SERIALIZABLE 能避免脏读、不可重复读、虚读的发生

以上隔离级别:从上到下,级别越高,性能越低,数据也越安全。

优化代码:

Connection con=null;
/*对事务的处理必须使用connection对象*/
try {
    /*开启事务
    * .....
    * 提交事务
    * */
    //开启连接
    con=jdbcUtils.getConnection();
    //开启事务
    con.setAutoCommit(false);
    /*处理.......*/
    accountDao dao=new accountDao();
    dao.updateBalance(con,from,-money);//转出金额
    dao.updateBalance(con,to,+money);

    //提交事务
    con.commit();
    con.close();
}
catch (Exception e)
{
    /*要回滚事务*/
    con.rollback();
    con.close();
    throw new RuntimeException(e);
}

六 工具类配置

上文多次用到了配置jdbcUtils工具类,源码如下

1 dbconfig.properties配置,此文件的配置路径在项目下

driveClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mysql2?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=UTC
name =root
password=wyh124413

2.jdbcUtils类

package commit;

import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;

/**
 * Created with IntelliJ IDEA
 *
 * @Author: mocas
 * @Date: 2020/5/17 14:29
 * @email: wangyuhang_mocas@163.com
 */
public class jdbcUtils {

    private static Properties pro=null;

    static {
        try {
            /*1 加载配置文件*/
            InputStream in= jdbcUtils.class.getClassLoader().getResourceAsStream("dbconfig.properties");

            pro=new Properties();
            pro.load(in);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        /*2 加载驱动类*/
        try {
            Class.forName(pro.getProperty("driveClassName"));
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
    }

    /*获取连接*/
    public static Connection getConnection() throws IOException, ClassNotFoundException, SQLException {


        /*3 得到connection*/
        return DriverManager.getConnection(pro.getProperty("url"),pro.getProperty("name"),pro.getProperty("password"));

    }
}

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值