JDBC相关内容

news2024/11/19 17:37:05

第1章:JDBC概述

1.1 数据的持久化

  • 持久化(persistence):把数据保存到可掉电式存储设备中以供之后使用。大多数情况下,特别是企业级应用,数据持久化意味着将内存中的数据保存到硬盘上加以”固化”,而持久化的实现过程大多通过各种关系数据库来完成。

  • 持久化的主要应用是将内存中的数据存储在关系型数据库中,当然也可以存储在磁盘文件、XML数据文件中。

1.2 Java中的数据存储技术

  • 在Java中,数据库存取技术可分为如下几类:

    • JDBC直接访问数据库

    • JDO (Java Data Object )技术

    • 第三方O/R工具,如Hibernate, Mybatis 等

  • JDBC是java访问数据库的基石,JDO、Hibernate、MyBatis等只是更好的封装了JDBC。

1.3 JDBC介绍

  • JDBC(Java Database Connectivity)是一个独立于特定数据库管理系统、通用的SQL数据库存取和操作的公共接口(一组API),定义了用来访问数据库的标准Java类库,(java.sql,javax.sql)使用这些类库可以以一种标准的方法、方便地访问数据库资源。

  • JDBC为访问不同的数据库提供了一种统一的途径,为开发者屏蔽了一些细节问题。

  • JDBC的目标是使Java程序员使用JDBC可以连接任何提供了JDBC驱动程序的数据库系统,这样就使得程序员无需对特定的数据库系统的特点有过多的了解,从而大大简化和加快了开发过程。

  • 如果没有JDBC,那么Java程序访问数据库时是这样的:


  • 有了JDBC,Java程序访问数据库时是这样的:


  • 总结如下:

1.4 JDBC体系结构

  • JDBC接口(API)包括两个层次:

    • 面向应用的API:Java API,抽象接口,供应用程序开发人员使用(连接数据库,执行SQL语句,获得结果)。

    • 面向数据库的API:Java Driver API,供开发商开发数据库驱动程序用。

JDBC是sun公司提供一套用于数据库操作的接口,java程序员只需要面向这套接口编程即可。

不同的数据库厂商,需要针对这套接口,提供不同实现。不同的实现的集合,即为不同数据库的驱动。 ————面向接口编程

1.5 JDBC程序编写步骤

补充:ODBC(Open Database Connectivity,开放式数据库连接),是微软在Windows平台下推出的。使用者在程序中只需要调用ODBC API,由 ODBC 驱动程序将调用转换成为对特定的数据库的调用请求。

第2章:获取数据库连接

2.1 要素一:Driver接口实现类

2.1.1 Driver接口介绍
  • java.sql.Driver 接口是所有 JDBC 驱动程序需要实现的接口。这个接口是提供给数据库厂商使用的,不同数据库厂商提供不同的实现。

  • 在程序中不需要直接去访问实现了 Driver 接口的类,而是由驱动程序管理器类(java.sql.DriverManager)去调用这些Driver实现。

    • Oracle的驱动:oracle.jdbc.driver.OracleDriver

    • mySql的驱动: com.mysql.jdbc.Driver

  • 将上述jar包拷贝到Java工程的一个目录中,习惯上新建一个lib文件夹。

在驱动jar上右键-->Build Path-->Add to Build Path

注意:如果是Dynamic Web Project(动态的web项目)话,则是把驱动jar放到WebContent(有的开发工具叫WebRoot)目录中的WEB-INF目录中的lib目录下即可

2.1.2 加载与注册JDBC驱动
  • 加载驱动:加载 JDBC 驱动需调用 Class 类的静态方法 forName(),向其传递要加载的 JDBC 驱动的类名

    • Class.forName(“com.mysql.jdbc.Driver”);

  • 注册驱动:DriverManager 类是驱动程序管理器类,负责管理驱动程序

    • 使用DriverManager.registerDriver(com.mysql.jdbc.Driver)来注册驱动

    • 通常不用显式调用 DriverManager 类的 registerDriver() 方法来注册驱动程序类的实例,因为 Driver 接口的驱动程序类都包含了静态代码块,在这个静态代码块中,会调用 DriverManager.registerDriver() 方法来注册自身的一个实例。下图是MySQL的Driver实现类的源码:

2.2 要素二:URL

  • JDBC URL 用于标识一个被注册的驱动程序,驱动程序管理器通过这个 URL 选择正确的驱动程序,从而建立到数据库的连接。

  • JDBC URL的标准由三部分组成,各部分间用冒号分隔。

    • jdbc:子协议:子名称

    • 协议:JDBC URL中的协议总是jdbc

    • 子协议:子协议用于标识一个数据库驱动程序

    • 子名称:一种标识数据库的方法。子名称可以依不同的子协议而变化,用子名称的目的是为了定位数据库提供足够的信息。包含主机名(对应服务端的ip地址),端口号,数据库名

  • 举例:jdbc:mysql://localhost:3306/test

  • 几种常用数据库的 JDBC URL

    • MySQL的连接URL编写方式:

      • jdbc:mysql://主机名称:mysql服务端口号/数据库名称?参数=值&参数=值

      • jdbc:mysql://localhost:3306/wedu

      • jdbc:mysql://localhost:3306/wedu?useUnicode=true&characterEncoding=utf8(如果JDBC程序与服务器端的字符集不一致,会导致乱码,那么可以通过参数指定服务器端的字符集)

      • jdbc:mysql://localhost:3306/wedu?user=root&password=123456

    • Oracle 9i的连接URL编写方式:

      • jdbc:oracle:thin:@主机名称:oracle服务端口号:数据库名称

      • jdbc:oracle:thin:@localhost:1521:wedu

    • SQLServer的连接URL编写方式:

      • jdbc:sqlserver://主机名称:sqlserver服务端口号:DatabaseName=数据库名称

      • jdbc:sqlserver://localhost:1433:DatabaseName=wedu

2.3 要素三:用户名和密码

  • user,password可以用“属性名=属性值”方式告诉数据库

  • 可以调用 DriverManager 类的 getConnection() 方法建立到数据库的连接

2.4 数据库连接方式举例

2.4.1 连接方式一
@Test
    public void testConnection1() {
        try {
            //1.提供java.sql.Driver接口实现类的对象
            Driver driver = null;
            driver = new com.mysql.jdbc.Driver();
​
            //2.提供url,指明具体操作的数据
            String url = "jdbc:mysql://localhost:3306/test";
​
            //3.提供Properties的对象,指明用户名和密码
            Properties info = new Properties();
            info.setProperty("user", "root");
            info.setProperty("password", "abc123");
​
            //4.调用driver的connect(),获取连接
            Connection conn = driver.connect(url, info);
            System.out.println(conn);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

说明:上述代码中显式出现了第三方数据库的API

2.4.2 连接方式二
@Test
    public void testConnection2() {
        try {
            //1.实例化Driver
            String className = "com.mysql.jdbc.Driver";
            Class clazz = Class.forName(className);
            Driver driver = (Driver) clazz.newInstance();
​
            //2.提供url,指明具体操作的数据
            String url = "jdbc:mysql://localhost:3306/test";
​
            //3.提供Properties的对象,指明用户名和密码
            Properties info = new Properties();
            info.setProperty("user", "root");
            info.setProperty("password", "abc123");
​
            //4.调用driver的connect(),获取连接
            Connection conn = driver.connect(url, info);
            System.out.println(conn);
​
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

说明:相较于方式一,这里使用反射实例化Driver,不在代码中体现第三方数据库的API。体现了面向接口编程思想。

2.4.3 连接方式三
   @Test
    public void testConnection3() {
        try {
            //1.数据库连接的4个基本要素:
            String url = "jdbc:mysql://localhost:3306/test";
            String user = "root";
            String password = "abc123";
            String driverName = "com.mysql.jdbc.Driver";
​
            //2.实例化Driver
            Class clazz = Class.forName(driverName);
            Driver driver = (Driver) clazz.newInstance();
            //3.注册驱动
            DriverManager.registerDriver(driver);
            //4.获取连接
            Connection conn = DriverManager.getConnection(url, user, password);
            System.out.println(conn);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

说明:使用DriverManager实现数据库的连接。体会获取连接必要的4个基本要素。

2.4.4 连接方式四
 @Test
    public void testConnection4() {
        try {
            //1.数据库连接的4个基本要素:
            String url = "jdbc:mysql://localhost:3306/test";
            String user = "root";
            String password = "abc123";
            String driverName = "com.mysql.jdbc.Driver";
​
            //2.加载驱动 (①实例化Driver ②注册驱动)
            Class.forName(driverName);
​
​
            //Driver driver = (Driver) clazz.newInstance();
            //3.注册驱动
            //DriverManager.registerDriver(driver);
            /*
            可以注释掉上述代码的原因,是因为在mysql的Driver类中声明有:
            static {
                try {
                    DriverManager.registerDriver(new Driver());
                } catch (SQLException var1) {
                    throw new RuntimeException("Can't register driver!");
                }
            }
​
             */
​
​
            //3.获取连接
            Connection conn = DriverManager.getConnection(url, user, password);
            System.out.println(conn);
        } catch (Exception e) {
            e.printStackTrace();
        }
​
    }

说明:不必显式的注册驱动了。因为在DriverManager的源码中已经存在静态代码块,实现了驱动的注册。

2.4.5 连接方式五(最终版)
@Test
    public  void testConnection5() throws Exception {
        //1.加载配置文件
        InputStream is = ConnectionTest.class.getClassLoader().getResourceAsStream(" ");
        Properties pros = new Properties();
        pros.load(is);
        
        //2.读取配置信息
        String user = pros.getProperty("user");
        String password = pros.getProperty("password");
        String url = pros.getProperty("url");
        String driverClass = pros.getProperty("driverClass");
​
        //3.加载驱动
        Class.forName(driverClass);
​
        //4.获取连接
        Connection conn = DriverManager.getConnection(url,user,password);
        System.out.println(conn);
​
    }

其中,配置文件声明在工程的src目录下:【jdbc.properties】

user=root
password=abc123
url=jdbc:mysql://localhost:3306/test
driverClass=com.mysql.jdbc.Driver

说明:使用配置文件的方式保存配置信息,在代码中加载配置文件

使用配置文件的好处:

①实现了代码和数据的分离,如果需要修改配置信息,直接在配置文件中修改,不需要深入代码 ②如果修改了配置信息,省去重新编译的过程。

第3章:使用PreparedStatement实现CRUD操作

3.1 操作和访问数据库

  • 数据库连接被用于向数据库服务器发送命令和 SQL 语句,并接受数据库服务器返回的结果。其实一个数据库连接就是一个Socket连接。

  • 在 java.sql 包中有 3 个接口分别定义了对数据库的调用的不同方式:

    • Statement:用于执行静态 SQL 语句并返回它所生成结果的对象。

    • PrepatedStatement:SQL 语句被预编译并存储在此对象中,可以使用此对象多次高效地执行该语句。

    • CallableStatement:用于执行 SQL 存储过程

3.2 使用Statement操作数据表的弊端

  • 通过调用 Connection 对象的 createStatement() 方法创建该对象。该对象用于执行静态的 SQL 语句,并且返回执行结果。

  • Statement 接口中定义了下列方法用于执行 SQL 语句:

    int excuteUpdate(String sql):执行更新操作INSERT、UPDATE、DELETE
    ResultSet executeQuery(String sql):执行查询操作SELECT
  • 但是使用Statement操作数据表存在弊端:

    • 问题一:存在拼串操作,繁琐

    • 问题二:存在SQL注入问题

  • SQL 注入是利用某些系统没有对用户输入的数据进行充分的检查,而在用户输入数据中注入非法的 SQL 语句段或命令(如:SELECT user, password FROM user_table WHERE user='a' OR 1 = ' AND password = ' OR '1' = '1') ,从而利用系统的 SQL 引擎完成恶意行为的做法。

  • 对于 Java 而言,要防范 SQL 注入,只要用 PreparedStatement(从Statement扩展而来) 取代 Statement 就可以了。

  • 代码演示:

public class StatementTest {
​
    // 使用Statement的弊端:需要拼写sql语句,并且存在SQL注入的问题
    @Test
    public void testLogin() {
        Scanner scan = new Scanner(System.in);
​
        System.out.print("用户名:");
        String userName = scan.nextLine();
        System.out.print("密   码:");
        String password = scan.nextLine();
​
        // SELECT user,password FROM user_table WHERE USER = '1' or ' AND PASSWORD = '='1' or '1' = '1';
        String sql = "SELECT user,password FROM user_table WHERE USER = '" + userName + "' AND PASSWORD = '" + password
                + "'";
        User user = get(sql, User.class);
        if (user != null) {
            System.out.println("登陆成功!");
        } else {
            System.out.println("用户名或密码错误!");
        }
    }
​
    // 使用Statement实现对数据表的查询操作
    public <T> T get(String sql, Class<T> clazz) {
        T t = null;
​
        Connection conn = null;
        Statement st = null;
        ResultSet rs = null;
        try {
            // 1.加载配置文件
            InputStream is = StatementTest.class.getClassLoader().getResourceAsStream("jdbc.properties");
            Properties pros = new Properties();
            pros.load(is);
​
            // 2.读取配置信息
            String user = pros.getProperty("user");
            String password = pros.getProperty("password");
            String url = pros.getProperty("url");
            String driverClass = pros.getProperty("driverClass");
​
            // 3.加载驱动
            Class.forName(driverClass);
​
            // 4.获取连接
            conn = DriverManager.getConnection(url, user, password);
​
            st = conn.createStatement();
​
            rs = st.executeQuery(sql);
​
            // 获取结果集的元数据
            ResultSetMetaData rsmd = rs.getMetaData();
​
            // 获取结果集的列数
            int columnCount = rsmd.getColumnCount();
​
            if (rs.next()) {
​
                t = clazz.newInstance();
​
                for (int i = 0; i < columnCount; i++) {
                    // //1. 获取列的名称
                    // String columnName = rsmd.getColumnName(i+1);
​
                    // 1. 获取列的别名
                    String columnName = rsmd.getColumnLabel(i + 1);
​
                    // 2. 根据列名获取对应数据表中的数据
                    Object columnVal = rs.getObject(columnName);
​
                    // 3. 将数据表中得到的数据,封装进对象
                    Field field = clazz.getDeclaredField(columnName);
                    field.setAccessible(true);
                    field.set(t, columnVal);
                }
                return t;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 关闭资源
            if (rs != null) {
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (st != null) {
                try {
                    st.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
​
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
​
        return null;
    }
}

3.3 PreparedStatement的使用

3.3.1 PreparedStatement介绍
  • 可以通过调用 Connection 对象的 preparedStatement(String sql) 方法获取 PreparedStatement 对象

  • PreparedStatement 接口是 Statement 的子接口,它表示一条预编译过的 SQL 语句

  • PreparedStatement 对象所代表的 SQL 语句中的参数用问号(?)来表示,调用 PreparedStatement 对象的 setXxx() 方法来设置这些参数. setXxx() 方法有两个参数,第一个参数是要设置的 SQL 语句中的参数的索引(从 1 开始),第二个是设置的 SQL 语句中的参数的值

3.3.2 PreparedStatement vs Statement
  • 代码的可读性和可维护性。

  • PreparedStatement 能最大可能提高性能:

    • DBServer会对预编译语句提供性能优化。因为预编译语句有可能被重复调用,所以语句在被DBServer的编译器编译后的执行代码被缓存下来,那么下次调用时只要是相同的预编译语句就不需要编译,只要将参数直接传入编译过的语句执行代码中就会得到执行。

    • 在statement语句中,即使是相同操作但因为数据内容不一样,所以整个语句本身不能匹配,没有缓存语句的意义.事实是没有数据库会对普通语句编译后的执行代码缓存。这样每执行一次都要对传入的语句编译一次。

    • (语法检查,语义检查,翻译成二进制命令,缓存)

  • PreparedStatement 可以防止 SQL 注入

3.3.3 Java与SQL对应数据类型转换表
Java类型SQL类型
booleanBIT
byteTINYINT
shortSMALLINT
intINTEGER
longBIGINT
StringCHAR,VARCHAR,LONGVARCHAR
byte arrayBINARY , VAR BINARY
java.sql.DateDATE
java.sql.TimeTIME
java.sql.TimestampTIMESTAMP
3.3.4 使用PreparedStatement实现增、删、改操作
//通用的增、删、改操作(体现一:增、删、改 ; 体现二:针对于不同的表)
    public void update(String sql,Object ... args){
        Connection conn = null;
        PreparedStatement ps = null;
        try {
            //1.获取数据库的连接
            conn = JDBCUtils.getConnection();
            
            //2.获取PreparedStatement的实例 (或:预编译sql语句)
                ps = conn.prepareStatement(sql);
            //3.填充占位符
            for(int i = 0;i < args.length;i++){
                ps.setObject(i + 1, args[i]);
            }
            
            //4.执行sql语句
            ps.execute();
        } catch (Exception e) {
            
            e.printStackTrace();
        }finally{
            //5.关闭资源
            JDBCUtils.closeResource(conn, ps);
            
        }
    }
3.3.5 使用PreparedStatement实现查询操作
 // 通用的针对于不同表的查询:返回一个对象 (version 1.0)
    public <T> T getInstance(Class<T> clazz, String sql, Object... args) {
​
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            // 1.获取数据库连接
            conn = JDBCUtils.getConnection();
​
            // 2.预编译sql语句,得到PreparedStatement对象
            ps = conn.prepareStatement(sql);
​
            // 3.填充占位符
            for (int i = 0; i < args.length; i++) {
                ps.setObject(i + 1, args[i]);
            }
​
            // 4.执行executeQuery(),得到结果集:ResultSet
            rs = ps.executeQuery();
​
            // 5.得到结果集的元数据:ResultSetMetaData
            ResultSetMetaData rsmd = rs.getMetaData();
​
            // 6.1通过ResultSetMetaData得到columnCount,columnLabel;通过ResultSet得到列值
            int columnCount = rsmd.getColumnCount();
            if (rs.next()) {
                T t = clazz.newInstance();
                for (int i = 0; i < columnCount; i++) {// 遍历每一个列
​
                    // 获取列值
                    Object columnVal = rs.getObject(i + 1);
                    // 获取列的别名:列的别名,使用类的属性名充当
                    String columnLabel = rsmd.getColumnLabel(i + 1);
                    // 6.2使用反射,给对象的相应属性赋值
                    Field field = clazz.getDeclaredField(columnLabel);
                    field.setAccessible(true);
                    field.set(t, columnVal);
​
                }
​
                return t;
​
            }
        } catch (Exception e) {
​
            e.printStackTrace();
        } finally {
            // 7.关闭资源
            JDBCUtils.closeResource(conn, ps, rs);
        }
​
        return null;
​
    }

说明:使用PreparedStatement实现的查询操作可以替换Statement实现的查询操作,解决Statement拼串和SQL注入问题。

3.4 ResultSet与ResultSetMetaData

3.4.1 ResultSet
  • 查询需要调用PreparedStatement 的 executeQuery() 方法,查询结果是一个ResultSet 对象

  • ResultSet 对象以逻辑表格的形式封装了执行数据库操作的结果集,ResultSet 接口由数据库厂商提供实现

  • ResultSet 返回的实际上就是一张数据表。有一个指针指向数据表的第一条记录的前面。

  • ResultSet 对象维护了一个指向当前数据行的游标,初始的时候,游标在第一行之前,可以通过 ResultSet 对象的 next() 方法移动到下一行。调用 next()方法检测下一行是否有效。若有效,该方法返回 true,且指针下移。相当于Iterator对象的 hasNext() 和 next() 方法的结合体。

  • 当指针指向一行时, 可以通过调用 getXxx(int index) 或 getXxx(int columnName) 获取每一列的值。

    • 例如: getInt(1), getString("name")

    • 注意:Java与数据库交互涉及到的相关Java API中的索引都从1开始。

  • ResultSet 接口的常用方法:

    • boolean next()

    • getString()

3.4.2 ResultSetMetaData
  • 可用于获取关于 ResultSet 对象中列的类型和属性信息的对象

  • ResultSetMetaData meta = rs.getMetaData();

    • getColumnName(int column):获取指定列的名称

    • getColumnLabel(int column):获取指定列的别名

    • getColumnCount():返回当前 ResultSet 对象中的列数。

    • getColumnTypeName(int column):检索指定列的数据库特定的类型名称。

    • getColumnDisplaySize(int column):指示指定列的最大标准宽度,以字符为单位。

    • isNullable(int column):指示指定列中的值是否可以为 null。

    • isAutoIncrement(int column):指示是否自动为指定列进行编号,这样这些列仍然是只读的。

问题1:得到结果集后, 如何知道该结果集中有哪些列 ? 列名是什么?

需要使用一个描述 ResultSet 的对象, 即 ResultSetMetaData

问题2:关于ResultSetMetaData

  1. 如何获取 ResultSetMetaData: 调用 ResultSet 的 getMetaData() 方法即可

  2. 获取 ResultSet 中有多少列:调用 ResultSetMetaData 的 getColumnCount() 方法

  3. 获取 ResultSet 每一列的列的别名是什么:调用 ResultSetMetaData 的getColumnLabel() 方法

3.5 资源的释放

  • 释放ResultSet, Statement,Connection。

  • 数据库连接(Connection)是非常稀有的资源,用完后必须马上释放,如果Connection不能及时正确的关闭将导致系统宕机。Connection的使用原则是尽量晚创建,尽量早的释放。

  • 可以在finally中关闭,保证及时其他代码出现异常,资源也一定能被关闭。

3.6 JDBC API小结

  • 两种思想

    • 面向接口编程的思想

    • ORM思想(object relational mapping)

      • 一个数据表对应一个java类

      • 表中的一条记录对应java类的一个对象

      • 表中的一个字段对应java类的一个属性

    sql是需要结合列名和表的属性名来写。注意起别名。

  • 两种技术

    • JDBC结果集的元数据:ResultSetMetaData

      • 获取列数:getColumnCount()

      • 获取列的别名:getColumnLabel()

    • 通过反射,创建指定类的对象,获取指定的属性并赋值。

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

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

相关文章

进程--消息队列和共享内存

目录 消息队列 创建消息队列 删除消息队列 发送消息和接收 消息队列 消息队列就是一个消息的列表&#xff0c;进程可以在消息队列中添加消息和的读取消息 消息队列具有FIFO的特性&#xff0c;具有无名管道与有名管道各自的优势&#xff0c;可以支持任意两个进程的进程间通讯…

【python实操】python小程序之随机抽签以及for循环计算0-x的和

引言 python小程序之随机抽签以及for循环计算0-x的和 文章目录 引言一、随机抽签1.1 题目1.2 代码1.3 代码解释 二、for循环计算0-x的和2.1 题目2.2 代码2.3 代码解释 三、思考3.1 随机抽签3.2 for循环计算0-x的和 一、随机抽签 1.1 题目 使用input输入五个同学的名字随机抽取…

对于基础汇编的趣味认识

汇编语言 机器指令 机器语言是机器指令的集合 机器指令展开来讲就是一台机器可以正确执行的命令 电子计算机的机器指令是一列二进制数字 &#xff08;计算机将其转变为一列高低电平&#xff0c;使得计算机的电子器件受到驱动&#xff0c;进行运算 寄存器&#xff1a;微处理器…

zabbix7.0创建自定义模板的案例详解(以监控httpd服务为例)

前言 服务端配置 链接: rocky9.2部署zabbix服务端的详细过程 环境 主机ip应用zabbix-server192.168.10.11zabbix本体zabbix-client192.168.10.12zabbix-agent zabbix-server(服务端已配置) 创建模板 模板组直接写一个新的&#xff0c;不用选择 通过名称查找模板&#xf…

动手学深度学习(李沐)PyTorch 第 6 章 卷积神经网络

李宏毅-卷积神经网络CNN 如果使用全连接层&#xff1a;第一层的weight就有3*10^7个 观察 1&#xff1a;检测模式不需要整张图像 很多重要的pattern只要看小范围即可 简化1&#xff1a;感受野 根据观察1 可以做第1个简化&#xff0c;卷积神经网络会设定一个区域&#xff0c…

wenyan:markdown 一键转换文章排版

介绍 今天给大家介绍一个markdown排版成自媒体文章的工具。 markdown 的重要性和便捷性不用再多说&#xff0c;但是从markdown 转换到文章排版&#xff0c;我换了很多个也都很不满意&#xff0c;尤其在不支持markdown的平台&#xff0c;更是一言难尽。 本次介绍的wenyan的核心…

JDBC进阶

目录 JDBC进阶 实体类和ORM 主键回显 批量操作 连接池 介绍 常见的连接池 Druid连接池 Hikari连接池 连接池与软编码 其他配置 Druid配置 Hikari配置 JDBC进阶 实体类和ORM 在使用JDBC操作数据库时会发现数据都是零散的&#xff0c;明明在数据库中是一行完整的数…

【四】Spring Cloud OpenFeign原理分析

Spring Cloud OpenFeign原理分析 概述 Spring Cloud 微服务实践也有挺多年了&#xff0c;一直想着总结一下这系列的知识点&#xff0c;最近终于下定决心来出一个Spring Cloud 系列文章了。本文主要围绕fegin组件来进行讲解&#xff0c;文中将会给出基础使用的示例&#xff0c;还…

0x10 用友 畅捷通T+ RecoverPassword.aspx 管理员密码修改漏洞

参考&#xff1a; 用友 畅捷通T RecoverPassword.aspx 管理员密码修改漏洞 | PeiQi文库 (wgpsec.org) 免责声明 欢迎访问我的博客。以下内容仅供教育和信息用途&#xff1a; 合法性&#xff1a;我不支持或鼓励非法活动。请确保遵守法律法规。信息准确性&#xff1a;尽管我尽…

全站最详细的Python环境配置步骤

1、官网下载IDE JetBrains下载 2、IDE下载、安装步骤 这里展示的是如何在Windows上下载、安装Pycharm工具&#xff0c;Linux的步骤类似。 2.1、选择开发者工具 选择开发者工具 2.2、选择Pycharm 选择Pycharm 2.3、选择下载 选择下载 2.4、选择社区版 一般而言&#xff…

【STM32-HAL库】AHT10温湿度传感器使用(STM32F407ZGT6配置i2c)(附带工程下载连接)

一、温湿度传感器&#xff1a; 温湿度传感器是一种能够检测环境中的温度和湿度&#xff0c;并将其转化为电信号输出的装置。它在智能家居、工业自动化、气象监测、农业等领域有着广泛的应用。 原理&#xff1a; 温湿度传感器通常基于不同的物理原理&#xff0c;以下是一些常见…

补:vs调试技巧!

目录 1>>闲话 2>>bug 3>>debug调式 4>>debug和release 5>>监视和内存观察 6>>总结 1>>闲话 数据结构章节在国庆后再给大家更喔&#xff0c;现在先把c基础打好&#xff0c;所以我又重返回去学习c语言&#xff0c;并且&#xff0…

17 vue3之tsx手写vite tsx插件

我们之前呢是使用Template去写我们模板。现在可以扩展另一种风格TSX风格 vue2 的时候就已经支持jsx写法&#xff0c;只不过不是很友好&#xff0c;随着vue3对typescript的支持度&#xff0c;tsx写法越来越被接受&#xff0c;减少我们学习react的成本 Ant Design组件库就是使用…

利用LLMs自动寻找量化投资策略

利用LLMs自动寻找量化投资策略 J.P.Morgan的python教程 Content 本文提出了一个利用大型语言模型&#xff08;LLMs&#xff09;和多代理架构的新框架&#xff0c;用于量化股票投资和投资组合管理。该框架通过整合LLMs生成多样化的alpha因子&#xff0c;并动态评估市场条件&am…

基于 QAnything 的知识库问答系统:技术解析与应用实践

最近已有不少大厂都在秋招宣讲了&#xff0c;也有一些在 Offer 发放阶段。 节前&#xff0c;我们邀请了一些互联网大厂朋友、今年参加社招和校招面试的同学。 针对新手如何入门算法岗、该如何准备面试攻略、面试常考点、大模型技术趋势、算法项目落地经验分享等热门话题进行了…

Mysql 学习——项目实战

MySQL 学习——项目实战 项目出处 博主&#xff1a;Asmywishi Linux-Ubuntu启动Mysql sudo mysqlData preparation Create Database and Table Create database : create database mysql_example1;Start database : use mysql_example1;Create Student table : # 学生表…

vue页面保持在div的底部(适用于聊天界面等需要显示最新信息的场景)

代码示例&#xff1a; <script setup lang"ts"> import {nextTick, onMounted, ref} from vueconst count [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, …

如何将题目文档做成一个题库刷题小程序?

✨告别题海战术&#xff0c;迎接智慧刷题新时代&#xff01;&#x1f680; &#x1f4da;面对堆积如山的题库文档&#xff0c;是否感到无从下手&#xff1f;别担心&#xff0c;这款本土定制刷题小程序来救场啦&#xff01;&#x1f389; &#x1f31f;自动生成题库&#xff0c…

数据结构-3.9.栈在递归中的应用

一.函数被调用背后的过程&#xff1a;最后被调用的函数最先结束也符合栈的后进先出 1.main函数为主函数即程序入口&#xff0c;运行时主函数先入栈&#xff0c;然后存入主函数里的数据&#xff1b; 2.func1函数加载在栈中时他后面的代码的地址#1(调用返回地址&#xff0c;不是…

Xshell7下载及服务器连接

一、Xshell-7.0.0164p、Xftp 7下载 1.1、文件下载 通过网盘分享的文件&#xff1a;xshell 链接: https://pan.baidu.com/s/1qc0CPv4Hkl19hI9tyvYZkQ 提取码: 5snq –来自百度网盘超级会员v2的分享 1.2、ip连接 下shell和xftp操作一样&#xff1a;找到文件—》新建—》名称随…