【MySQL】JDBC(含settings.xml文件配置/配置国内镜像以及pom.xml文件修改)

JDBC(Java Data Base Connectivity, Java数据库连接 )是Java程序和数据库之间的桥梁,包含 了⼀套Java定义的用于执行SQL语句的接口,使开发者能够编写数据库的程序。JDBC 的主要作用是: 与数据库建立连接、发送SQL语句和处理数据库执行结果。

  • 接口是一套规则,接口中定义一系列系统方法,这些方法由具体的实现类去完成实现逻辑。而JDBC是Java平台提供的接口,具体的实现是由数据库厂商完成的。
  • 之前学的都是操作数据库的语言------SQL,而JDBC是Java语言中用来执行SQL语句的一套API(应用程序编程接口),它让Java开发者能够通过编写代码来发送SQL语句,并处理数据库返回的结果。
  • 简单来说,SQL是"语言",JDBC是Java访问数据库的"工具"。

访问数据库要经过以下几个重要步骤

  1. 确定数据库服务器的地址,端口号
  2. 建立连接,用户名,密码(不同的数据库以不同的协议建立连接)
  3. 发送要执行的SQL语句:以什么样的形式发送,这里主要考虑编码的格式(协议------就是事先商量好的规则)
  4. 接受返回的结果(结果集,受影响的行数)使用Java操作数据库,必须处理不同数据库对数据的编解码,这些是由数据库厂商实现的。
  5. 关闭连接。

以上的五步对应到JDBC中就是:

  1. 确定数据源
  2. 数据库连接
  3. 确定执行对象
  4. 得到结果集
  5. 释放资源,关闭连接

总结

  • Java是把以上操作步骤定义了相应的接⼝,具体的实现交给数据库⼚商去做,Java程序员只需要按照需要调用接⼝中定义的方法即可,这样不论使用什么数据库,都对于Java程序没有任 何影响,即便是换⼀个数据库,也只需要换⼀下相应厂商的实现依赖。
  • JDBC使用过程可以概括为:加载数据库厂商的驱动包、建⽴连接、创建Statement、执行SQL、 处理结果释放资源和关闭连接

1.使用JDBC

1.1 settings.xml文件配置-配置国内镜像

首先需要打开idea的settings设置界面,通过以下的操作找到idea中内置的Maven,Maven就类似于应用商店,在maven仓库中维护了所有的Java工程需要用到的依赖:

但是这个maven仓库默认是国外的,会导致下载速度慢等问题,所以要把它修改成国内的,就是在 Maven 的 settings.xml 中配置国内镜像(如阿里云),那么要修改 settings.xml 的配置,要找到idea的安装路径:

右击 idea 打开属性,选择打开文件所在位置,然后通过以下的具体路径找到 settings.xml文件:

然后打开 settings.xml 文件,修改这个Maven配置文件,在 <mirror></mirror> 标签中添加 mirror 子节点,将以下的代码整个复制替换到 <mirror> 标签中(镜像的父节点也统一替换掉):

XML 复制代码
<mirrors>
    <!-- mirror
     | Specifies a repository mirror site to use instead of a given repository. The repository that
     | this mirror serves has an ID that matches the mirrorOf element of this mirror. IDs are used
     | for inheritance and direct lookup purposes, and must be unique across the set of mirrors.
     |
    -->
    <!-- 加入如下mirror节点 使用国内阿里云仓库镜像  开始 -->
    <mirror>
        <id>aliyunmaven</id>
        <mirrorOf>*</mirrorOf>
        <name>阿里云公共仓库</name>
        <url>https://maven.aliyun.com/repository/public</url>
    </mirror>
    <mirror>
        <id>central</id>
        <mirrorOf>*</mirrorOf>
        <name>aliyun central</name>
        <url>https://maven.aliyun.com/repository/central</url>
    </mirror>
    <mirror>
        <id>spring</id>
        <mirrorOf>*</mirrorOf>
        <name>aliyun spring</name>
        <url>https://maven.aliyun.com/repository/spring</url>
    </mirror>
    <!-- 加入如下mirror节点 使用国内阿里云仓库镜像  结束-->
</mirrors>

替换如下图,然后保存修改结果:

修改完配置之后,我们可以将 settings.xml 这个文件复制到我们自定义的目录中,然后修改设置文件路径,同样的 repository 也一样:

如果设置完目录路径没有找到记得点击刷新,或者重启 idea:

1.2 创建Maven工程并修改 pom.xml 文件

完成上述的操作,现在我们开始创建一个Maven工程:

打开这个项目之后,就会直接显示 pom.xml 文件:

我们需要在工程中的pom.xml中的新增的<dependencies></dependencies>标签中添加MySQL依赖,在添加之前,我们需要获取MySQL驱动包(通过在 pom.xml 中声明依赖,Maven 会根据坐标自动从仓库(本地或镜像)下载对应的 .jar 文件):

在Maven仓库Maven Repository: Search/Browse/Explore搜索MySQL,找到下载的对应MySQL版本的驱动包:

如以上画红框的XML,就是要添加进pom.xml的依赖,添加进去之后,一定要记得点击「刷新」按钮(🔄)刷新,如果没有找到,就到Maven面板里面点击刷新:

就会在 repository 目录之下生成许多文件:

但是,如果上述XML添加进去之后刷新后报错或者关闭Maven项目后再打开报错了,那么将坐标改成新的坐标,然后再点击刷新:

原因 :改为新坐标之前刷新生成的文件是 Maven 按照新坐标 com.mysql:mysql-connector-j 自动下载的驱动包(因为旧坐标 mysql:mysql-connector-java 从 8.0.31 起就被重定向到新坐标了)。

最后,如果在Maven项目左侧目录中出现了8.0.33,也就是刚才在pom.xml中添加的依赖,就说明已经加载到工程中了:

以上的过程也就是------加载数据库厂商的驱动包。接下来通过数据库厂商提供的驱动来操作数据库,也就是------建立数据库连接,在开始建立之前,我们先学习JDBC常用的接口和类。

1.3 JDBC常用的接口和类

1.3.1 DriverManager 和 DataSource

  • DataSource驱动管理类,用于管理JDBC驱动程序,可以从驱动程序中获取数据库连接,始于 JDK1.1。
  • DataSource数据源是DriverManager的替代方案,是一个接口,始于JDK1.4,是获取数据库连接的首选方法, 推荐使用。

两者区别:

  1. DriverManager和DataSource都可以获取到数据库连接,但它们之间存着着⼀些区别,主要在于连接的管理方式和资源利用效率。
  2. 连接管理方式不同:
    1. DriverManager每次调用 getConnection 方法都会初始化⼀个新的连接,使用完成后会关闭真实连接,导致资源浪费。也就是说,该类每调用一次 getConnection 方法,都会开启一个新的会话/客户端。
    2. DataSource使用了连接池的技术,会在初始化时创建⼀定数量的数据库连接,这些连接可以重复使用,关闭时并不是真正关闭连接,而是将连接归还给连接池,以供后续使用,有效地提高资源利用率和和性能。
当使用DriverManager来获取数据库连接时,需要先手动加载数据库厂商提供的驱动类,使用以下的代码获取:
java 复制代码
Class.forName("com.mysql.cj.jdbc.Driver");

以上代码中参数是通过完全限定名加载指定类到JVM ,也就是说,Class.forName("com.mysql.cj.jdbc.Driver");本质是让 JVM 加载 MySQL 驱动类,并执行它的静态代码块,MySQL 驱动类(Driver)的核心源码:

【注意:MySQL 5.x 版本(JDBC 3.0 及以下):必须手动加载。MySQL 8.0+ 版本(JDBC 4.0+):可以省略手动加载,但是建议保留。】

手动加载完驱动类之后,使用DriverManager类中的getConnection()方法获取数据库连接,该方法的返回值类型为Connection类,以下是源码:

  • 其中,该方法的第一个参数 url :JDBC 连接数据库的 URL 地址,用来指定要连接的数据库类型、地址、端口、库名等信息。格式规范(以 MySQL 为例):
  • 第二个参数 user :数据库的 用户名,用于身份认证,验证你是否有权限访问该数据库。
  • 第三个参数 password :数据库用户对应的 密码,和 user 配对,完成身份认证。

示例:forName方法和getConneaction方法会抛出异常,以下URL中的数据库以DesignTable为例

java 复制代码
public static void main(String[] args) {
    try {
        //加载数据库厂商提供的驱动
        Class.forName("com.mysql.cj.jdbc.Driver");
        //获取数据库连接
        Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/DesignTable?characterEncoding=utf8" +
                    "&allowPublicKeyRetrieval=true&useSSL=false", "root", "123456");
    } catch(ClassNotFoundException e) {
        e.printStackTrace();
    } catch(SQLException e) {
        e.printStackTrace();
    }
}

当使用DataSource来获取数据库连接(getConnection())时,完全不用手动加载驱动,因为连接池会自动处理驱动加载

DataSource是JDBC 定义的通用数据库连接接口,只规定了 "获取连接" 的方法 ,但不实现具体逻辑;而 MysqlDataSource 是 MySQL 驱动专门为 MySQL 数据库编写的 DataSource 实现类,是 DataSource 接口的「MySQL 专属版本」。简单说:DataSource 是 "抽象的连接池标准",MysqlDataSource 是 "MySQL 对这个标准的具体落地"。

因此,在使用 DataSource 获取数据库连接之前,先使用 MysqlDataSource 实现类配置一下MySQL连接的信息(URL,User,Password):

创建MysqlDataSource对象,并使用setURL(),setUser(),setPassword()方法设置连接信息,最后DataSource 获取 MysqlDataSource 设置的连接信息,并使用getConnection()方法实现数据库连接。

示例:注意getConnection()是不带参数的。

java 复制代码
public static void main(String[] args) {
    //定义MySQL数据源对象
    MysqlDataSoruce mysqlDataSoruce = new MysqlDataSource();
    //设置数据库连接信息
    mysqlDataSource.setURL("jdbc:mysql://127.0.0.1:3306/DesignTable?characterEncoding=utf8" +
                    "&allowPublicKeyRetrieval=true&useSSL=false");
    mysqlDataSource.setUser("root");
    mysqlDataSource.setPassword("123456");

    //定义JDBC数据源对象
    DataSource dataSource = mysqlDataSource;

    try {
        //获取数据库连接
        Connection connection = dataSource.getConnection();
    } catch(SQLException e) {
        e.printStackTrace();
    }
}

通过上述的操作,已经将数据库与Java建立了联系(JDBC),那么接下来要在Java中对数据库进行操作。

1.3.2 Connection 数据库连接

数据库连接(会话)对象,在连接的上下文中执行SQL语句并返回结果。也就是开始使用插入/更新/查询语句。

详细版本:Connection 接口是 Java 程序和数据库之间的 **「桥梁 / 会话」** ------ 所有对数据库的操作(执行 SQL、事务管理、创建执行对象)都必须通过 Connection 来完成,它是 JDBC 中最核心的接口之一。

Connection 接口的作用 最常见的就是创建执行 SQL 的对象: Connection 最常用的功能是创建 Statement/PreparedStatement 对象 ------ 这些对象是真正执行 SQL 的「工具」,没有 Connection 就无法创建**。**


Statement
  • 用于执行静态SQL语句并返回执行结果,由于只能执行静态语句,所以这里会有⼀个问题,假设⼀ 个语句中需要动态的参数,比如where子句中的条件,那么只能通过字符串拼接的方式组装完成的 SQL语句,比如:

    java 复制代码
    String sql = "select id,name,sn,mail,class_id from student where name = '" + name + "'";
  • 上述字符串拼接形式构造SQL语句 时,如果不处理参数中的特殊字符就会造成SQL注入,这是⼀个非常严重的安全性问题。

  • 上述查询语句,以数据库 designtable 中的student表为例:

SQL注入即是指web应用程序++对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应 ⽤程序中事先定义好的查询语句的结尾上添加额外的SQL语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询++,从而进⼀步得到相应的数据信息。

示例 :查询名字为王五的记录,正常执行:

构造恶意参数来执行非法的SQL,把正常的条件值王五替换成**'or/**/1=1;#'** :

以上查询出来了所有的记录,此时学生表中的数据全部都将泄漏,这就是 使用Statement对象 执行SQL语句会遇到的 SQL注入 问题。

为了解决这个问题,可以使用 PreparedStatement 接口,该接口继承于 Statement :

PreparedStatement

预编译SQL语句对象,SQL语句被预编译并存储在PreparedStatement对象中,可以使用该对象多次执行SQL语句,同时可以解决SQL注入问题。

与 Statement 最关键的区别就在 SQL语句上,Statement使用的是字符串拼接,这样极易被注入,而 PreparedStatement 使用的是占位符(?) ,这样天然的预防了注入的风险:

java 复制代码
String sql = "select id,name,sn,mail,class_id from student where name = ?";

1.3.3 executeQuery() 和 executeUpdate()

executeQuery()

执行结果返回的是⼀个结果集,通常用于select 操作。返回值的类型是ResultSet类。

executeUpdate()

执行结果返回的是⼀个整形(表示受影响的行数),通常用于insert,update,delete操作。返回值的类型是整型。


Statement 和 PrepareStatement 的区别

核心:Statement 是「简单 SQL 执行器」,每次执行都重新编译 SQL,有 SQL 注入风险;PreparedStatement 是「预编译 SQL 执行器」,SQL 只编译一次、可复用,能防 SQL 注入,是生产环境的首选。

执行方法:传 SQL vs 无参执行

  • Statement:必须在执行时传入完整 SQL 字符串(因为每次都要编译),即executeQuery(sql)/executeUpdate(sql)
  • PreparedStatement:预编译时已传入 SQL,执行时无参,即executeQuery()/executeUpdate()

参数传递:字符串拼接 vs 占位符

  • Statement:字符串拼接(极易被注入):恶意输入的**'or/**/1=1;#'**被拼接到 SQL 中,数据库会把它当成合法 SQL 指令执行。
  • PreparedStatement:占位符(天然防注入):PreparedStatement 把「SQL 结构」和「参数值」完全分离 ------------ 用 ? 占位符 + setXxx() 赋值 :SQL 预编译时只解析结构(select id,name,sn,mail,class_id from student where name = ? ),参数值会被数据库当作「纯数据」处理,即使用 setXxx() 方法用真实值去替换 ?,不会被解析为 SQL 指令,从根源杜绝注入
    • 在前面介绍 Connection 接口时说过,执行SQL语句的对象 Statement 和 PrepareStatement 分别是 connection.createStatement() 和 connection.prepareStatement(sql),也就是在创建 Statement对象时不需要闯入SQL语句,而创建 PrepareStatement对象时需要传入SQL语句,这是为了防止SQL注入

对比总结图:

1.3.4 ResultSet 结果集

  • 是⼀个查询结果集的数据表,通常由执行查询操作的语句生成。执行插入,更新,删除的操作不需要用到,因为查询的结果只会显示受影响的行数。
  • ResultSet对象维护了⼀个指向当前数据行的游标,最初游标位于第⼀行之前,调用next方法法将游标移动到下⼀行,当ResultSet中没有更多的数据行时返回false,所以可以在while循环中使⽤它来遍历结果集。------ 迭代器
  • ResultSet接⼝提供了getter方法法(getString、getBoolean、getLong 等),用于从当前行检索列值,可以使用列的索引号或列的名称来检索值 。⼀般来说,使用列索引会更有效率,索引编号从1开始,按照从左 到右的顺序读取。

1.3.5 释放资源

在整个数据库访问过程中创建的对象都需要释放,包括:ResultSet,Statement和Connection, 后创建的先释放。使用ResultSet,Statement和Connection的close()方法释放,该方法会抛出一个异常。

1.3.6 示例

到这里,JDBC中常用的接口和类全部学习完成,现在我们利用上述学的知识在Java中实现一个SQL查询语句,例如以下:

1)使用 DriverManager 和 Statement
java 复制代码
public class Demo_DataSource {
    public static void main(String[] args) {
        Connection connection = null;
        Statement statement = null;
        ResultSet resultset = null;
        
        try {
            //1.加载数据库厂商提供的驱动
            Class.forName("com.mysql.cj.jdbc.Driver");
            //2.获取数据库连接
            connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/DesignTable?characterEncoding=utf8" +
                    "&allowPublicKeyRetrieval=true&useSSL=false", "root", "123456");
            //3.创建Statement对象
            statement = connection.createStatement();
            //4.定义SQL语句
            System.out.println("请输入学生姓名:");
            Scanner scanner = new Scanner(System.in);
            //接收用户输入
            String name = scanner.next();
            String sql = "select id,name,sn,mail,class_id from student where name = '" + name + "'";
            //5.执行SQL语句
            resultset = statement.executeQuety(sql);
            //6.遍历结果集,获取数据
            while (resultSet.next()) {
                long stuId = resultSet.getLong(1);
                String stuName = resultSet.getString(2);
                String stuSn = resultSet.getString(3);
                String stuMail = resultSet.getString(4);
                Long classId = resultSet.getLong(5);
                System.out.println(MessageFormat.format("学生编号={0},姓名={1},学号={2},邮箱={3},班级编号={4}",
                        stuId,stuName,stuSn,stuMail,classId));
            }

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            //7.依次释放资源,关闭连接
            if(resultset != null) {
                try {
                    resultSet.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(statement != null) {
                try {
                    statement.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(connection != null) {
                try {
                    connection.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

输出结果:

但是,通过前面的学习我们直到,Statement会有SQL注入的问题,因此可以使用PreparedStatement预处理执行SQL语句。并且 DriverManager 类每次使用都会获取一个新的连接,导致浪费,那么可以使用 DataSource 接口,该接口一次链接可以执行很多SQL,直到关闭资源close(通过一个连接池管理很多个连接,当需要SQL执行的时候,从连接池拿一个空间连接出来,用完后返还给连接池)。

2)优化:使用 DataSource 和 PreparedStatement
java 复制代码
public class Demo_DataSource {
    public static void main(String[] args) {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultset = null;
        
        //定义MySQL数据源
        MysqlDataSource mysqlDataSource = new MysqlDataSource();
        //设置连接信息
        mysqlDataSource.setURL("jdbc:mysql://127.0.0.1:3306/DesignTable?characterEncoding=utf8" +
                "&allowPublicKeyRetrieval=true&useSSL=false");
        mysqlDataSource.setUser("root");
        mysqlDataSource.setPassword("123456");
    
        //1.定义JDBC数据源
        DataSource dataSource = mysqlDataSource;
        
        try {
            //2.获取数据库连接
            connection = dataSource.getConnection();
            //3.创建预处理对象
            //定义SQL语句
            String sql = "select id,name,sn,mail,class_id from student where name = ?";
            preparedStatement = connection.preparedStatement(sql);
            //接受用户输入
            System.out.println("请输入学生姓名:");
            Scanner scanner = new Scanner(System.in);
            String name = scanner.next();
            //4.用真实值替换占位符(?)
            preparedStatement.setString(1,name);
            //5.执行SQL,获取结果集
            resultset = preparedStatement.executeQuery();
            //6.遍历结果集
            while (resultSet.next()) {
                long stuId = resultSet.getLong(1);//也可以是具体的列,例如1改成id
                String stuName = resultSet.getString(2);
                String stuSn = resultSet.getString(3);
                String stuMail = resultSet.getString(4);
                Long classId = resultSet.getLong(5);
                System.out.println(MessageFormat.format("学生编号={0},姓名={1},学号={2},邮箱={3},班级编号={4}",
                        stuId,stuName,stuSn,stuMail,classId));
            }
        }catch (SQLException e) {
            e.printStackTrace();
        } finally {
            //6.依次释放资源,关闭连接
            if (resultSet != null) {
                try {
                    resultSet.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (preparedStatement != null) {
                try {
                    preparedStatement.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (connection != null) {
                try {
                    connection.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
    

输出结果:

3)再优化:封装

可以将数据源信息,资源的关闭单独在一个类DBUtil中进行封装,想要使用的时候再进行调用。

  • 在DBUtil类中,定义静态成员变量:数据源DataSource;定义静态常量:URL,User,Password,将MySQL数据源的定义与连接信息的设置定义在静态构造方法中,这样当类加载时,就会执行数据源的初始化。
  • 由于在获取数据库连接时需要DataSource.getCOnnection()方法,那么创建一个公共方法getConnection()进行返回获取,记得抛出一个异常。
  • 最后close()方法关闭资源。
  • 可以将DBUtil 构造方法私有化,防止new这个对象。
java 复制代码
public class DBUtil {
    //数据源
    private static DataSource dataSource = null;
    //数据库连接串
    private static final Strinf URL = "jdbc:mysql://127.0.0.1:3306/DesignTable?characterEncoding=utf8" +
            "&allowPublicKeyRetrieval=true&useSSL=false";
    private static final String USER = "root";
    private static final String PASSWORD = "123456";
    
    //当类加载到JVM时,执行数据源的初始化
    static {
        MysqlDataSource mysqlDataSOurce = new MysqlDataSource();
        mysqlDataSOurce.setURL(URL);
        mysqlDataSOurce.setUser(USER);
        mysqlDataSOurce.setPassword(PASSWORD);
        dataSource  = mysqlDataSOurce; 
    }

    //构造方法私有化,防止new这个对象
    private DBUtil() {};

    //获取数据库连接
    public static Connection getConnection() throws SQLException {
        return dataSource.getConnection();
    }
    
    //释放资源,关闭连接
    public static void close(ResultSet resultSet, Statement statement, Connection connection) {
        if (resultSet != null) {
            try {
                resultSet.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (statement != null) {
            try {
                statement.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (connection != null) {
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

接下来,我们以往数据库中新增insert一条关于学生小华的记录为例在Java中执行SQL语句:

注意:插入操作不需要定义结果集对象ResultSet,insert返回的是受影响的行数

java 复制代码
public class Demo_insert {
    public static void main(String[] args) {
        Connection connection = null;
        PreparedStatement preparedStatement = null;    
        
        try {
            //1.获取数据连接
            connection = DBUtil.getConnection();
            //2.定义SQL语句
            String sql = "insert into student(name,sn,mail,class_id) values(?,?,?,?)";
            //3.创建预处理对象
            preparedStatement = connection.preparedStatement(sql);
            //4.接受用户输入
            Scanner scanner = new Scanner(System.in);
            System.out.println("请输入姓名:");
            String name = scanner.next();

            System.out.println("请输入学号:");
            String sn = scanner.next();

            System.out.println("请输入邮箱:");
            String mail = scanner.next();

            System.out.println("请输入班级编号:");
            Long classId = Long.valueOf(scanner.next());

            //5.用真实值替换?
            preparedStatement.setString(1,name);
            preparedStatement.setString(2,sn);
            preparedStatement.setString(3,mail);
            preparedStatement.setLong(4,classId);
            //6.执行SQL语句
            int row = preparedStatement.executeUpdate();
            //7.判断结果    
            if (row == 1) {
                System.out.println("插入成功");
            }else {
                System.out.println("插入失败");
            }
        }catch (SQLException e) {
            e.printStackTrace();
        } finally {
            //8.释放资源,关闭连接
            DBUtil.close(null,preparedStatement,connection);
        }
    }
}
    

输出结果:执行插入小华的数据记录,插入成功后,当我们打开数据库的客户端,去查询表中的记录,发现确实有增加了一条数据,这就说明了数据库与Java之间相互连接了(JDBC):

相关推荐
FirstFrost --sy3 小时前
MySQL内置函数
数据库·mysql
2401_879693873 小时前
将Python Web应用部署到服务器(Docker + Nginx)
jvm·数据库·python
reembarkation3 小时前
光标在a-select,鼠标已经移出,下拉框跟随页面滚动
java·数据库·sql
eggwyw3 小时前
MySQL-练习-数据汇总-CASE WHEN
数据库·mysql
星轨zb3 小时前
通过实际demo掌握SpringSecurity+MP中的基本框架搭建
数据库·spring boot·spring security·mp
treacle田3 小时前
达梦数据库-配置本地守护进程dmwatcher服务-记录总结
数据库·达梦数据库·达梦数据库local数据守护
wyt5314294 小时前
Redis的安装教程(Windows+Linux)【超详细】
linux·数据库·redis
CeshirenTester4 小时前
从数据库到结构化用例:一套可落地的测试智能体架构
数据库·架构
2301_793804694 小时前
Python数据库操作:SQLAlchemy ORM指南
jvm·数据库·python