使用MySQL数据库,实现你的第一个JDBC程序

news2024/10/7 2:22:12

熟悉了JDBC的编程步骤后,接下来通过一个案例并依照上一小节所讲解的步骤来演示JDBC的使用。此案例会从tb_user表中读取数据,并将结果打印在控制台。

需要说明的是,Java中的JDBC是用来连接数据库从而执行相关数据相关操作的,因此在使用JDBC时,一定要确保安装有数据库。常用的关系型数据库有MySQL和Oracle,本书就以连接MySQL数据库为例,使用JDBC执行相关操作。

案例的具体实现步骤如下:

(1) 搭建数据库环境

在MySQL数据库中创建一个名称为jdbc的数据库,然后在该数据库中创建一个名称为tb_user的表,创建数据库和表的SQL语句如下:

CREATE DATABASE jdbc;USE jdbc;
CREATE TABLEtb_user(
        id INT PRIMARY KEY AUTO_INCREMENT,NAMEVARCHAR(40),
        sex VARCHAR(2),    
        email VARCHAR(60),
        birthday DATE        
);

上述创建tb_user表时添加了id、NAME、sex、email和birthday共5个字段,其中NAME字段名称为大写形式,这是因为name字段在MySQL数据库中属于关键字,所以为了方便区分,这里将name字段名称全部用大写表示。

数据库和表创建成功后,再向tb_user表中插入3条数据,插入的SQL语句如下所示:

INSERT INTOtb_user(NAME,sex,email,birthday)VALUES('Jack','男','jack@126.com','1980-01-04'),('Tom','男','tom@126.com','1981-02-14'),('Lucy','女','lucy@126.com','1979-12-28');

为了查看数据是否添加成功,使用SELECT语句查询tb_user表中的数据,执行结果如图1所示。

图1 tb_user表中的数据

注意:

数据库和表创建成功后,如果使用的是命令行窗口向tb_user表中插入带有中文的数据,命令行窗口可能会报错,同时从MySQL数据库查询带有中文数据还可能会显示乱码,这是因为MySQL数据库默认使用的是UTF-8编码格式,而命令行窗口默认使用的是GBK编码格式,所以执行带有中文数据的插入语句会出现解析错误。为了在命令行窗口也能正常向MySQL数据库插入中文数据,以及查询中文数据,可以在执行插入语句和查询语句前,先在命令行窗口执行以下两条命令:

set character_set_client=gbk;
set character_set_results=gbk;

执行完上述两条命令后,再次在命令行窗口执行插入和查询操作就不再出现乱码问题了。

(1) 创建项目环境,导入数据库驱动

在Eclipse中新建一个名称为chapter09的Java项目,使用鼠标右键单击项目名称,然后选择【New】→【Folder】,在弹出窗口中将该文件夹命名为lib并单击【Finish】按钮,此时项目根目录中就会出现一个名称为lib的文件夹。将下载好的MySQL数据库驱动文件Jar包(mysql-connector-java-5.1.46-bin.jar)复制到项目的lib目录中,并使用鼠标右击该JAR包,在弹出框中选择【Build Path】→【Add to Build Path】,此时Eclipse会将该JAR包发布到类路径下。加入驱动后的项目结构如图2所示。

其中,MySQL驱动文件可以在其官网地址:http://dev.mysql.com/downloads/connector/j/页面中下载,单击页面Platform Independent (Architecture Independent), ZIP Archive后的“Download”按钮,并在新打开的窗口中的单击 “No thanks, just start my download”超链接后即可下载驱动压缩包(本书编写时的最新驱动版本文件是mysql-connector-java-5.1.46.zip),解压后即可得到相应JAR包。

(1) 编写JDBC程序

在项目chapter09的src目录下,新建一个名称为com.itheima.jdbc的包,并在该包中创建类Example01。在该类读取数据库中的tb_user表,并将结果输出到控制台,如文件1所示。

文件1 Example01.java

importjava.sql.*;publicclassExample01{publicstaticvoidmain(String[] args)throwsSQLException{Connection conn =null;Statement stmt =null;ResultSet rs =null;try{// 1. 加载数据库驱动Class.forName("com.mysql.jdbc.Driver");// 2.通过DriverManager获取数据库连接String url ="jdbc:mysql://localhost:3306/jdbc";String username ="root";String password ="root";
                 conn =DriverManager.getConnection(url,username, password);// 3.通过Connection对象获取Statement对象
                 stmt = conn.createStatement();// 4.使用Statement执行SQL语句String sql ="select * from tb_user";
                 rs = stmt.executeQuery(sql);// 5. 操作ResultSet结果集System.out.println("id    |    name      |    sex  "+"   |    email        |    birthday ");while(rs.next()){int id = rs.getInt("id");// 通过列名获取指定字段的值String name = rs.getString("name");String sex = rs.getString("sex");String email = rs.getString("email");Date birthday = rs.getDate("birthday");System.out.println(id +"    |    "+ name +"    |    "+ sex +"    |    "+ email +"    |    "+ birthday);}}catch(Exception e){
                 e.printStackTrace();}finally{// 6.关闭连接,释放资源if(rs !=null){ rs.close();}if(stmt !=null){ stmt.close();}if(conn !=null){ conn.close();}}}}

运行结果如图3所示。

图3 运行结果

文件1中,首先注册了MySQL数据库驱动,通过DriverManager获取一个Connection对象,然后使用Connection对象创建一个Statement对象,Statement对象通过executeQuery(String sql)方法执行了SQL语句,并返回结果集ResultSet,接下来,通过遍历ResultSet得到查询结果并输出,最后关闭连接,释放数据库资源。

从图3中可以看到,tb_user表中的数据已被打印在了控制台。至此第一个JDBC程序实现成功。

注意:

在进行数据库连接时,连接MySQL数据库的username和password都要与创建MySQL数据库时设置的登录账户一致,否则登录失败。本章以及后续案例都默认MySQL数据库登录的username和password都为“root”。

实现JDBC程序一共需要几步?

通常情况下,JDBC的使用可以按照以下几个步骤进行:

(1) 加载数据库驱动

加载数据库驱动通常使用Class类的静态方法forName()来实现,具体实现方式如下:

Class.forName("DriverName");

在上述代码中,DriverName就是数据库驱动类所对应的字符串。例如,要加载MySQL数据库的驱动可以采用如下代码:

Class.forName("com.mysql.jdbc.Driver");

加载Oracle数据库的驱动可以采用如下代码:

Class.forName("oracle.jdbc.driver.OracleDriver");

从上面两种加载数据库驱动的代码可以看出,在加载驱动时所加载的并不是真正使用数据库的驱动类,而是数据库驱动类名的字符串。

(2) 通过DriverManager获取数据库连接

DriverManager中提供了一个getConnection()方法来获取数据库连接,获取方式如下:

Connection conn =DriverManager.getConnection(String url,String user,String pwd);

从上述代码可以看出,getConnection()方法中有3个参数,它们分别表示连接数据库的URL、登录数据库的用户名和密码。其中用户名和密码通常由数据库管理员设置,而连接数据库的URL则遵循一定的写法。以MySQL数据库为例,其地址的书写格式如下:

jdbc:mysql://hostname:port/databasename

上面代码中,jdbc:mysql:是固定的写法,mysql指的是MySQL数据库。hostname指的是主机的名称(如果数据库在本机上,hostname可以为localhost或127.0.0.1,如果在其他机器上,那么hostname为所要连接机器的IP地址),port指的是连接数据库的端口号(MySQL端口号默认为3306),databasename指的是MySQL中相应数据库的名称。

(3) 通过Connection对象获取Statement对象

Connection创建Statement的方式有如下三种:

● createStatement():创建基本的Statement对象。

● prepareStatement(String sql):根据传递的SQL语句创建PreparedStatement对象。

● prepareCall(String sql):根据传入的SQL语句创建CallableStatement对象。

以创建基本的Statement对象为例,其创建方式如下:

Statement stmt = conn.createStatement();

(4) 使用Statement执行SQL语句

所有的Statement都有如下三种执行SQL语句的方法:

● execute(String sql):用于执行任意的SQL语句。

● executeQuery(String sql):用于执行查询语句,返回一个ResultSet结果集对象。

● executeUpdate(String sql):主要用于执行DML(数据操作语言)和DDL(数据定义语言)语句。执行DML语句(INSERT、UPDATE或DELETE)时,会返回受SQL语句影响的行数,执行DDL(CREATE、ALTER)语句返回0。

以executeQuery()方法为例,其使用方式如下:

// 执行SQL语句,获取结果集ResultSetResultSet rs = stmt.executeQuery(sql);

(5) 操作ResultSet结果集

如果执行的SQL语句是查询语句,执行结果将返回一个ResultSet对象,该对象里保存了SQL语句查询的结果。程序可以通过操作该ResultSet对象来取出查询结果。

(6) 关闭连接,释放资源

每次操作数据库结束后都要关闭数据库连接,释放资源,以重复利用资源。需要注意的是,通常资源的关闭顺序与打开顺序相反,顺序是ResultSet、Statement(或PreparedStatement)和Connection。为了保证在异常情况下也能关闭资源,需要在try...catch的finally代码块中统一关闭资源。

至此,JDBC程序的大致实现步骤已经讲解完成。

Spring中的JDK动态代理是如何实现的?

JDK动态代理是通过java.lang.reflect.Proxy 类来实现的,我们可以调用Proxy类的newProxyInstance()方法来创建代理对象。对于使用业务接口的类,Spring默认会使用JDK动态代理来实现AOP。

接下来,通过一个案例来演示Spring中JDK动态代理的实现过程,具体步骤如下。

(1)创建一个名为chapter03的Web项目,导入Spring框架所需JAR包到项目的lib目录中,并发布到类路径下。

(2)在src目录下,创建一个com.itheima.jdk包,在该包下创建接口UserDao,并在该接口中编写添加和删除的方法,如文件1所示。

文件1 UserDao.java

packagecom.itheima.jdk;publicinterfaceUserDao{publicvoidaddUser();publicvoiddeleteUser();}

(3)在com.itheima.jdk包中,创建UserDao接口的实现类UserDaoImpl,分别实现接口中的方法,并在每个方法中添加一条输出语句,如文件2所示。

文件2 UserDaoImpl.java

packagecom.itheima.jdk;// 目标类publicclassUserDaoImplimplementsUserDao{publicvoidaddUser(){System.out.println("添加用户");}publicvoiddeleteUser(){System.out.println("删除用户");}}

需要注意的是,本案例中会将实现类UserDaoImpl作为目标类,对其中的方法进行增强处理。

(4)在src目录下,创建一个com.itheima.aspect包,并在该包下创建切面类MyAspect,在该类中定义一个模拟权限检查的方法和一个模拟记录日志的方法,这两个方法就表示切面中的通知,如文件3所示。

文件3 MyAspect.java

packagecom.itheima.aspect;//切面类:可以存在多个通知Advice(即增强的方法)publicclassMyAspect{publicvoidcheck_Permissions(){System.out.println("模拟检查权限...");}publicvoidlog(){System.out.println("模拟记录日志...");}}

(5)在com.itheima.jdk包下,创建代理类JdkProxy,该类需要实现InvocationHandler接口,并编写代理方法。在代理方法中,需要通过Proxy类实现动态代理,如文件4所示。

文件4 JdkProxy.java

packagecom.itheima.jdk;importjava.lang.reflect.InvocationHandler;importjava.lang.reflect.Method;importjava.lang.reflect.Proxy;importcom.itheima.aspect.MyAspect;/**
      * JDK代理类
      */publicclassJdkProxyimplementsInvocationHandler{// 声明目标类接口privateUserDao userDao;// 创建代理方法publicObjectcreateProxy(UserDao userDao){this.userDao = userDao;// 1.类加载器ClassLoader classLoader =JdkProxy.class.getClassLoader();// 2.被代理对象实现的所有接口Class[] clazz = userDao.getClass().getInterfaces();// 3.使用代理类,进行增强,返回的是代理后的对象returnProxy.newProxyInstance(classLoader,clazz,this);}/*
          * 所有动态代理类的方法调用,都会交由invoke()方法去处理
          * proxy 被代理后的对象 
          * method 将要被执行的方法信息(反射) 
          * args 执行方法时需要的参数
          */@OverridepublicObjectinvoke(Object proxy,Method method,Object[] args)throwsThrowable{// 声明切面MyAspect myAspect =newMyAspect();// 前增强
             myAspect.check_Permissions();// 在目标类上调用方法,并传入参数Object obj = method.invoke(userDao, args);// 后增强
             myAspect.log();return obj;}}

在文件4中,JdkProxy类实现了InvocationHandler接口,并实现了接口中的invoke()方法,所有动态代理类所调用的方法都会交由该方法处理。在创建的代理方法createProxy()中,使用了Proxy类的newProxyInstance()方法来创建代理对象。newProxyInstance()方法中包含三个参数,其中第1个参数是当前类的类加载器,第2个参数表示的是被代理对象实现的所有接口,第3个参数this代表的就是代理类JdkProxy本身。在invoke()方法中,目标类方法执行的前后,会分别执行切面类中的check_Permissions()方法和log()方法。

(6)在com.itheima.jdk包中,创建测试类JdkTest。在该类中的main()方法中创建代理对象和目标对象,然后从代理对象中获得对目标对象userDao增强后的对象,最后调用该对象中的添加和删除方法,如文件5所示。

文件5 JdkTest.java

packagecom.itheima.jdk;publicclassJdkTest{publicstaticvoidmain(String[] args){// 创建代理对象JdkProxy jdkProxy =newJdkProxy();// 创建目标对象UserDao userDao=newUserDaoImpl();// 从代理对象中获取增强后的目标对象UserDao userDao1 =(UserDao) jdkProxy.createProxy(userDao);// 执行方法
             userDao1.addUser();
             userDao1.deleteUser();}}

执行程序后,控制台的输出结果如图1所示。

图1 运行结果

从图1可以看出,userDao实例中的添加用户和删除用户的方法已被成功调用,并且在调用前后分别增加了检查权限和记录日志的功能。这种实现了接口的代理方式,就是Spring中的JDK动态代理。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/194456.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

双面电子会议桌牌

产品特征: 超低功耗,3-5年电池寿命电子纸墨水屏幕,视角接近180多种电子桌牌显示颜色可选 3色(黑,白,红) 4色(黑,白,红,黄) 7色&…

营销大数据如何帮助企业深入了解客户—镭速

随着互联网的进一步发展,大门向您的企业敞开大门,让您在如何使用数据为客户提供他们所寻求的个性化,令人兴奋和引人入胜的体验方面更具创造性和创新性。大数据是了解客户究竟是谁以及如何与他们互动的关键部分。 行动中的见解 随着智能手机…

听劝,不要试图以编程为基础去学习网络安全

目录一、网络安全学习的误区1.不要试图以编程为基础去学习网络安全2.不要刚开始就深度学习网络安全3.收集适当的学习资料4.适当的报班学习二、学习网络安全的些许准备1.硬件选择2.软件选择3.外语能力三、网络安全学习路线第一阶段:基础操作入门第二阶段:…

什么是基站定位?

基站与信号塔首先,我们先介绍一下基站。基站包括移动、联通和电信基站,当手机开机、关机、切换基站时都会向最近最优基站赋权。其主要功能是负责用户手机端信号传出工作,包括语音通话、网络访问等各项业务。这里我们特别强调一个误区&#xf…

不离不弃生死相依

男孩儿:“对不起……” 女孩儿:“无所谓,你没什么对不起我的。” 键盘敲出最后这句话,女孩儿失声痛哭。 爱上他是女孩儿没有想到的事情,她以为自己不会爱上任何人。 可最后还是敌不过男孩儿的温柔,陷了进去…

OpenMMLab AI实战课笔记

1. 第一节课 1.1 计算机视觉任务 计算机视觉主要实现以下目标: 分类目标检测分割:语义分割、实例分割 (对像素进行精确分类, 像素粒度或细粒度)关键点检测 1.2 OpenMMLab框架 框架选择:PyTorchOpenMMLab是基于PyTorch开发的code base, …

linux_信号

文章目录1、信号的实现机制2、发送信号2.1、发送信号的原因2.2、发送信号的机制kill 函数3、接收信号3.1、处理信号signal 函数sigaction 函数3.2、信号阻塞 | 解除sigset_t 信号集合sigpending 函数sigprocmask 函数sigsuspend 函数4、定时器4.1、睡眠函数sleep 函数pause 函数…

STM32 学习笔记_1前言;软件安装

前言 学习自江科大自动协 b站课程。 呜呼!今朝有坑今朝开,管他明朝埋不埋!开新坑的过程是最爽的。 STM32 是 ST 公司基于 ARM CORE-M 芯片(类似 CPU)开发的32位的单片机,相比8位的51单片机性能更强。&am…

【数据结构】哈希表的原理及实现

1.什么是哈希表 哈希表又称为散列表,它是一种以键值对形式来存储数据的结构,只要输入待查找的key,就可以通过该key寻找到对应的值。对应函数:y f(key)通过把关键码映射到表中的对应位置来访问对应信息,来加快查找速度…

机械设备行业ERP在企业中如何发挥作用?

对机械设备制造企业而言,一方面,大部分销售额都集中在少数几个客户,很难实时了解市场和用户真实需求,订单修改、取消,销售、生产预测不准,原料积压、作废等是常有的事,日积月累给企业造成极大的…

【官方 | 计算机二级Python教程】第一章:程序设计基本方法

【官方 | 计算机二级Python教程】第一章:程序设计基本方法参考书目第一章:程序设计基本方法本章知识导图1.1 程序设计语言1.1.1 程序设计语言概述1.1.2 编译和解释1.2 Python语言概述1.2.1 Python语言的发展1.2.2 Python最小程序1.3 Python开发环境配置1…

iptables端口复用_远程操控

目录 方式一:利用 ICMP 做遥控开关 一、创建端口复用链 二、创建端口复用规则 三、设置开启开关 四、设置关闭开关 五、将发现的数据包转到HTTP_SSH_PORT链上进行处理 六、开启复用 七、关闭复用 方式二:利用tcp数据包中的关键字做遥控开关 一…

【Java】GET 和 POST 请求的区别

GET 和 POST 请求的区别 GET 和 POST请求是最常用的两种请求方法,写了几个Servlet项目,发现这两种请求用的实在是多,给我的感觉就是这两个请求仿佛只有一个名字不同而已。但是通过查询资料发现,里面大有文章。HTTP协议定义的方法…

从0开始学python -18

Python3 元组 Python 的元组与列表类似,不同之处在于元组的元素不能修改。 元组使用小括号 ( ),列表使用方括号 [ ]。 元组创建很简单,只需要在括号中添加元素,并使用逗号隔开即可。 实例(Python 3.0) >>> tup1 (Go…

研发能力加码!维视智造团队入选“科学家+工程师”队伍!

一、维视智造成功入选2023年度秦创原“科学家工程师”队伍近日,陕西省科学技术厅公布了2023年度秦创原“科学家工程师”队伍入选名单,维视智造旗下欣维视觉工程师团队联合西北工业大学马志强副教授团队,申报的“大口径光学元件形性误差检测方…

第9章 Idea集成gitee(码云)

第一节 码云简介 众所周知,GitHub服务器在国外,使用GitHub作为项目托管网站,如果网速不好的话,严重影响使用体验,甚至会出现登录不上的情况。针对这个情况,大家也可以使用国内的项目托管网站-码云。 码云…

golang 协程关闭——谁敢说没踩过坑

Go语言中,协程创建和启动非常简单,但是如何才能正确关闭协程呢,和开车一样,前进总是很容易,但是如何正确的把车停在指定的地方总是不容易的。生产实践中,go常常遇到未能正确关闭协程而影响程序运行的场景&a…

Unity - TextMeshPro

TextMeshPro TextMeshPro 是 Unity 的终极文本解决方案。它是 Unity 的 UI 文本和旧版文本网格的完美替代品。 TextMeshPro(也称为 TMP)功能强大且易于使用,它使用高级文本渲染技术以及一组自定义着色器;提供显着的视觉质量改进&…

C++分文件编写VS Code和CMakeLists使用详解

目录一、示例代码1.1 主函数main.cpp1.2 子函数源文件1.3 子函数头文件二、VS Code编译2.1 报错2.2解决方法三、CMakeLists编译Windows 10 Ubuntu 20.04 VS Code 一、示例代码 1.1 主函数main.cpp 要用双引号包含子函数的头文件&#xff0c;第二行 #include<iostream&g…

项目经理必备的5种项目管理工具,让你的项目迅速上手

做项目管理是一条漫漫长路&#xff0c;所有的本事&#xff0c;都是靠一个个项目&#xff0c;一点点积累而来的&#xff0c;并不存在“迅速上手”的方法。 一名普通项目经理的成长&#xff0c;都要经过一定时间的修炼&#xff0c;并且要灵活使用项目管理工具&#xff0c;这里给…