Java操作数据库基本原理

news2025/7/19 11:12:54

- 四年前存稿

Java操作数据库基本原理


概述

全称Java Database Connectivity,Java的数据库连接,使用Java语言操作数据库,定义了操作所有关系型数据库规则(接口)

使用步骤

我的mysql是8版本的,使用jar包时必须使用8版本的,如果驱动jar包跟mysql版本不一样,执行时会报错。且要把注册驱动改为com.mysql.cj.jdbc.Driver,在url那边也要修改,在表名后面加?useUnicode=true&characterEncoding=UTF-8&userSSL=false&serverTimezone=GMT%2B8。不然也报错。同时,mysql5之后的驱动jar包可以省略注册驱动的步骤
但是以下步骤是基础,真正使用的时候不用Statement对象(作了解),而是使用PreparedStatement对象,参照后面使用PreparedStatement ,能防止SQL注入问题,安全性更高,效率也更高。

 public static void main(String[] args) throws Exception {
     //1.导入驱动jar包
     
     //2.注册驱动,这里可以注释掉不需要。
     Class.forName("com.mysql.cj.jdbc.Driver");
     
     //3.获取数据库连接对象
     Connection conn =  DriverManager.getConnection("jdbc:mysql://localhost:3306/db3?useUnicode=true&characterEncoding=UTF-8&userSSL=false&serverTimezone=GMT%2B8","root","888888");
     
     //4.定义一个sql语句
     String sql = "update account set balance = 500 where id = 1";
     
     //5.获取执行sql对象
     Statement stmt = conn.createStatement();
     
     //6.执行sql,返回影响行数
     int count = stmt.executeUpdate(sql);
     
     //7.打印结果
     System.out.println(count);
     
     //8.释放资源
     stmt.close();
     conn.close();
 }

JDBC各个类详解

DriverManager - - 驱动管理对象
①注册驱动:告知程序该使用哪一个数据库驱动jar包

 //2.注册驱动,mysql5之后驱动jar包可以省略注册驱动,即这里可以注释掉不需要
Class.forName("com.mysql.cj.jdbc.Driver");

②获取数据库连接:
static Connection getConnection(String url,String user,String password)
url — 指定的连接路径
语法 — jdbc:mysql://ip地址(域名):端口号/数据库名称
例如 —"jdbc:mysql://localhost:3306/db3?useUnicode=true&characterEncoding=UTF-8&userSSL=false&serverTimezone=GMT%2B8"
其中,若mysql连接的是本地的mysql服务器,并且mysql默认服务端口号是3306,则url可以简写为"jdbc:mysql:///db3?useUnicode=true&characterEncoding=UTF-8&userSSL=false&serverTimezone=GMT%2B8"(即省略ip地址和端口号:jdbc:mysql:///数据库名称)
user — 用户名
passwor — 密码

 //3.获取数据库连接对象
Connection conn =  DriverManager.getConnection("jdbc:mysql://localhost:3306/db3?useUnicode=true&characterEncoding=UTF-8&userSSL=false&serverTimezone=GMT%2B8","root","888888");

Connection - - - 数据库连接对象
①获取执行的sql对象
②管理事务
setAutoCommit(boolean autoCommit) – 开启事务
commit() - - 提交事务
rollback() - - 回滚事务


Statement - - - 执行sql对象
①执行sql语句
int executeUpdate(String sql) - - 执行DML(insert、update、delete)、DDL(create、alter、drop)
ResultSet executeQuery(String sql) - - 执行DQL(select)语句

执行insert语句测试.java

public static void main(String[] args) {
      Statement stmt = null;
      Connection conn = null;
      try{
          //1.注册驱动
          Class.forName("com.mysql.cj.jdbc.Driver");
          //2.定义sql
          String sql = "insert into account values(null,'monkey',3000)";
          //3.获取Connection对象
          conn = DriverManager.getConnection("jdbc:mysql:///db3?useUnicode=true&characterEncoding=UTF-8&userSSL=false&serverTimezone=GMT%2B8","root","888888");
          //4.获取执行sql的对象 Statement
          stmt = conn.createStatement();
          //5.执行sql
          int count = stmt.executeUpdate(sql);//影响行数,若是ddl语句,count返回0
          //6.处理结果
          System.out.println(count);
          if (count > 0){
               System.out.println("添加成功");
          }else{
               System.out.println("添加失败");
           }
       }catch (ClassNotFoundException e){
            e.printStackTrace();
       }catch (SQLException e) {
           e.printStackTrace();
       }finally {
           //7.释放资源
           //释放顺序应该是先stmt再是conn,但是看看try语快里面的执行顺序,很容易造成空指针异常
           if (stmt != null){
               try{
                   stmt.close();
               }catch (SQLException e){
                   e.printStackTrace();
               }
           }
           if (conn != null){
               try{
                   conn.close();
               }catch (SQLException e){
                   e.printStackTrace();
               }
           }
       }
   }

ResultSet查询指定的数据.java

public static void main(String[] args) {
      Statement stmt = null;
      Connection conn = null;
      ResultSet res = null;
      try{
          //1.注册驱动
          Class.forName("com.mysql.cj.jdbc.Driver");
          //2.定义sql
          String sql = "select * from account";
          //3.获取Connection对象
          conn = DriverManager.getConnection("jdbc:mysql:///db3?useUnicode=true&characterEncoding=UTF-8&userSSL=false&serverTimezone=GMT%2B8","root","888888");
          //4.获取执行sql的对象 Statement
          stmt = conn.createStatement();
          //5.执行sql
          res = stmt.executeQuery(sql);//影响行数,若是ddl语句,count返回0
          //6.处理结果
          while (res.next()){
              int id =  res.getInt(1);
              String name = res.getString("name");
              double balance = res.getDouble(3);
              System.out.println(id);
              System.out.println(name);
              System.out.println(balance);
          }
          /*  打印第二行数据,默认数据游标最初指向第一行的列名行
            res.next();
           int id =  res.getInt(1);
           String name = res.getString("name");
           double balance = res.getDouble(3);
           System.out.println(id);
           System.out.println(name);
           System.out.println(balance);*/
       }catch (ClassNotFoundException e){
           e.printStackTrace();
       } catch (SQLException e) {
           e.printStackTrace();
       }finally {
           //7.释放资源
           //释放顺序应该是先stmt再是conn,但是看看try语快里面的执行顺序,很容易造成空指针异常
           if (res != null){
               try{
                   res.close();
               }catch (SQLException e){
                   e.printStackTrace();
               }
           }
           if (stmt != null){
               try{
                   stmt.close();
               }catch (SQLException e){
                   e.printStackTrace();
               }
           }
           if (conn != null){
               try{
                   conn.close();
               }catch (SQLException e){
                   e.printStackTrace();
               }
           }
       }
   }

ResultSet - - - 结果集对象,封装查询结果
boolean next() - - 向下移动一行,判断是否有数据(末尾行),true为有,false没有
getXxx([可选参数]) - - 获取数据(Xxx代表数据类型),如int getInt()、String getString();可选参数int型代表列数编号如getString(1),可选参数String代表列名名称,getDouble(“price”)

/*
循环读取表中的数据
游标默认初始执向列名的一行,使用next()方法时向下移动一次
如果有数据返回true,没有返回false
类似于迭代器
*/
while(rs.next()){
    int id = rs.getInt(1);
    String name = rs.getString("name");
    double balance = rs.getDouble(3);
}

PreparedStatement - - - 预编译执行sql对象,提高安全性
SQL注入问题 - - 在拼接sql时,有一些特殊关键字参与字符串拼接,造成安全性问题
解决SQL注入问题 - - 使用PreparedStatement对象解决
预编译的SQL - -参数使用?作为占位符
eg:select * from user where username=? and password=?
使用步骤如下,效率更加高,且能防止SQL注入问题,怎么改参见下面登录案例的代码

1.导入驱动包
2.注册驱动
3.获取数据库连接对象 Connection
4.定义sql,eg: select * from user where username=? and password=?
5.获取sql语句对象,Connection.preparedStatement(String sql)
6.给占位符 ? 赋值:setXxx(参数1,参数2)
  - - 参数1代表?的位置标号,1开始,参数2代表?的值
7.执行sql,返回结果,不需要传递sql语句
8.处理结果
9.释放资源
 Connection conn = null;
 PreparedStatement pstmt = null;
 ResultSet rs = null;
 //连接数据检验是否正确
 try {
     //1.获取数据库连接
     conn = JDBCUtils.getConnection();

     //2.定义sql
     String sql = "select * from user where xxx1= ? and xxx2=?";

     //3.获取执行sql的对象,预编译
     pstmt = conn.prepareStatement(sql);
     
     //4.给?赋值
     pstmt.setString(1,xxx1);
     pstmt.setString(2,xxx2);

     //5.执行查询
     rs = pstmt.executeQuery();//这里不需要传参
     
     //6.处理结果
 } catch (SQLException e) {
     e.printStackTrace();
 }finally {
     JDBCUtils.close(rs,pstmt,conn);
 }


JDBCUtils工具类

抽取JDBC工具类JDBCUtils,因为每次都要写JDBC的步骤(看上面的代码,每次写都要捕捉异常,判断,代码重复太高),为了方便所以来抽取一个工具类,拿来公用

创建在src文件下的配置文件jdbc.properties

url = jdbc:mysql:///db3?useUnicode=true&characterEncoding=UTF-8&userSSL=false&serverTimezone=GMT%2B8
user = root
password = 888888
driver = com.mysql.cj.jdbc.Driver

JDBCUtils.java

import java.io.FileReader;
import java.io.IOException;
import java.sql.*;
import java.util.Properties;

/*
    JDBC工具类
 */
public class JDBCUtils {
    private static String url;
    private  static String user;
    private static  String password;
    private static  String driver;
    //静态代码块,只会执行一次
    static {
        //读取资源,获取值
        //1.创建Properties集合类
        Properties pro = new Properties();
        try {
            //2.加载文件
            pro.load(new FileReader("src/jdbc.properties"));
            //3.获取数据,赋值
            url = pro.getProperty("url");
            user = pro.getProperty("user");
            password = pro.getProperty("password");
            driver = pro.getProperty("driver");
            //4.注册驱动
            Class.forName(driver);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    public static Connection getConnection() throws SQLException {
        return DriverManager.getConnection(url,user,password);
    }

    /**
     * 释放资源
     * @param rs
     * @param stmt
     * @param coon
     */
    public static void close(ResultSet rs,Statement stmt, Connection coon){
        if (rs != null){
            try{
                rs.close();
            }catch (SQLException e){
                e.printStackTrace();
            }
        }
        if (stmt != null){
            try{
                stmt.close();
            }catch (SQLException e){
                e.printStackTrace();
            }
        }
        if (coon != null){
            try{
                coon.close();
            }catch (SQLException e){
                e.printStackTrace();
            }
        }
    }
    /*
        重写函数,参数个数不同
      */
    public static void close(Statement stmt, Connection coon){
        if (stmt != null){
            try{
                stmt.close();
            }catch (SQLException e){
                e.printStackTrace();
            }
        }
        if (coon != null){
            try{
                coon.close();
            }catch (SQLException e){
                e.printStackTrace();
            }
        }
    }
}


实例 - - 登录

1.通过键盘录入用户名和密码
2.判断用户是否登录成功

在这里插入图片描述
使用到的JDBCUtils类参照上面工具类代码,配置文件根据自己情况修改
代码.java

public class jdbcDemo7 {
    /**
     * 登录函数
     */
    public  boolean login(String username,String password){
        if (username == null && password == null){
            return false;
        }
        Connection conn = null;
        PreparedStatement pstmt = null;
        //Statement stmt = null;
        ResultSet rs = null;
        //连接数据检验是否正确
        try {
            //1.获取数据库连接
            conn = JDBCUtils.getConnection();

            //2.定义sql
            String sql = "select * from user where username= ? and password=?";

            //3.获取执行sql的对象,预编译
             pstmt = conn.prepareStatement(sql);
            // stmt = conn.createStatement();

            //4.给?赋值
            pstmt.setString(1,username);
            pstmt.setString(2,password);

            //5.执行查询
            rs = pstmt.executeQuery();//这里不需要传参
            // rs = stmt.executeQuery(sql);

            return rs.next();
            
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JDBCUtils.close(rs,pstmt,conn);
        }
        return false;
    }

      /*
        测试
        */
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.print("请输入用户名:");
        String username = sc.nextLine();
        System.out.print("请输入密码:");
        String password = sc.next();
      // boolean flag = login(username,password);//直接调用静态方法static
        boolean flag = new jdbcDemo7().login(username,password);//非静态方法用这种方式访问
        if(flag){
           System.out.println("登录成功");
        }else{
           System.out.println("用户名或密码错误");
        }
     }
}

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

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

相关文章

6年Android开发最终被优,事后加入车载开发,开启新起点~

如今传统Android 开发行业的岗位越发紧张了,经过去年一些互联网大厂的部门人员优化、开源截流等操作,加快了内卷的速度,原本坐山观虎斗我,没想到也被卷入其中。 1. Android 开发6年,无情中招 就去年年底,…

RZ/G2UL核心板-40℃低温启动测试

1. 测试对象HD-G2UL-EVM基于HD-G2UL-CORE工业级核心板设计,一路千兆网口、一路CAN-bus、 3路TTL UART、LCD、WiFi、CSI 摄像头接口等,接口丰富,适用于工业现场应用需求,亦方便用户评估核心板及CPU的性能。HD-G2UL-CORE系列工业级核…

铁路与公路

蓝桥杯集训每日一题acwing4074 某国家有 n 个城市(编号 1∼n)和 m 条双向铁路。 每条铁路连接两个不同的城市,没有两条铁路连接同一对城市。 除了铁路以外,该国家还有公路。 对于每对不同的城市 x,y,当且仅当它们之…

Mars3D美丽乡村系统发布

近日,我们基于Mars3D平台做了一个Mars3D美丽乡村应用系统,于2023年3月7日正式发布上线!该系统提供一个PC浏览器端的“样板房”项目模版,包含常用的地图基础功能,可基于该平台开发新项目,更换数据即可快速形…

C++继承派生以及虚基类的内存分布

C中类有3种权限&#xff1a;public、protected、private。&#xff08;本文为《直击招聘》的笔记总结&#xff09;。如果没有指明默认为private&#xff0c;定义class A如下class A {int x; public:void displaya() {cout << "A::x:" << &x <<…

理解进程、通过调用 fork 函数创建进程

文章目录1.理解进程1.1 CPU核的个数与进程数1.2 进程 ID2.通过调用 fork 函数创建进程2.1 fork.c1.理解进程 进程&#xff08;Process&#xff09;&#xff0c;其定义如下&#xff1a;“占用内存空间的正在运行的程序”。 假如各位从网上下载了 LBreakout 游戏并安装到硬盘。…

CS项目实训-Java 银行ATM机

摘 要 本次课程设计主要目的是培养我们面向对象软件开发的思维&#xff0c;初步了解软件开发的一般流程。提高编程的实际动手能力并增强大家对面向对象的了解。这次课程设计的主要内容是开发一个应用程序&#xff0c;我们小组设计的ATM柜员机&#xff0c;它主要是由各个indows窗…

05 | 如何安全、快速地接入OAuth 2.0?

05 | 如何安全、快速地接入OAuth 2.0&#xff1f; 构建第三方软件应用 第一点&#xff0c;注册信息 小兔软件的研发人员提前登录到京东商家开放平台进行手动注册&#xff0c;以便后续使用这些注册的相关信息来请求访问令牌。兔软件需要先拥有自己的 app_id 和 app_serect 等信…

联想笔记本电脑开机后一直转圈无法启动怎么办?

联想笔记本电脑开机后一直转圈无法启动怎么办&#xff1f;在正常开启电脑的过程中&#xff0c;系统进入到加载页面&#xff0c;但是却一直无法正常的启动。进行系统的重新启动依然是无法正常的使用。遇到这个情况需要进行系统的重置。接下来我们来看看详细的解决方法分享吧。 准…

实现用户操作日志记录

Java记录操作日志 java自带的日志框架是java.util.logging&#xff08;JUL&#xff09;&#xff0c;从JDK1.4&#xff08;2002&#xff09;开始捆绑在JDK中。可以使用JUL来记录操作日志。以下是使用JUL记录事务的示例&#xff1a; // java.util.logging java.util.logging.Lo…

网分线缆测试和dc-block

今天的好苹果和坏苹果 好苹果&#xff1a;是校准件和网分都是好的&#xff0c;又给了我一次复盘的机会 网分测试线缆&#xff1a; 1.网分直接复位&#xff0c;如果网分复位是校准状态&#xff0c;且解的是精密转接头&#xff0c;BNC的&#xff0c;可以不校准&#xff0c;结果差…

【高中数学教资】教案设计通用模板

前言 本文针对的是高中数学教师资格证笔试中最后的大题——教案设计&#xff08;含设计意图&#xff0c;文末有2022下半年高中数学教资教案设计大题&#xff09;。并附上高中数学404教资考点大纲&#xff0c;还有在学习中发现的一些可以免费学习网站推荐。 一、高中数学404考…

List系列集合

一. List集合特点、特有API List的实现类的底层原理 ArrayList底层是基于数组实现的&#xff1a;根据索引定位元素快&#xff0c;增删相对慢。LinkedList底层基于双链表实现的&#xff1a;查询元素慢&#xff0c;增删首尾元素是非常快的。public class ListDemo01 {public sta…

SerDes---CDR技术

1、为什么需要CDR 时钟数据恢复主要完成两个工作&#xff0c;一个是时钟恢复&#xff0c;一个是数据重定时&#xff0c;也就是数据的恢复。时钟恢复主要是从接收到的 NRZ&#xff08;非归零码&#xff09;码中将嵌入在数据中的时钟信息提取出来。 2、CDR种类 PLL-Based CDROve…

【信号与系统笔记】第一章 绪论

1.1信号传输系统 信息传输的任务 将带有信息的信号&#xff0c;通过某种系统由发送者传送给接收者。 通信系统的组成 转换器&#xff1a;把消息转换为电信号或者把电信号还原成消息信道&#xff1a;信号传输的通道&#xff0c;广义上来说。发射机和接收机也可以是信道的一部分…

【RabbitMQ】Producer之publisher confirm、transaction - 基于AMQP 0-9-1(二)

上篇文章主要介绍Producer的mandatory参数&#xff0c;备份队列和TTL的内容&#xff0c;这篇文章讲继续介绍Producer端的开发&#xff0c;主要包括发布方确认和事务机制。 发布方确认 消息持久化机制可以保证应服务器出现异常导致消息丢失的问题&#xff0c;但是Producer将消…

线程池ThreadPoolExecutor,从0到0.6

ThreadPoolExecutor是JDK提供的在java.util.concurrent包中的一个用于创建线程池的工具类。 一、ThreadPoolExecutor的7个参数 corePoolSize&#xff1a;核心线程数&#xff0c;线程池中保留的最小的线程数量&#xff0c;即使它们是空闲的也不会被销毁&#xff0c;除非allowCor…

Modbus转profinet网关连接1200PLC在博图组态与驱动器通讯程序案例

本案例给大家介绍由兴达易控modbus转profinet网关连接1200PLC在博图软件无需编程&#xff0c;实现1200Profinet转modbus与驱动器通讯的程序案例 硬件连接&#xff1a;1200PLC一台&#xff1b;英威腾DA180系列驱动器一台&#xff1b;兴达易控modbus转profinet网关一台 下面就是…

【Git】拉取 Pull Requests 测试的两种方法

文章目录前言参考目录方法说明方法一&#xff1a;直接拉取方法二&#xff1a;使用 diff 文件2.1、保存 diff 文件2.2、新建分支并执行文件前言 最近有参与到框架帮忙进行简单的 Pull Requests&#xff08;以下简称 PR&#xff09; 测试&#xff0c;因为也是第一次接触到这种操…

代码随想录 动态规划||01背包理论 416

Day3601背包理论基础01背包有n件物品和一个最多能背重量为w 的背包。第i件物品的重量是weight[i]&#xff0c;得到的价值是value[i] 。每件物品只能用一次&#xff0c;求解将哪些物品装入背包里物品价值总和最大。暴力的解法是指数级别的时间复杂度。进而才需要动态规划的解法来…