18.数据库操作

本文介绍了数据库的基础知识,包括数据库的定义、种类和功能,重点讲解了SQL语言的构成。接着,深入探讨了JDBC技术,包括JDBC-ODBC桥、JDBC技术及其驱动程序类型。详细阐述了JDBC中Connection、Statement、PreparedStatement、DriverManager和ResultSet等关键接口和类的使用,以及如何进行数据库连接、SQL语句执行和结果集处理。最后,给出了数据库操作的实践案例,涉及连接数据库、发送SQL语句、处理查询结果等常见操作。
摘要由CSDN通过智能技术生成

18.数据库操作

数据库系统是由数据库、数据库管理系统和应用系统、数据库管理员构成。

数据库管理系统简称DBMS,是数据库系统的关键组成部分,包括数据库定义、数据查询、数据维护等。

而JDBC技术是连接数据库和应用程序的纽带。

18.1数据库基础知识

如今现在常用的高级数据库有SQL Server、MySQL、Oracle等。

18.1.1什么是数据库

数据库是一种存储接口,允许使用各种格式输入、处理和检索数据。主要特点如下:

1.数据共享。所有用户可同时存取数据库中数据。

2.减少数据冗余度。相比文件系统,避免用户格子间里应用文件。

3.数据独立性。数据库逻辑结构和应用程序相互独立,物理结构变化不影响数据的逻辑结构。

4.数据集中控制。利用数据库可以对数据集中控制和管理,并通过数据模型表示各种数据的组织以及数据间的联系。

5.数据的一致性和可维护性。(安全性控制、完整性控制、并发控制、故障的发现和恢复。

数据库的基本结构分为三个层次:

1.物理数据层:数据库最内层,物理存储设备上实际存储的数据集合。

2.概念数据层:数据库中间层,数据库的整体逻辑表示,指出了每个数据的逻辑定义及数据间的逻辑联系,存储记录的集合。

3.逻辑数据层:用户所看到和使用的数据库,一个或一些特定用户使用的数据集合,即逻辑记录的集合。

18.1.2数据库的种类及功能

数据库系统一般基于某种数据模型,可以分为层次型、网状型、关系型及面向对象型,目前最流行的是关系型。

以MySQL为例,MySQL数据库是开发源代码的软件,具有功能性墙、使用简便、管理方便、运行速度快、安全可靠性强等优点,MySQL是具有客户机/服务器体系结构的分布式数据库管理系统,也是一个完全网络化的跨平台关系型数据库系统。

MySQL在UNIX/Linux系统上以多线程方式运行,在Windows NT上以系统服务运行,在Windows95/98上以普通进程方式运行。

从JDK6开始,JDK的安装目录中新增加了一个db的目录,即Java DB。这是要给纯Java实现的、开源的数据库关系系统(DBMS),源于Apache软件基金会(ASF)名下的项目Derby。

18.1.3SQL语言

SQL(Structure Query Language,结构化查询语言)被广泛地应用于大多数数据库中,依赖于关系模型。SQL语言主要由以下几部分组成:

1.数据定义语言(Data Definition Language,DDL)如create、alter、drop等。

2.数据操纵语言(Data Manipulation Language,DML)如select\insert\update\delete等。

3.数据控制语言(Data Control Language,DCL),如grant、revoke等。

4.事务控制语言(Transaction Control Language),如commit、rollback等。

其中DDL是最常用的SQL语言,介绍如下:

1.select语句

SELECT 所选字段列表 FROM 数据表名
WHERE 条件表达式 GROUP BY 字段名 HAVING 条件表达式(指定分组的条件)
ORDER BY 字段[ASC|DESC]

2.insert语句

insert into 表名[(字段名1,字段名2...)]
values(属性值1,属性值2...)

3.update语句

UPDATE 数据表名 SET 字段名=新的字段值 WHERE 条件表达式

4.delete语句

delete from 数据表名 where 条件表达式

18.2JDBC概述

JDBC是用来执行SQL语句的API(Application Programming Interface,应用程序设计接口),是连接数据库和java应用程序的纽带。

18.2.1JDBC-ODBC桥

JDBC-ODBC桥是一个JDBC驱动程序。完成了从JDBC操作到ODBC操作之间的转换工作,允许JDBC驱动程序用作ODBC的驱动程序,使用JDBC-ODBC桥连接数据库的步骤如下:

(1)首先加载JDBC-ODBC桥的驱动程序,代码如下:

Class.forName("sum.jdbc.JdbcOdbcDriver");

Class类是java.lang包中的一个类,通过该类的静态方法forName()可加载sun.jdbc.odbc包中的JdbcOdbcDriver类来建立JDBC-ODBC桥连接器。

(2)使用java.sql包中的Connection接口,并通过DriverManager类的静态方法getConnection()创建连接对象。代码如下:

Connection conn=DriverManager.getConnection("jdbc:odbc:数据源名字","user name","password");

数据源必须给出一个简短的描述名。加入没有设置user name和password,则要与数据源tom交换数据。建立Connection对象的代码如下:

Connection conn=DriverManager.getConnection("jdbc.odbc:tom",""."");

(3)向数据库发送SQL语句。使用Statement接口声明一个SQL语句对象,并通过刚才创建的链接数据库对象的conn的createStatement()方法创建这个SQL对象,代码如下:

Statement sql=conn.createStatement();

JDBC-ODBC桥作为链接数据库的过渡性技术,现在已经不再流行,但由于ODBC技术被广泛使用,使得Java可以利用JDBC-ODBC桥访问几乎所有的数据库。

JDBC-ODBC桥作为sun.jdbc.odbc包与JDK一起自动安装,无需额外配置。

18.2.2JDBC技术

JDBC全称是Java DataBase Connectivity,指定了同一的访问各种关系数据库的标准接口。

JDBC是一种底层的API,因此访问数据库时需要在业务逻辑层中镶入SQL语句。

JDBC不能直接访问数据库,必须依赖于数据库厂商提供的JDBC驱动程序。

JDBC总体结构由4个组件组成:应用程序、驱动程序管理器、驱动程序、数据源。

JDBC技术主要用来完成以下几个任务:

(1)与数据库建立一个连接。

(2)向数据库发送SQL语句。

(3)处理从数据库返回的结果。

18.2.3JDBC驱动程序的类型

JDBC驱动程序基本上分为4种:JDBC-ODBC桥、本地API、JDBC网络驱动、本地协议驱动。

其中JDBC网络驱动和本地协议驱动时JDBC访问数据库的首选。

18.3JDBC中常用的类和接口

java.sql包中定义了常用的访问和处理数据库的类。

18.3.1Connection接口

Connection接口代表与特定的数据库连接,在连接上下文中执行SQL语句并返回结果。

方法功能描述
createStatement()创建Statement对象
createStatement(int resultSetType,int resultSetConcurrency)创建一个statement对象,该对象将生成具有给定类型、并发性和可保存性的ResultSet对象
preparedStatement()创建预处理对象preparedStatement
isReadonly()查看当前Conncetion对象的读取模式是否为只读形式
setReadOnly()设置当前Connection对象的读写模式,默认是非只读模式
commit()使所有上一次提交/回滚后进行的更改为持久更改,并释放此Conncetion对象当前持有的所有数据库锁
roolback()取消在当前事务中进行的所有更改,并释放此Connection对象当前持有的所有数据库锁
close()立即释放此Connection对象的数据库和JDBC资源,而不是等待他们被自动释放

18.3.2Statement接口

Statement接口用于在已经建立连接的基础上向数据库发送SQL语句。在JDBC中由3种Statement对象,分别是:

1.Statement对象,用于执行不带参数的简单SQL语句;

2.PrepareStatement对象,继承自Statement对象,用来执行动态SQL语句;

3.CallableStatement对象,继承自PrepareStatement对象,用于执行对数据库的存储过程的调用。

Statement接口常用方法如下所示:

方法功能描述
execute(string sql)执行静态的SELECT语句,该语句可能就返回多个结果集
exceteQuery(String sql)执行给定的SQL语句,该语句返回单个ResultSet对象
clearBatch()清空此Statment对象的当地球SQL命令列表
excuteBatch()将一批命令提交给数据库来执行,如果全部命令执行成功,则返回更新计数组成的数组。数组元素的排序与SQL语句的添加顺序对应
addBatch(String sql)将给定的SQL命令添加到此statement对象的当前命令列表中。如果驱动程序不支持批量处理,将抛出异常
close()释放Statement实例占用的数据库和JDBC资源

18.3.3PreparedStatement接口

PreparedStatement接口用来动态地执行SQL语句。通过PrepareStatement实例执行的动态SQL语句,将被预编译并保存到PrepareStatement实例中,从而可以反复地执行该SQL语句。

PreparedStatement接口常用方法如下所示:

方法功能描述
setInt(int index ,int k)将指定位置的参数设置为对应的int值
setFloat(int index,float f)将指定位置的参数设置为对应的float值
setLong(int index,ling l)将指定位置的参数设置为对应的long值
setDouble(int index,double d)将指定位置的参数设置为对应的double值
setBoolean(int index,boolean b)将指定位置的参数设置为对应的boolean值
setDate(int index,date date)将指定位置的参数设置为对应的date值
executeQuery()再次PreparedStatement对象中执行SQL查询,并返回该查询生成的ResultSete对象
setString(int inex,String s)将指定位置的参数设置为对应的String值
setNull(int index,int sqlType)将制定位置的参数设置为SQL NULL
executeUpdate()执行前面包含的参数的动态INSET、UPDATE或DELETE语句
clearParameters()清除当前所有参数值

18.3.4DriverManager类

DriverManager类用来管理数据库中所有驱动程序,可以跟踪可以用的驱动程序,并在数据库的驱动程序之间建立连接。DriverManager类常用方法如下所示:

方法功能描述
getConnection(String url,String user,String password)指定三个入口参数(URL、用户名、密码)来获取与数据库的连接,不能连接则抛出SQLException异常
setLooginTimeout()获取驱动程序视图登陆到某一数据库时可以等待的最长时间,单位为秒
println(Stirng message)将一条消息打印到当前JDBC日志流中

18.3.5ResultSet接口

ResultSet接口类似于一个临时表,用来暂时存放数据库查询操作获得的结果集。ResultSet实例具有指向当前数据行的指针,指针开始的位置在第一条记录的前面,通过next()方法可以将指针向下移。

在JDK1.2之后,该接口添加了一组更新方法updateXXX(),该方法有两个重载方法,可以根据列的索引号和列的名称来更新指定列。但如果要将更新同步到数据库中,还需要执行updateRow()或insertRow()方法。

ResultSet接口常用方法如下所示:

方法功能描述
getInt()以int形式获取此ResultSet对象的当前行的指定列值,如果列值是NULL,则返回值是0
getFloat()以Folat形式获取此ResultSet对象的当前行的指定列值,若列值是NULL,则返回值是0
getDate()以date形式获取ResultSet对象的当前行的指定列值,如果列值是NULL,则返回null
getBoolean()以boolean形式获取ResultSet对象的当前行的指定列值,如果列值是NULL,则返回null
getString()以String形式获取ResultSet对象的当前行的指定列值,如果列值是NULL,则返回null
getObject()以Object形式获取ResultSet对象的当前行的指定列值,如果列值是NULL,则返回null
first()将指针移到当前记录的第一行
last()将指针移到当前记录的最后一行
next()将指针移向下一行
beforeFirst()将指针移动到集合的开头(第一行位置)
afterLast()将指针移动到集合的尾部(最后一行位置)
absolute(int index)将指针移到ResultSet给定编号的行
isFirst()判断指针是否位于当前ResultSet集合的第一行。返回boolean值
isLast()判断指针是否位于当前ResultSet集合的最后一行。返回boolean值
updateInt()用指定的int值更新指定列
updateFloat()用指定的float值更新指定列
updateLong()用指定的long值更新指定列
updateString()用指定的String值更新指定列
updateObject()用指定的Object值更新指定列
updateNull()将指定的列值修改为NULL
updateDate()用指定的date值更新指定列
updateDouble()用指定的double值更新指定列
getRow()查看当前行的索引号
insertRow()将查日航的内容更新到数据库
updateRow()将堂前行的内容同步到数据库
deleteRow()删除当前行,但不同步到数据库,在执行close()方法后同步到数据库

18.4数据库操作

实操中遇到的的问题及解决方法:

1.IntelliJ IDEA导入mysql-connector-java-5.1.44-bin.jar
2.SSL连接警告

3.提示mysql时区错误

18.4.1连接数据库

访问数据库前需要先加载数据库驱动程序(加载一次即可),而后每次访问数据时创建一个Connection对象。在完成数据库操作后,再摧毁前面创建的Connection对象,释放与数据库的连接。

以下是一个连接数据库程序实例:

public class Conn {
    Connection con;

    public Connection getConnection() {
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            //forName()方法用来加载JDBC驱动程序
            System.out.println("数据库驱动加载成功");
        } catch (ClassNotFoundException e) {
            //加载驱动失败会抛出ClassFoundException异常
            e.printStackTrace();
        }
        try {
            con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/qiang_db?useSSL=false",
                    "root", "123");
            //java.sql包中的DriverManager类静态方法getConnection()用于建立数据库连接
            //getConnection(String url,String user,String password)
            System.out.println("数据库连接成功");
        } catch (SQLException e) {
            //连接失败抛出SQLException异常
            e.printStackTrace();
        }
        return con;
    }

    public static void main(String[] args) {
        Conn c = new Conn();
        c.getConnection();

    }
}

运行结果:

1535599055641

18.4.2向数据库发送SQL语句

getConnection()只是获取了与数据库的连接,要想执行SQL语句还需要statement对象,通过Conncetion对象的createStatement()方法获取。举例如下:

try{
    Statement sql=con.createStatement();
    //con为上例中创建的Connection对象
}catch(SQLException e){
    e.printStackTrace();
}

18.4.3处理查询结果集

有了statement对象就可以调用相应的方法实现对数据库的查询和修改,并将查询结果存放在ResultSet类对象中。获取查询结果集代码如下:

ResultSet res=sql.executeQuery("select*from student");

运行结果返回一个ResultSet对象,该对象一次只可以看到结果集中的一行数据,使用该类的next()方法可以将光标从当前位置移向下一行。

18.4.4顺序查询

ResultSet类的next()方法返回值是boolean类型的数据,当光标移动到最后一行将返回false。以下是一个顺序查询的实例。

import java.sql.*;

public class Gradation {
    static Connection con;
    static Statement sql;
    static ResultSet res;

    public Connection getConnection() {
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        try {
            con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/qiang_db?useSSL=false"
                    , "root", "123");

        } catch (SQLException e) {
            e.printStackTrace();
        }
        return con;
    }

    public static void main(String[] args) {
        Gradation gra = new Gradation();
        gra.getConnection();
        try {
            sql = con.createStatement();
            res = sql.executeQuery("select*from students");
            while (res.next()) {
                String id = res.getString("id");
                String name = res.getString("name");
                String sex = res.getString("sex");
                String age = res.getString("age");
                System.out.println("编号:" + id);
                System.out.println("姓名" + name);
                System.out.println("性别" + sex);
                System.out.println("年龄" + age);
                System.out.println();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }

    }
}

“id”在第一列,其中getString(“id”); 等价于 getString(1);

18.4.5模糊查询

SQL与剧中提供了LIKE操作符用于模糊查询,可以使用”%“来代替0个或者多个字符,”_”代表一个字符,例如需要查询姓名为王的同学的所有信息时,可以使用如下的SQL语句:

select*from students where name like"张%"

举例如下:

public class Gradation {
    static Connection con;
    static Statement sql;
    static ResultSet res;

    public Connection getConnection() {
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        try {
            con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/qiang_db?useSSL=false"
                    , "root", "123");

        } catch (SQLException e) {
            e.printStackTrace();
        }
        return con;
    }

    public static void main(String[] args) {
        Gradation gra = new Gradation();
        gra.getConnection();
        try {
            sql = con.createStatement();
            res = sql.executeQuery("select*from students where name like '王%'");
            //对于单一精确的对象,可以使用'='替代like,如‘select*from students where name='王刚'
            while (res.next()) {
                String id = res.getString("id");
                String name = res.getString("name");
                String sex = res.getString("sex");
                String age = res.getString("age");
                System.out.print("编号:" + id);
                System.out.print(" 姓名" + name);
                System.out.print(" 性别" + sex);
                System.out.println(" 年龄" + age);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }

    }
}

18.4.6预处理语句

SQL解释器负责把SQL语句生成底层的内部命令,当提交大量SQL语句时,会增加SQL解释器负担,影响执行速度。

Connection对象的preparedStatement(String sql)方法对SQL语句进行预处理,生成数据库底层内部命令,从而减轻数据库负担,提高访问数据库速度。

对SQL预处理时可以使用通配符”?“来代替任何字段的值。

sql=con.prepareStatement("select*from students where id=?");

在执行预处理语句前,需要使用相应方法设置通配符所表示的值,例如:

sql.setInt(1,2);
//"1"表示第一个通配符,2表示设置的通配符的值

再通过setXXX()方法为SQL语句中参数赋值时,建议利用与参数匹配的方法,也可以利用setObject()方法为各种类型的参数赋值,如:

import java.sql.*;

public class Prep {
    static Connection con;
    static PreparedStatement sql;
    static ResultSet res;

    public Connection getConnection() {
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        try {
            con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/qiang_db?useSSL=false"
                    , "root", "123");

        } catch (SQLException e) {
            e.printStackTrace();
        }
        return con;
    }

    public static void main(String[] args) {
        Prep pre = new Prep();
        pre.getConnection();
        try {
            sql = con.prepareStatement("select*from students where name=?");
            sql.setString(1,"王刚");
            res = sql.executeQuery();
            while (res.next()) {
                String id = res.getString("id");
                String name = res.getString("name");
                String sex = res.getString("sex");
        String age = res.getString("age");
        System.out.println("编号:" + id+"\t姓名:" + name+"\t性别:" + sex+"\t年龄:" + age);
    }
} catch (SQLException e) {
        e.printStackTrace();
        }

    }
}

18.4.7添加、修改、删除记录

指定PreparedStatement类的参数可以动态地对数据表中原有数据进行修改,并通过executeUpdate()方法执行更新语句操作。

executeQuery()方法在PreparedStatement对象中执行SQL查询,并返回查询生成的ResultSet对象。

executeUpdate()方法在PreparedStatement对象中执行SQl语句,该语句需要是一个DDL语句(insert\update\delete)或者无返回内容的SQL语句(如DDL);

import java.sql.*;

public class Prep {
    static Connection con;
    static PreparedStatement sql;
    static ResultSet res;

    public Connection getConnection() {
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        try {
            con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/qiang_db?useSSL=false"
                    , "root", "123");

        } catch (SQLException e) {
            e.printStackTrace();
        }
        return con;
    }

    public static void main(String[] args) {
        Prep pre = new Prep();
        pre.getConnection();
        try {
            //输出原始数据
            sql = con.prepareStatement("select*from students");
            res = sql.executeQuery();
            System.out.println("初始数据为:");
            while (res.next()) {
                String id = res.getString("id");
                String name = res.getString("name");
                String sex = res.getString("sex");
                String age = res.getString("age");
                System.out.println("编号:" + id + "\t姓名:" + name + "\t性别:" + sex + "\t年龄:" + age);
            }
            //添加数据
            sql = con.prepareStatement("insert into students values(?,?,?,?)");
            sql.setInt(1, 6);
            sql.setString(2, "吴芳");
            sql.setString(3, "女");
            sql.setInt(4, 20);
            sql.executeUpdate();
            //更新数据
            sql = con.prepareStatement("update students set age=? " +
                    "where id =5");
            sql.setInt(1, 3);
            sql.executeUpdate();
            //删除数据
            sql.executeUpdate("delete from students where id= 1");
            //查看修改后的数据
            sql = con.prepareStatement("select*from students");
            res = sql.executeQuery();
            System.out.println("更新后数据为:");
            while (res.next()) {
                String id = res.getString("id");
                String name = res.getString("name");
                String sex = res.getString("sex");
                String age = res.getString("age");
                System.out.println("编号:" + id + "\t姓名:" + name + "\t性别:" + sex + "\t年龄:" + age);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值