JDBC(Java Database Connectivity)

**

一、JDBC基本概念

**
1.1 Java DataBase Connectivity(Java数据库连接)

通俗来讲,就是使用Java语言来操作数据库。

1.2 JDBC本质

JDBC其实就是一套操作所有关系型数据库的规则(接口)。
各个数据库厂商去实现这些接口,提供数据库驱动jar包
我们可以使用这套接口(JDBC)编程,但真正执行的代码是驱动jar包中的实现类。

JDBC的使用类似于使用多态创建对象,左边是接口,右边是接口的实现类。例如:

现有一个Person接口和一个Worker实现类,
// 创建实现类对象,左父右子,多态写法
Person p = new Worker();
//Person接口中有一个抽象方法eat,Worker重写了该方法,现在通过实现类对象调用该方法
//实际上调用的是Worker类中的eat方法
p.eat();

1.3 JDBC使用步骤

1)导入驱动jar包:mysql-connector-java-xxxx-bin.jar

1.复制jar包到项目的libs目录下(目录可以随便创建,此处名字设置为了libs,该目录也可以不创建,但是创建目录以后更便于管理)
2.右键点击libs目录,选择Add as Library(只有执行完该操作,才是真正将jar包加入到项目中)

2)注册驱动
3)获取数据库连接对象 Connection

这就是本地Java代码和数据库之间的桥梁

4)定义sql语句
5)获取执行sql语句的对象:Statement
6)执行sql,接收返回的结果
7)处理结果
8)释放资源

**

二、JDBC中的接口和类

**
2.1 DriverManger:驱动管理对象

1)注册驱动:即告诉程序该用哪一个数据库驱动jar包

static void registerDriver(Driver driver):注册与给定的驱动程序 DriverManger。
写代码使用:Class.forName("com.mysql.jdbc.Driver");
通过查看源码发现:在com.mysql.jdbc.Driver类中存在静态代码块
    static {
        try {
            DriverManager.registerDriver(new Driver());
        } catch (SQLException var1) {
            throw new RuntimeException("Can't register driver!");
        }
    }

所以,通过Class.forName将com.mysql.jdbc.Driver类文件加载进内存,类文件中的静态代码块会随着类的加载而执行,而且只执行一次,即DriverManager.registerDriver方法执行一次,实现注册驱动功能。

2)获取数据库连接

方法:static Connection getConnection(String url, String user, String password)
参数:
    String url:指定连接的路径
        语法:不同数据库写法会有不同
            MySQl数据库:jdbc.mysql://IP地址(域名):端口号/数据库名称
            例如:jdbc:mysql://localhost:3306/db3
            备注:
                1.ip地址可以找到计算机,端口号可以找到计算机上安装的mysql服务器
                2.如果连接的是本机mysql服务器,并且mysql服务默认端口是3306,则url可以简写为:
                   jdbc:mysql:///数据库名称
    String user:用户名
    String password:密码

2.2 Connection:数据库连接对象

1)获取执行sql的对象

Statement CreateStatement()
PreparedStatement prepareStatement(String sql)

2)管理事务

开启事务:void setAutoCommit(boolean autoCommit)
    调用该方法设置参数为false,即开启事务。(关闭了自动提交,就是手动提交了)
提交事务:void commit()
回滚事务:void rollback()

2.3 Statement:执行sql的对象

1)执行sql

1.boolean execute(String sql):可以执行任意的sql,该方法使用的并不多,了解即可。
2.int executeUpdate(String sql):
    执行DML(INSERT、DELETE、UPDATE,增删改表中的数据)语句(常用),
    也可以执行DDL(CREATE、DROP、ALTER增删改数据库和表)语句(不常用)

    返回值是影响的行数,可以通过这个行数判断DML语句是否执行成功:
        返回值 > 0 表示执行成功;反之,执行失败。
3.ResultSet executeQuery(String sql):执行DQL(SELECT,查看表中的数据)语句

2.4 ResultSet:结果集对象

结果集对象就是封装查询结果的对象。

1)方法

1.boolean next():游标向下移动一行,并判断当前行是否是最后一行末尾,即判断是否有数据。
    返回值是一个布尔类型:
        如果是最后一行,返回false;
        如果不是最后一行,返回true。
        即如果是false,就代表没有数据了。
2.getXxx():获取数据
    Xxx:代表数据类型,例如:
        id是int类型,对应使用getInt(),可以封装int类型的数据
        name是varchar类型,对应使用的就是getString(),可以封装String类型的数据
        balance是double,对应的就使用getDouble(),可以封装double类型的数据
    参数:
        int:代表列的编号(注意区别于索引,编号是从1开始的)。例如getDouble(3)获取的是第3列的数据,即balance
        String:代表列名称。例如getDouble("balance")
        备注:
            这就是getDouble()方法的重载形式,可以传递int类型的编号,也可以传递String类型的列名称

2)使用步骤

1.游标向下移动一行,因为游标默认的位置是在表头的一行,下一行才是第一行数据
2.判断是否有数据
3.获取数据

2.5 PreparedStatement:执行sql的对象(重点)

1)SQL注入问题

SQL注入是指在拼接sql时,有一些sql的特殊关键字参与字符串的拼接,会造成安全性问题。例如:

随意输入一个用户名:sgdf
输入密码:a' or 'a' = 'a
发现,竟然登录成功了。
打印出的sql语句:SELECT * FROM user WHERE username = 'sgdf' AND PASSWORD = 'a' or 'a' = 'a';
    username = 'sgdf' --> false
    PASSWORD = 'a' --> false
    'a' = 'a'; --> true
    最终结果为true,所以会查询出所有的数据。

2)如何解决SQL注入问题?

使用PreparedStatement对象来解决。

Statement对象执行的是静态的SQL,静态的sql表示所有的参数在生成sql的时候,都是拼接好的,即用户名和密码传入以后,sql语句就直接生成了

静态sql容易产生SQL注入的问题

PreparedStatement对象执行的是预编译的sql,参数使用占位符(?)代替。

3)使用步骤

1.导入驱动jar包
2.注册驱动
3.获取连接对象Connection
4.定义sql
    注意:sql的参数使用?作为占位符。例如:SELECT * FROM user WHERE username = ? AND PASSWORD = ?;
5.获取执行对象PreparedStatement对象。
    调用Connection中的方法:Connection.preparedStatement(String sql)
    注意:
        1.Connection.createStatement(),方法不需要传递参数
        2.Connection.preparedStatement(String sql),该方法需要传递参数
6.给?赋值
    1.使用PreparedStatement对象中的方法:setXxx(location, value);
        location:表示?的位置(编号),从1开始
        value:表示?的值
7.执行sql,接收返回结果,不需要传递sql语句,因为在获取对象的时候已经将sql语句传入了
8.处理结果
9.释放资源

一般建议使用PreparedStatement来完成DML(增删改)操作,因为:

1.可以防止SQL注入
2.效率更高

**

三、抽取JDBC工具类:JDBCUtils

**

3.1 目的

为了简化书写,因为注册驱动,获取数据库连接,释放资源这些代码每次写都是一样的

3.2 如何抽取?

哪些代码重复度比较高,就抽取哪些代码

1.注册驱动也抽取,但是一般不会抽取到一个方法中
2.抽取一个方法获取数据库连接对象
    需求:不想传递参数(因为太繁琐),还可以保证工具类的通用性
    解决方案:通过配置文件解决(使用配置文件是非常常用的一种方法)
        jdbc.properties
            url=
            user=
            password=
        这样随时可以修改配置文件,但是代码不需要修改。
3.抽取一个方法释放资源

**

四、JDBC控制事务

**
4.1 事务的概念

一个包含多个步骤的业务操作,如果这个业务被事务管理,那么这些步骤要么同时成功,要么同时失败。

4.2 事务的操作

1.开启事务:start transaction
2.提交事务:commit
3.回滚事务:rollback

4.3 使用Connection对象管理事务

1.开启事务:void setAutoCommit(boolean autoCommit)
    调用该方法设置参数为false,即开启事务。(关闭了自动提交,就是手动提交了)
2.提交事务:void commit()
3.回滚事务:void rollback()

**

六、配置文件

**
配置文件中很多变量是经常改变的,通过修改配置文件,可以让用户脱离程序去修改相关的变量设置。

Python支持的配置文件是.ini文件,同样,也有读取配置文件的类ConfigParse,可以通过该类的方法来修改.ini配置文件

Java的配置文件常为.properties文件,格式为文本文件,JDK内置的java.util.Properties类支持.properties文件的读写。

你可能感兴趣的:(Java,java,数据库,开发语言)