day37_jdbc

news2025/2/27 5:41:31

·今日内容

上课同步视频:CuteN饕餮的个人空间_哔哩哔哩_bilibili
同步笔记沐沐霸的博客_CSDN博客-Java2301
零、 复习昨日

零、 复习昨日

见晨考

一、作业

package com.qf.homework;

import com.qf.model.User;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * --- 天道酬勤 ---
 *
 * @author QiuShiju
 * @desc
 */
public class Demo_CRUD {

    public static void main(String[] args) throws Exception {
        // User user = getUserById(1);
        // System.out.println(user );

        // 创建对象,准备注册
        // User user2 = new User( );
        // user2.setUsername("周期");
        // user2.setPassword("123456");
        // user2.setPhone("120");
        // user2.setCreateTime(new Date( ));
        // user2.setMoney(4800.0);
        // user2.setSex(2);
        // boolean isok = addUser(user2);
        // System.out.println("注册是否成功" + isok );

        // List<User> list = findAll( );
        // for (User user : list) {
        //     System.out.println(user );
        // }


        User user3 = new User( );
        user3.setId(5);
        user3.setUsername("admin");
        user3.setPassword("11111");
        //user3.setCreateTime(new Date(  ));
        updateById2(user3);
    }

    // 根据id从数据库查询出用户信息
    public static User getUserById(int id) throws Exception {
        // 1 注册驱动
        Class.forName("com.mysql.Driver");
        // 2 获得连接
        String url = "jdbc:mysql://localhost:3306/java2301?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&useSSL=false";
        String username = "root";
        String password = "123456";
        Connection conn = DriverManager.getConnection(url, username, password);
        // 3 获得执行语句
        Statement s = conn.createStatement( );

        User user = null;

        String sql = "select * from tb_user where id = " + id;
        System.out.println("拼接后的sql --> " + sql );
        ResultSet rs = s.executeQuery(sql);
        if(rs.next()) {
            // 取出数据
            String username1 = rs.getString("username");
            String password1 = rs.getString("password");
            String phone = rs.getString("phone");
            Date createTime = rs.getDate("createTime");
            double money = rs.getDouble("money");
            int sex = rs.getInt("sex");

            // 封装数据
            user = new User();
            user.setId(id);
            user.setUsername(username1);
            user.setPassword(password1);
            user.setPhone(phone);
            user.setCreateTime(createTime);
            user.setMoney(money);
            user.setSex(sex);
        }

        return user;
    }


    // 向数据库插入一个用户,返回是否插入成功
    public static boolean addUser(User user) throws Exception {
        // 1 注册驱动
        Class.forName("com.mysql.Driver");
        // 2 获得连接
        String url = "jdbc:mysql://localhost:3306/java2301?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&useSSL=false";
        String username = "root";
        String password = "123456";
        Connection conn = DriverManager.getConnection(url, username, password);
        // 3 获得执行语句
        Statement s = conn.createStatement( );

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String date = sdf.format(user.getCreateTime( ));

        String sql = "insert into tb_user (username,password,phone,createTime,money,sex) " +
                "values ('"+user.getUsername()+"','"+user.getPassword()+"','"+user.getPhone()+"','"+date+"',"+user.getMoney()+","+user.getSex()+")";

        System.out.println("拼接后的sql ---> " + sql );
        int num = s.executeUpdate(sql);

        return num > 0 ? true:false;
    }

    /// 通过id删除用户数据,返回受影响行数
    public static int deleteById(int id){
        return 0;
    }

    // 设计方法,查询全部数据,返回值是List集合,集合中是全部用户数据
    public static List<User> findAll() throws Exception{
        // 1 注册驱动
        Class.forName("com.mysql.Driver");
        // 2 获得连接
        String url = "jdbc:mysql://localhost:3306/java2301?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&useSSL=false";
        String username = "root";
        String password = "123456";
        Connection conn = DriverManager.getConnection(url, username, password);
        // 3 获得执行语句
        Statement s = conn.createStatement( );

        ArrayList<User> list = new ArrayList<>( );
        User user = null;

        String sql = "select * from tb_user";
        ResultSet rs = s.executeQuery(sql);
        while(rs.next()) {
            // 取出数据
            int id = rs.getInt("id");
            String username1 = rs.getString("username");
            String password1 = rs.getString("password");
            String phone = rs.getString("phone");
            Date createTime = rs.getDate("createTime");
            double money = rs.getDouble("money");
            int sex = rs.getInt("sex");

            // 封装数据
            user = new User();
            user.setId(id);
            user.setUsername(username1);
            user.setPassword(password1);
            user.setPhone(phone);
            user.setCreateTime(createTime);
            user.setMoney(money);
            user.setSex(sex);

            // 【重点】 将对象存储入集合
            list.add(user);
        }

        return list;
    }

    // 通过id更改用户数据
    // 方案1: 更新全部字段
    public static int updateById(User user) throws Exception {
        // 1 注册驱动
        Class.forName("com.mysql.Driver");
        // 2 获得连接
        String url = "jdbc:mysql://localhost:3306/java2301?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&useSSL=false";
        String username = "root";
        String password = "123456";
        Connection conn = DriverManager.getConnection(url, username, password);
        // 3 获得执行语句
        Statement s = conn.createStatement( );
        // SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        // String date = sdf.format(user.getCreateTime( ));
        String sql = "update tb_user set username = '"+user.getUsername()+"'," +
                "password = '"+user.getPassword()+"'," +
                "phone = '"+user.getPhone()+"'," +
                //"createTime = '"+date+"'," +
                "money = "+user.getMoney()+"," +
                "sex = "+user.getSex()+" " +
                "where id = " + user.getId();
        System.out.println("拼接后的sql -->" + sql );


        int i = s.executeUpdate(sql);
        s.close();
        conn.close();
        return i;
    }

    // 方案2:
    // update tb_user set phone = '248589792' where id = 6
    // update tb_user set username = 'admin' where id = 6
    // update tb_user set username = 'admin', password = '123456' where id = 6
    // 这就是需要根据传入的User对象属性的值是否为null,判断是否要更新该字段
    // 即sql语句需要根据情况决定是否拼接某一个字段
    // 这就是动态sql
    public static int updateById2(User user) throws Exception {
        // 1 注册驱动
        Class.forName("com.mysql.Driver");
        // 2 获得连接
        String url = "jdbc:mysql://localhost:3306/java2301?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&useSSL=false";
        String username = "root";
        String password = "123456";
        Connection conn = DriverManager.getConnection(url, username, password);
        // 3 获得执行语句
        Statement s = conn.createStatement( );

        String sql = "update tb_user set ";
        StringBuilder sb = new StringBuilder(sql);
        if (user.getUsername() != null) {
            // sql += " username = '" + user.getUsername()+"',";
            sb.append(" username = '" + user.getUsername()+"',");
        }
        if (user.getPassword() != null) {
            // sql += " password = '" + user.getPassword()+"',";
            sb.append(" password = '" + user.getPassword()+"',");
        }
        if (user.getPhone() != null) {
            // sql += " phone = '" + user.getPhone()+"',";
            sb.append(" phone = '" + user.getPhone()+"',");
        }
        if (user.getCreateTime() != null) {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            String date = sdf.format(user.getCreateTime( ));
            // sql += " createTime = '" + date+"',";
            sb.append(" createTime = '" + date+"',");
        }
        if (user.getMoney() != 0.0) {
            //sql += " money = " + user.getMoney()+",";
            sb.append(" money = " + user.getMoney()+",");
        }
        if (user.getSex() != 0) {
            // sql += " sex = " + user.getSex()+",";
            sb.append(" sex = " + user.getSex()+",");
        }

        int index = sb.lastIndexOf(",");
        sb.deleteCharAt(index);
        sb.append(" where id = " + user.getId());
        System.out.println(sb );

        // String newSql = sql.substring(0, index);
        // newSql += " where id = " + user.getId();
        // System.out.println("动态sql -->" + newSql );

        int i = s.executeUpdate(sb.toString( ));

        return i;
    }
}

二、SQL注入

2.1 什么是SQL注入

用户输入的数据中有SQL关键词,导致在执行SQL语句时出现一些不正常的情况.这就是SQL注入!


出现SQL注入是很危险

image-20230322084643699

2.2 避免SQL注入

问题出现在用户输入数据时,里面有关键词,再配合字符串拼接导致出现SQL注入.所以为了避免SQL注入,可以在用户输入数据到SQL之前,先把SQL语句预编译,预处理后,JDBC就会知道此SQL需要几个参数,后续再将用户输入的数据给参数填充.

这就是PreparedStatement

三、PreparedStatement【重点】

PreparedStatement是Statement的子接口,用来预处理SQL语句

PreparedStatement使用

  • 先写SQL语句,SQL语句中的参数不能直接拼接,而是使用?占位
  • 使用ps预处理SQL语句,处理的?号,ps内部就会知道此SQL语句需要几个参数
  • 再动态给?处填充值

image-20230322084657336

package com.qf.jdbc;

import java.sql.*;
import java.util.Scanner;

/**
 * --- 天道酬勤 ---
 *
 * @author QiuShiju
 * @desc 登录-使用预处理语句完成
 */
public class Demo2_LoginPlus {

    public static void main(String[] args) throws Exception {

        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入用户名:" );
        String username = scanner.nextLine( );

        System.out.println("请输入密码:" );
        String password = scanner.nextLine( );

        Class.forName("com.mysql.Driver");
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/java2217?useSSL=false", "root", "123456");

        // 改造SQL,将拼接变量,变成?占位
        String sql = "select * from tb_user where username = ? and password = ?";
        System.out.println("处理前:  " + sql);

        // 由之前的Statement换成PreparedStatement
        // 将改造好的SQL,传入方法
        PreparedStatement ps = conn.prepareStatement(sql);
        System.out.println("处理后: " + ps );

        // 给处理好的占位参数赋值
        // ps.setXxx() 给指定Xxx类型赋值
        // 第一个?,下标是1
        ps.setString(1,username);
        ps.setString(2,password);

        System.out.println("填充后: " + ps );

        //【特别注意!!!!】 此处executeQuery不需要再传入SQL参数!!!
        ResultSet rs = ps.executeQuery();

        if (rs.next()) {
            System.out.println("登录成功!!" );
        } else {
            System.out.println("用户名或密码错误!" );
        }

        rs.close();
        ps.close();
        conn.close();
    }
}
请输入用户名:
111
请输入密码:
111' or '1=1
处理前:  select * from tb_user where username = ? and password = ?
处理后: select * from tb_user where username = ** NOT SPECIFIED ** and password = ** NOT SPECIFIED **
填充后: select * from tb_user where username = '111' and password = '111\' or \'1=1'
用户名或密码错误!

四、预处理语句完成CRUD

4.1 插入


    // 向数据库插入一个用户,返回是否插入成功
    public static boolean addUser(User user) throws Exception {
        // 1 注册驱动
        Class.forName("com.mysql.Driver");
        // 2 获得连接
        String url = "jdbc:mysql://localhost:3306/java2301?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&useSSL=false";
        String username = "root";
        String password = "123456";
        Connection conn = DriverManager.getConnection(url, username, password);

        // 3.1 写sql,参数拼接,变?
        String sql = "insert into tb_user (username,password,phone,createTime,money,sex) " +
                "values (?,?,?,?,?,?)";

        // 3.2 处理?问
        PreparedStatement ps = conn.prepareStatement(sql);

        // 3.3 ?赋值
        ps.setString(1,user.getUsername());
        ps.setString(2,user.getPassword());
        ps.setString(3,user.getPhone());

        // 日期需要转换成java.sql.Date才能赋值
        java.sql.Date date = new java.sql.Date(user.getCreateTime( ).getTime( ));
        ps.setDate(4,date);

        ps.setDouble(5,user.getMoney());
        ps.setInt(6,user.getSex());

        // 4 执行
        int i = ps.executeUpdate( );

        return i > 0 ? true:false;
    }

4.2 更新

    public static int updateById(User user) throws Exception {
        // 1 注册驱动
        Class.forName("com.mysql.Driver");
        // 2 获得连接
        String url = "jdbc:mysql://localhost:3306/java2301?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&useSSL=false";
        String username = "root";
        String password = "123456";
        Connection conn = DriverManager.getConnection(url, username, password);

        // 3.1 写sql,参数变?号
        String sql = "update tb_user set username = ?," +
                "password = ?," +
                "phone = ?," +
                "createTime = ?," +
                "money = ?," +
                "sex = ? " +
                "where id = ?";
        // 3.2 处理?问
        PreparedStatement ps = conn.prepareStatement(sql);

        // 3.3 ?赋值
        ps.setString(1,user.getUsername());
        ps.setString(2,user.getPassword());
        ps.setString(3,user.getPhone());

        // 日期需要转换成java.sql.Date才能赋值
        java.sql.Date date = new java.sql.Date(user.getCreateTime( ).getTime( ));
        ps.setDate(4,date);

        ps.setDouble(5,user.getMoney());
        ps.setInt(6,user.getSex());
        ps.setInt(7,user.getId());

        // 4 执行
        int i = ps.executeUpdate( );

        ps.close();
        conn.close();

        return i;
    }

4.3 删除


    /// 通过id删除用户数据,返回受影响行数
    public static int deleteById(int id) throws Exception{
        // 1 注册驱动
        Class.forName("com.mysql.Driver");
        // 2 获得连接
        String url = "jdbc:mysql://localhost:3306/java2301?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&useSSL=false";
        String username = "root";
        String password = "123456";
        Connection conn = DriverManager.getConnection(url, username, password);

        // 3.1 写sql,参数写?
        String sql = "delete from tb_user where id = ?";
        // 3.2 处理?
        PreparedStatement ps = conn.prepareStatement(sql);
        // 3.3 给?赋值
        ps.setInt(1,id);

        // 4 执行
        int i = ps.executeUpdate( );

        return i;
    }

4.4 查询

// 根据id从数据库查询出用户信息
    public static User getUserById(int id) throws Exception {
        // 1 注册驱动
        Class.forName("com.mysql.Driver");
        // 2 获得连接
        String url = "jdbc:mysql://localhost:3306/java2301?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&useSSL=false";
        String username = "root";
        String password = "123456";
        Connection conn = DriverManager.getConnection(url, username, password);
        User user = null;
        // 3 预处理
        // 3.1 写sql,参数用?占位
        String sql = "select  * from tb_user where id = ?";
        // 3.2 预处理?号
        PreparedStatement ps = conn.prepareStatement(sql);
        // 3.3 给?赋值
        ps.setInt(1,id);

        // 4 执行sql
        ResultSet rs = ps.executeQuery( );

        if(rs.next()) {
            // 取出数据
            String username1 = rs.getString("username");
            String password1 = rs.getString("password");
            String phone = rs.getString("phone");
            Date createTime = rs.getDate("createTime");
            double money = rs.getDouble("money");
            int sex = rs.getInt("sex");

            // 封装数据
            user = new User();
            user.setId(id);
            user.setUsername(username1);
            user.setPassword(password1);
            user.setPhone(phone);
            user.setCreateTime(createTime);
            user.setMoney(money);
            user.setSex(sex);
        }

        return user;
    }
 // 设计方法,查询全部数据,返回值是List集合,集合中是全部用户数据
    public static List<User> findAll() throws Exception{
        // 1 注册驱动
        Class.forName("com.mysql.Driver");
        // 2 获得连接
        String url = "jdbc:mysql://localhost:3306/java2301?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&useSSL=false";
        String username = "root";
        String password = "123456";
        Connection conn = DriverManager.getConnection(url, username, password);
        ArrayList<User> list = new ArrayList<>( );
        User user = null;
        // 3.1 写sql
        String sql = "select * from tb_user";
        // 3.2 处理sql
        PreparedStatement ps = conn.prepareStatement(sql);

        // 4 执行
        ResultSet rs = ps.executeQuery( );


        while(rs.next()) {
            // 取出数据
            int id = rs.getInt("id");
            String username1 = rs.getString("username");
            String password1 = rs.getString("password");
            String phone = rs.getString("phone");
            Date createTime = rs.getDate("createTime");
            double money = rs.getDouble("money");
            int sex = rs.getInt("sex");

            // 封装数据
            user = new User();
            user.setId(id);
            user.setUsername(username1);
            user.setPassword(password1);
            user.setPhone(phone);
            user.setCreateTime(createTime);
            user.setMoney(money);
            user.setSex(sex);

            // 【重点】 将对象存储入集合
            list.add(user);
        }

        return list;
    }

五、事务处理【了解】

事务是逻辑一组操作,要么全部成功,要么全部失败!


使用mysql客户端操作事务

  • 因为mysql支持事务,且每句话都在事务内,且自动提交
  • 所以关闭自动提交事务,手动开启事务 start transaction
  • 正常写sql/执行sql
  • 一切正常,提交事务 commit
  • 如果不正常,要回滚 rollback

JDBC也可以完成事务操作

  • conn.setAutoCommit(false) 关闭自动提交,就相当于是开启手动管理
  • 正常的处理sql
  • 一切正常,提交事务 conn.commit()
  • 如果不正常,回滚 conn.rollback()

演示: 以转账案例演示

package com.qf.tx;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;

/**
 * --- 天道酬勤 ---
 *
 * @author QiuShiju
 * @desc 以转账为案例演示
 * --------------------
 * Statement语句和PreparedStatement语句
 * 与事务操作没有影响
 */
public class Demo6_TX {

    // 张三转账给李四
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement ps1 = null;
        PreparedStatement ps2 = null;
        try {
            Class.forName("com.mysql.Driver");
            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/java2217?useSSL=false", "root", "123456");

            // 【1 开启事务】
            conn.setAutoCommit(false);

            // 张三的钱减少100
            String sql1 = "update account set money = money - 100 where id = 1";
            ps1 = conn.prepareStatement(sql1);
            int num = ps1.executeUpdate( );
            if (num > 0) {
                System.out.println("张三转账(-100)完成!");
            }

            System.out.println(1/0 ); // 模拟在转账中,出现异常,后续不执行

            // 李四的钱要增加100
            String sql2 = "update account set money = money + 100 where id = 2";
            ps2 = conn.prepareStatement(sql2);
            int num2 = ps2.executeUpdate( );
            if (num2 > 0) {
                System.out.println("李四转账(+100)完成!");
            }

            // 【2 一切顺利,提交事务】
            conn.commit();

        } catch (Exception e) {
            try{
                // 【3 不顺利,中间有异常,回滚事务】
                conn.rollback();
            }catch (Exception e2) {
                System.out.println("回滚事务异常!!" );
                e2.printStackTrace();
            }
            System.out.println("SQL异常!!!");
            e.printStackTrace( );
        } finally {
            try {
                ps1.close( );
                ps2.close( );
                conn.close( );
            } catch (Exception e) {
                System.out.println("关流时有异常!!");
                e.printStackTrace( );
            }
        }
    }
}

另外发现: 建立与Mysql连接后,关流之前,可以执行很多次SQL语句

六、DBUtil【理解,会用】

DBUtil操作数据库的工具类,因为发现每次操作数据库,JDBC的步骤第1,2,5步完全重复的,即加载驱动,获得连接对象,已经最后的关流是每次都要写但每次都是一样的!!!


现在设计工具类,简化第1,2,5步

  • 设计个方法,调用直接获得连接对象
  • 设计个方法,调用直接关闭全部的流对象
package com.qf.util;

import java.io.InputStream;
import java.sql.*;
import java.util.Properties;

/**
 * --- 天道酬勤 ---
 *
 * @author QiuShiju
 * @desc
 */
public class DBUtil {

    // 创建Properties类对象,专用于操作properties文件
    private static final Properties properties = new Properties();

    /**
     * 加载驱动的目的是为了在JVM中有sql运行的环境
     * 该环境有一份就行了,不用重复加载
     * ------------------------------------
     * static 静态代码块
     * 1) 保证内存中只有一份
     * 2) 保证随着类加载而加载,即该代码块会执行
     */
    static {

        // 通过反射的技术获得字节码文件
        // 再通过字节码文件将配置文件读取成输入流
        InputStream inputStream = DBUtil.class.getResourceAsStream("/db.properties");
        try {
            // 再通过流获得其中数据
            properties.load(inputStream);
            // 从properties对象取值
            Class.forName(properties.getProperty("driverClass"));
        } catch (Exception e) {
            System.out.println("加载驱动异常!!" );
            e.printStackTrace( );
        }
    }

    /**
     * 一般会将关于JDBC配置信息,抽取出来,形成一个配置文件,方便维护
     * 文件类型是properties文件,该文件类似map,键值对类型
     * 名字 properties
     * 位置 src/properties
     * 内容
     */
    public static Connection getConnection() {
        Connection conn = null;
        try{
            conn = DriverManager.getConnection(properties.getProperty("url"),properties.getProperty("username") ,properties.getProperty("password") );
        } catch (Exception e) {
            System.out.println("获得连接出异常!!!" );
            e.printStackTrace();
        }
        return conn;
    }


    /**
     * 关闭所有流
     */
    public static void closeAll(Connection conn, Statement s) {
        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace( );
            }
        }

        if (s != null) {
            try {
                s.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace( );
            }
        }
    }

    public static void closeAll(Connection conn, Statement s, ResultSet rs){
        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace( );
            }
        }

        if (s != null) {
            try {
                s.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace( );
            }
        }

        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace( );
            }
        }
    }
}

在src下创建db.properties文件

driverClass=com.mysql.Driver
url=jdbc:mysql://localhost:3306/java2217?useSSL=false
username=root
password=123456

image-20230321170200023

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

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

相关文章

【笔试强训】(红与黑,五子棋,走迷宫)DFS+BFS算法解析

博主简介&#xff1a;想进大厂的打工人博主主页&#xff1a;xyk:所属专栏: 笔试强训专栏 深度优先遍历&#xff08;Depth First Search, 简称 DFS&#xff09; 与广度优先遍历&#xff08;Breath First Search&#xff09;是图论中两种非常重要的算法。 本文就以习题的方式来给…

STM32F10X--EXTI--外部中断/事件控制器

一、EXTI是什么&#xff1f; EXTI&#xff08;External interrupt/event controller&#xff09;—外部中断/事件控制器&#xff0c;管理了控制器的20 个中断/事 件线。每个中断/事件线都对应有一个边沿检测器&#xff0c;可以实现输入信号的上升沿检测和下降沿的 检测。EXTI 可…

SpringMVC的基础知识

创建SpringMVC项目 SpringMVC项目其实和SpingBoot项目差不多,就多引入了一个SpringWeb项目而已拉 可以看这篇博客,创建的就是一个SpringMVC项目--创建项目の博客 SpringMVC是啥 Spring是啥相信大家都了解 啥是MVC呢?MVC是Model View Controller的缩写 我们分开看这三个词Model…

【框架源码】Spring源码核心注解@Conditional原理及应用

1.什么是Conditional注解 Conditional来源于spring-context包下的一个注解。通过Conditional配置一些条件判断&#xff0c;当所有条件都满足时&#xff0c;被该Conditional注解标注的目标才会被Spring处理。 例如根据当前环境、系统属性、配置文件等条件来决定是否注册某个Bea…

PostgreSQL-如何创建并发索引

索引简介 索引是数据库中一种快速查询数据的方法。索引中记录了表中的一列或多列值与其物理位置之间的对应关系&#xff0c;就好比一本书前面的目录&#xff0c;通过目录中页码就能快速定位到我们需要查询的内容。 建立索引的好处是加快对表中记录的查找或排序&#xff0c;但…

Mysql进阶-索引事务相关

文章目录 数据库存储引擎INNODBMYISAM 索引索引分类索引语法SQL性能分析SQL执行频率慢查询profile详情explain 执行计划**Etrax**(额外信息&#xff09;using index conditionusing where&#xff1b;using indexusing where 索引使用规则最左前缀法则范围查询 索引失效情况1.索…

conda故障处理

【已解决】subprocess-exited-with-error 准备元数据(setup.py)…错误 错误:subprocess-exited-with-error python setup.py egg_info运行失败。 │退出代码:10 <╰>[1行输出] 请指定——curl-dir/path/to/built/libcurl [输出结束] 注意:此错误源自子进程&#xf…

Halcon 形态学(膨胀(Dilation)、腐蚀(Erosion))

文章目录 1 形态学概念2 膨胀(Dilation) 算子介绍3 腐蚀(Erosion)算子介绍4 膨胀腐蚀 示例15 腐蚀膨胀 示例26 示例原图7 补充:结构元素概念1 形态学概念 图像的形态学处理是对图像的局部像素进行处理,用于从图像中提取有意义的局部图像细节。 通过改变局部区域的像素形态…

单链表OJ题:LeetCode--面试题:02.04 分割链表

朋友们、伙计们&#xff0c;我们又见面了&#xff0c;今天给大家带来的是LeetCode面试题&#xff1a;02.04.分割链表 数 据 结 构&#xff1a;数据结构专栏 作 者&#xff1a;stackY、 LeetCode &#xff1a;LeetCode刷题训练营 LeetCode面试题&#xff1a;02.04.分割…

H5微信授权登录弹窗提示

如下图&#xff1a;用户授权登录前&#xff0c;先通过静默授权&#xff0c;拿到token&#xff0c;展示部分信息&#xff0c;用户通过授权后拿到头像昵称&#xff0c;该弹窗让用户有个比较好的体验 1、标签 <template><!--遮罩--><view v-if"showAuth"…

MD-MTSP:遗传算法GA求解多仓库多旅行商问题(提供MATLAB代码,可以修改旅行商个数及起点)

一、多仓库多旅行商问题 多旅行商问题&#xff08;Multiple Traveling Salesman Problem, MTSP&#xff09;是著名的旅行商问题&#xff08;Traveling Salesman Problem, TSP&#xff09;的延伸&#xff0c;多旅行商问题定义为&#xff1a;给定一个&#x1d45b;座城市的城市集…

开发一个自定义“套壳“浏览器的开源方案

一.项目概述 二.技术选型 三.项目介绍 1.项目地址:​​​​​​https​​​​​​://github.com/keyxh/TLC_Browers 2.项目目录介绍: 3.项目后期 开发语言:VB6 浏览器内核:webview2 项目目的:在vb6调用h5&#xff0c;实现自定义的浏览器 参考资料: https://github.com…

从 Spring 的创建到 Bean 对象的存储、读取

目录 创建 Spring 项目&#xff1a; 1.创建一个 Maven 项目&#xff1a; 2.添加 Spring 框架支持&#xff1a; 3.配置资源文件&#xff1a; 4.添加启动类&#xff1a; Bean 对象的使用&#xff1a; 1.存储 Bean 对象&#xff1a; 1.1 创建 Bean&#xff1a; 1.2 存储 B…

BUUCTF--reverse1,reverse2--WP

文章目录 一.BUUCTF--reverse1二.BUUCTF--reverse2 一.BUUCTF–reverse1 这道题目也是非常简单&#xff0c;主要考察IDA Pro的使用&#xff0c;分析代码&#xff1a; 发现是64位exe&#xff0c;直接拖到IDA Pro中&#xff0c;发现没有找到主函数&#xff1a; 那就直接ShiftF12…

【操作符详解 2023-05-13】

#include <stdio.h>int main() {int a 1;int b 2;int c (a > b, a b 10, a, b a 1);//逗号表达式printf("%d\n", a);printf("%d\n", b);printf("%d\n", c);return 0; }int main() {int arr[10] { 1,2,3,4,5 };// …

等差数列求和,轻松解决力扣“K 个元素的最大和”问题

本篇博客会讲解力扣“2656. K 个元素的最大和”的解题思路&#xff0c;这是题目链接。 先来审题&#xff1a; 以下是输出示例&#xff1a; 以下是提示&#xff1a; 本题有2种思路&#xff0c;一种是直接按照题目所说的方式模拟&#xff0c;另一种是直接使用数学公式。 显然…

STM32f103时钟树详解

一、概述 stm32有四种时钟信号源&#xff0c;HSE(高速外部时钟)、HSI&#xff08;高速内部时钟&#xff09;、LSE&#xff08;低速外部时钟&#xff09;、LSI&#xff08;低速内部时钟&#xff09;。HSE通常接8M晶振&#xff0c;经由内部分频和倍频&#xff0c;最大可得到72MH…

荔枝派Zero(全志V3S)驱动开发之RGB LED灯

文章目录 前言一、硬件连接二、文件 IO 方式操作 GPIO三、编写驱动四、编写应用程序1、V1 版本&#xff0c;实现蓝灯亮灭2、V2 版本&#xff0c;实现蓝灯闪烁 五、编译六、运行测试七、资源自取方式1&#xff1a;github 链接方式2&#xff1a;百度网盘 前言 一、硬件连接 查看…

绝~ 阿里内部“Java进阶必备宝典”,理论到实战,一键通关

前言 作为一名Java方向的程序员&#xff0c;打好夯实的基础是非常重要的&#xff0c;现在大厂面试对于程序员基础知识的掌握考察也越来越严格&#xff0c;虽然说现在技术更新比较快&#xff0c;但基础扎实才能够更深入的去理解每一个知识技术点。 关于Java程序员如何筑基&…

实现“省市县的联动”

分析&#xff1a;实现这一功能需要发送三次Ajax请求 1.第一次请求&#xff1a;是页面加载完毕之后&#xff0c;发送一次Ajax请求&#xff0c;查询出所有的省级单位&#xff0c;将这些查询结果展示在<select>标签中。 2.第二次请求&#xff1a;当所选省级单位发生变化的时…