day44_jdbc

news2024/11/15 23:54:05

今日内容

0 复习昨日
1 讲作业
2 数据库连接池(druid)
3 反射
4 改造DBUtil
5 完成CRUD练习

0 复习昨日

1 sql注入

2 预处理语句

3 事务操作

4 DBUtil

1 作业【重要】

利用ORM完成,以下的几个方法非常重要,将来写项目就是这些操作


写项目步骤

  • 搭建环境
    • 创建项目
    • 导入依赖
    • 工具类
    • 数据库对应实体类
  • 开发数据库层的代码
    • 数据库层代码,一般称为dao (data access object)
    • 操作的是User表,所以类UserDao
CREATE TABLE `tb_user` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '用户编号',
  `username` varchar(10) DEFAULT NULL COMMENT '用户名',
  `password` varchar(10) DEFAULT NULL COMMENT '密码',
  `phone` varchar(11) DEFAULT NULL COMMENT '手机号',
  `createTime` date DEFAULT NULL COMMENT '注册时间',
  `money` double(10,2) DEFAULT NULL COMMENT '账户余额',
  `sex` int(1) DEFAULT NULL COMMENT '性别 1男2女',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8;

1 根据id从数据库查询出用户信息
public User findUserById(int id)

2 向数据库插入一个用户,返回是否插入成功
public boolean addUser(User user)

3 通过id删除用户数据,返回boolean
public boolean deleteById(int id)
4 设计方法,查询全部数据,返回值是List集合,集合中是全部用户数据
publicList findAll()
5 通过id更改用户数据
public boolean updateById(User user)
注意:根据id更新,即参数User对象中一定有id属性值
更新user表的数据,根据User对象的属性更新,如果属性值是null则不跟更新,不为null就更新对应的字段
返回值是受影响的行数

package com.qf.dao;

import com.qf.model.User;
import com.qf.util.DBUtil;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

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

    /**
     * 根据id查用户
     *
     * @param id
     * @return
     */
    public User findUserById(int id) {
        Connection conn = DBUtil.getConnection( );
        PreparedStatement ps = null;
        ResultSet rs = null;
        User user = null;
        try {
            ps = conn.prepareStatement("select * from tb_user where id = ?");
            ps.setInt(1, id);

            rs = ps.executeQuery( );

            if (rs.next( )) {
                user = new User( );
                user.setId(rs.getInt("id"));
                user.setPhone(rs.getString("phone"));
                user.setUsername(rs.getString("username"));
                user.setSex(rs.getInt("sex"));
                user.setMoney(rs.getDouble("money"));
                user.setPassword(rs.getString("password"));
                user.setCreateTime(rs.getDate("createTime"));
            }
        } catch (Exception e) {
            e.printStackTrace( );
        } finally {
            DBUtil.closeAll(conn, ps, rs);
        }
        return user;
    }

    /**
     * 查询全部数据,返回值是List集合,集合中是全部用户数据
     */
    public List<User> findAll() {
        Connection conn = DBUtil.getConnection( );
        PreparedStatement ps = null;
        ResultSet rs = null;
        User user = null;
        ArrayList<User> list = new ArrayList<>( );

        try {
            ps = conn.prepareStatement("select * from tb_user");

            rs = ps.executeQuery( );

            while (rs.next( )) {
                // 每一行数据都需要创建新对象
                user = new User( );
                user.setId(rs.getInt("id"));
                user.setPhone(rs.getString("phone"));
                user.setUsername(rs.getString("username"));
                user.setSex(rs.getInt("sex"));
                user.setMoney(rs.getDouble("money"));
                user.setPassword(rs.getString("password"));
                user.setCreateTime(rs.getDate("createTime"));

                // 将每个对象装入集合
                list.add(user);
            }
        } catch (Exception e) {
            e.printStackTrace( );
        } finally {
            DBUtil.closeAll(conn, ps, rs);
        }
        return list;
    }

    /**
     * 插入数据
     */
    public boolean addUser(User user) {
        Connection conn = DBUtil.getConnection( );
        PreparedStatement ps = null;
        int num = 0;
        try {
            String sql = "insert into tb_user (id,username,password,phone,createTime,money,sex) values (?,?,?,?,?,?,?)";
            ps = conn.prepareStatement(sql);
            ps.setInt(1, user.getId( ));
            ps.setString(2, user.getUsername( ));
            ps.setString(3, user.getPassword( ));
            ps.setString(4, user.getPhone( ));
            ps.setDate(5, new java.sql.Date(user.getCreateTime( ).getTime( )));
            ps.setDouble(6, user.getMoney( ));
            ps.setInt(7, user.getSex( ));

            num = ps.executeUpdate( );
        } catch (Exception e) {
            e.printStackTrace( );
        } finally {
            DBUtil.closeAll(conn, ps);
        }
        return num > 0 ? true : false;
    }

    /**
     * 删除数据
     */
    public boolean deleteById(int id) {
        Connection conn = DBUtil.getConnection( );
        PreparedStatement ps = null;
        int num = 0;
        try {
            String sql = "delete from tb_user where id = ?";
            ps = conn.prepareStatement(sql);
            ps.setInt(1, id);

            num = ps.executeUpdate( );
        } catch (Exception e) {
            e.printStackTrace( );
        } finally {
            DBUtil.closeAll(conn, ps);
        }
        return num > 0 ? true : false;
    }

    /**
     * 根据id更新用户
     * 更新user表的数据,根据User对象的属性更新,
     * 如果属性值是null则不更新,不为null就更新对应的字段
     * ---------------------------------------
     * update tb_user set username= ?,password = ?,phone = ? ,,,,
     * -------------------------------------------
     * 因为值为空不为空情况不一样,那么每次更新的sql语句也不太一样,
     * 解决方案
     * 1) 方案一: (更新全部字段)
     * 在传给updateById()的user对象中,属性全部赋值,没有null
     * 属性值跟原表一样的,更新了也跟原表没变化
     * 属性值跟原表不一样的,就会更新成新值
     * 2) 方案二: (更新部分字段)
     * 根据传给updateById()的user对象中的属性值判断
     * 属性有值,就更新,属性没有值就不更新
     * 即SQL语句要动态拼接
     */
    // 方案一
    public boolean updateById1(User user) {
        Connection conn = DBUtil.getConnection( );
        PreparedStatement ps = null;
        int num = 0;
        try {
            String sql = "update tb_user set username = ?,password = ?," +
                    "phone = ?,createTime = ?,money = ? ," +
                    "sex = ? where id = ?";
            ps = conn.prepareStatement(sql);

            ps.setString(1, user.getUsername( ));
            ps.setString(2, user.getPassword( ));
            ps.setString(3, user.getPhone( ));
            ps.setDate(4, new java.sql.Date(user.getCreateTime( ).getTime( )));
            ps.setDouble(5, user.getMoney( ));
            ps.setInt(6, user.getSex( ));
            ps.setInt(7, user.getId( ));

            num = ps.executeUpdate( );
        } catch (Exception e) {
            e.printStackTrace( );
        } finally {
            DBUtil.closeAll(conn, ps);
        }
        return num > 0 ? true : false;
    }

    // 方案二
    public boolean updateById2(User user) {
        Connection conn = DBUtil.getConnection( );
        Statement statement = null;
        int num = 0;
        try {
            String sql = "update tb_user set ";
            if (user.getUsername( ) != null) {
                sql += "username = '" + user.getUsername( ) + "',";
            }
            if (user.getPassword( ) != null) {
                sql += "password = '" + user.getPassword( ) + "' ,";
            }
            if (user.getPhone( ) != null) {
                sql += "phone = '" + user.getPhone( ) + "' ,";
            }
            // ...继续拼接其他字段,我在此省略
            System.out.println("字段拼接完的sql " + sql);
            // update tb_user set username= 'aaa',password = '111',
            // 截取最后一个,
            int index = sql.lastIndexOf(",");
            String newSql = sql.substring(0, index);
            System.out.println("截取,后的sql  " + newSql);

            // 最后拼接条件
            newSql += " where id = " + user.getId( );
            System.out.println("最终的sql  " + newSql);

            statement = conn.createStatement( );
            num = statement.executeUpdate(newSql);

        } catch (Exception e) {
            e.printStackTrace( );
        } finally {
            DBUtil.closeAll(conn,statement);
        }
        return num > 0 ? true : false;
    }
}

测试

package com.qf.test;

import com.qf.dao.UserDao;
import com.qf.model.User;

import java.util.Date;
import java.util.List;

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

    public static void main(String[] args) {
        UserDao userDao = new UserDao( );
        // User user = userDao.findUserById(2);
        // System.out.println(user );

        // List<User> list = userDao.findAll( );
        // list.forEach(e -> System.out.println(e ));

        // User user = new User( );
        // user.setId(8);
        // user.setUsername("博文");
        // user.setPassword("123456");
        // user.setCreateTime(new Date());
        // boolean isOk = userDao.addUser(user);
        // System.out.println("插入是否成功?" + isOk );


        // boolean isOk = userDao.deleteById(4);
        // System.out.println("删除是否成功 " + isOk );

        // User user = new User( );
        // user.setId(1);
        // user.setUsername("aaaa");
        // user.setPassword("123456");
        // user.setPhone("11110000");
        // user.setMoney(1000);
        // user.setSex(1);
        // user.setCreateTime(new Date(122,10,21));
        // boolean isOk = userDao.updateById1(user);
        // System.out.println(isOk );

        User user = new User( );
        user.setId(2);
        user.setUsername("ROOT");
        user.setPassword("654321");
        boolean isOk = userDao.updateById2(user);
        System.out.println(isOk );
    }
}

小结

1 DAO是什么
2 关于数据库操作的类,应该放在什么包,什么类中
3 要将数据封装成对象(ORM)
4 学会在编码时通过输出语句确定结果是否符合预期
5 学会DEBUG
6 记住以上5个CRUD思路

2 数据库连接池

目前数据库连接是使用是建立连接,用完直接关闭连接.即需要不断创建和销毁连接.就会消耗系统资源.借鉴线程池的思想,设计出数据库连接池.

在程序初始时,预先创建好指定数量的数据库连接对象,存储连接池。需要用时就去取,用完就放回去即可。就会不会频繁创建和销毁,从而节省系统资源。

使用上的线程池有很多

  • druid (德鲁伊)
  • c3p0
  • dbcp

2.1 Druid数据库连接池

Druid是阿里开源技术,性能很好

使用步骤

  • 导入依赖druid.jar包

  • 创建一个jdbc.properties

    driverClass=com.mysql.jdbc.Driver
    url=jdbc:mysql://localhost:3306/java2217?useSSL=false
    username=root
    password=123456
    # ----- 加入druid的一些连接配置
    #<!-- 初始化连接 -->
    initialSize=10
    #最大连接数量
    maxActive=50
    #<!-- 最小空闲连接 -->
    minIdle=5
    #<!-- 超时等待时间以毫秒为单位 60000毫秒/1000等于60秒 -->
    maxWait=5000
    
  • 修改之前的DBUtil

    public class DBUtil {
    
        // 创建Properties类对象,专用于操作properties文件
        private static final Properties properties = new Properties();
        // 声明Druid连接池的连接池对象
        // 数据连接,一般称作数据源 dataSource
        private static DruidDataSource dataSource;
    
    
    
  static {

      try {
          InputStream inputStream = DBUtil.class.getResourceAsStream("/jdbc.properties");
          properties.load(inputStream);
          // 不需要由我们加载驱动
          // 需要给dataSource赋值
          dataSource = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);

      } catch (Exception e) {
          System.out.println("加载驱动异常!!" );
          e.printStackTrace( );
      }
  }

  public static Connection getConnection() {
      Connection conn = null;
      try{
          // 不需要我们获得连接
          // 而是通过Druid获得
          conn = dataSource.getConnection();
      } catch (Exception e) {
          System.out.println("获得连接出异常!!!" );
          e.printStackTrace();
      }
      return conn;
  }
 // 后续正常...跟之前一样

}

  • 开始使用

  • 跟之前一样使用

3 反射(reflect)

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,对于任意一个对 象,都能够调用它的任意一个方法和属性

这种动态获取的信息以及动态调用对象的方法的功能称为java 语言的反射机制。

反射是在程序运行过程中拿到类的字节码文件,进而获得类中的属性,方法等.

3.1 获得类的字节码文件

  • Object类的方法 getClass()
  • 类的静态属性 Xxx.class
  • Class类的静态方法Class.forName(“xxx”)
   /**
     * 演示获取字节码文件
     */
    public static void getClassFile() throws ClassNotFoundException {
        // 方式1
        Class<?> clazz = Class.forName("com.qf.model.User");

        // 方式2
        Class<User> clazz2 = User.class;

        // 方式3
        User user = new User( );
        Class<? extends User> clazz3 = user.getClass( );

        if (clazz.equals(clazz2) && clazz2.equals(clazz3)) {
            System.out.println("是同一个字节码文件" );
        } else {
            System.out.println("不是" );
        }
    }

3.2 获得并设置属性(Field)

在这里插入图片描述

    /**
     * 获得字节码中的属性并操作
     */
    public static void getAndSetFields() throws Exception {
        Class<User> clazz = User.class;
        /**
         * Filed getField(String name)
         *       通过属性名获得属性对象(只能获得public修饰的属性的属性对象)
         * Filed getDeclaredField()
         *       通过属性名获得属性对象(获得任意修饰符修饰的属性对象)
         */
        // Field id = clazz.getField("id");
        // System.out.println(id );

        Field id1 = clazz.getDeclaredField("id");
        System.out.println(id1 );

        /**
         * Filed[]  getFields( ) 获得public修饰所有属性对象,返回数组
         * Filed[] getDeclaredFields( )  获得所有属性对象,返回数组
         */
        Field[] fields = clazz.getFields( );
        System.out.println(fields.length );
        Field[] declaredFields = clazz.getDeclaredFields( );
        System.out.println(declaredFields.length );

        // =============================================
        // 获得属性名
        String name = id1.getName( );
        System.out.println("name = "+ name );

        // 获得属性访问修饰符
        int modifiers = id1.getModifiers( );
        System.out.println("访问修饰符: " + modifiers );

        // 获得属性值
        // 获得哪个对象的该属性值
        // 但是不能获得私有属性的值
        // 可以通过设置,就可以访问,
        id1.setAccessible(true);
        User user = new User( );
        int value = id1.getInt(user);
        System.out.println("id = " + value );

        // 设置属性值
        // 设置哪个对象的该属性值
        id1.setInt( user,11);

        System.out.println(user );

    }

3.3 获得并设置方法(Method)

在这里插入图片描述

    /**
     *  获得字节码中的方法
     */
    public static void getAndSeMethod() throws Exception {
       Class<User> clazz = User.class;
       // 方法有重载,需要通过参数来确定获得哪个方法
       Method m1 = clazz.getMethod("m1"); // 获得无参的m1方法
       Method m1_ = clazz.getMethod("m1",int.class); // 获得有参的m1(int)方法

        // 获得关于方法的所有信息
        int count = m1.getParameterCount( );// 参数个数
        int count_ = m1_.getParameterCount( );// 参数个数

        // 操作方法,让方法执行
        // 参数1: 哪个对象的该方法执行
        // 参数2: 该方法执行时的参数
        Object ret = m1.invoke(new User( ));
        System.out.println("m1()执行后的返回值:" + ret );
        m1_.invoke(new User(),222);

    }

3.4 获得并设置构造方法(Constructor)

在这里插入图片描述

    /**
     *  获得字节码中的构造方法
     */
    public static void getAndSeConstructor() throws Exception {
        Class<User> clazz = User.class;

        // 通过参数来获得有参还是无参构造
        Constructor<User> constructor = clazz.getConstructor( );

        // 构造方法执行,创建对象
        User user = constructor.newInstance( );

        System.out.println(user );

        // 创建字节码的对象,还有另外方法
        // 可以通过字节码,直接创建
        User user1 = clazz.newInstance( );
    }

4 使用反射封装DBUtil

package com.qf.util;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;

import java.io.File;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

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

    // 创建Properties类对象,专用于操作properties文件
    private static final Properties properties = new Properties( );
    // 声明Druid连接池的连接池对象
    // 数据连接,一般称作数据源 dataSource
    private static DruidDataSource dataSource;


    static {

        try {
            InputStream inputStream = DBUtil.class.getResourceAsStream("/jdbc.properties");
            properties.load(inputStream);
            // 不需要由我们加载驱动
            // 需要给dataSource赋值
            dataSource = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);

        } catch (Exception e) {
            System.out.println("加载驱动异常!!");
            e.printStackTrace( );
        }
    }

    public static Connection getConnection() {
        Connection conn = null;
        try {
            // 不需要我们获得连接
            // 而是通过Druid获得
            conn = dataSource.getConnection( );
        } 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( );
            }
        }
    }


    /**
     * 封装查询方法,返回一个对象
     * 参数1 执行查询的SQL,预处理的,条件用?占位
     * select * from tb_user where id = ? and username = ? and password = ?
     * 参数2 结果要封装的类
     * 参数3 给?赋值,不定长参数,是数组
     * 1,admin,123456
     */
    public static <T> T selectOne(String sql, Class<T> t, Object... args) {
        Connection conn = getConnection( );
        PreparedStatement ps = null;
        ResultSet rs = null;
        T target = null;
        try {
            ps = conn.prepareStatement(sql);
            for (int i = 0; args != null && i < args.length; i++) {
                ps.setObject(i + 1, args[i]);
            }

            rs = ps.executeQuery( );
            /**
             * 创建对象
             * 从数据库取出数据,并设置对象属性
             */
            while (rs.next( )) {
                target = t.newInstance( );
                Field[] declaredFields = t.getDeclaredFields( );
                for (int i = 0; i < declaredFields.length; i++) {
                    Field field = declaredFields[i];
                    Object value = rs.getObject(field.getName( ));

                    // 破解私有
                    field.setAccessible(true);

                    // 给对象的该字段赋值
                    field.set(target, value);
                }

            }
        } catch (Exception e) {
            e.printStackTrace( );
        } finally {
            closeAll(conn, ps, rs);
        }
        return target;
    }

    public static <T> List<T> selectAll(String sql, Class<T> t, Object... args) {
        Connection conn = getConnection( );
        PreparedStatement ps = null;
        ResultSet rs = null;
        T target = null;
        ArrayList<T> list = new ArrayList<>( );
        try {
            ps = conn.prepareStatement(sql);
            for (int i = 0; args != null && i < args.length; i++) {
                ps.setObject(i + 1, args[i]);
            }

            rs = ps.executeQuery( );
            /**
             * 创建对象
             * 从数据库取出数据,并设置对象属性
             */
            while (rs.next( )) {
                target = t.newInstance( );
                Field[] declaredFields = t.getDeclaredFields( );
                for (int i = 0; i < declaredFields.length; i++) {
                    Field field = declaredFields[i];
                    Object value = rs.getObject(field.getName( ));

                    // 破解私有
                    field.setAccessible(true);

                    // 给对象的该字段赋值
                    field.set(target, value);
                }
                list.add(target);

            }
        } catch (Exception e) {
            e.printStackTrace( );
        } finally {
            closeAll(conn, ps, rs);
        }
        return list;
    }

    /**
     * 增删改方法一样
     */
    public static boolean update(String sql, Object... args) {
        Connection conn = getConnection( );
        PreparedStatement ps = null;
        int num = 0;
        try {
            ps = conn.prepareStatement(sql);
            for (int i = 0; args != null && i < args.length; i++) {
                ps.setObject(i + 1, args[i]);
            }
            num = ps.executeUpdate( );
        } catch (Exception e) {
            e.printStackTrace( );
        } finally {
            closeAll(conn, ps);
        }
        return num > 0 ? true : false;
    }
}

5 作业

1 上午5道题,按照格式(包名,类名,到封装)写一遍
2 重复一遍反射代码
3 封装DBUtil理解
4 DBUtil再次写那5道题
5 昨天sql题,写个2道

finally {
closeAll(conn, ps, rs);
}
return list;
}

/**
 * 增删改方法一样
 */
public static boolean update(String sql, Object... args) {
    Connection conn = getConnection( );
    PreparedStatement ps = null;
    int num = 0;
    try {
        ps = conn.prepareStatement(sql);
        for (int i = 0; args != null && i < args.length; i++) {
            ps.setObject(i + 1, args[i]);
        }
        num = ps.executeUpdate( );
    } catch (Exception e) {
        e.printStackTrace( );
    } finally {
        closeAll(conn, ps);
    }
    return num > 0 ? true : false;
}

}




# 5 作业

1 上午5道题,按照格式(包名,类名,到封装)写一遍
2 重复一遍反射代码
3 封装DBUtil理解
4 DBUtil再次写那5道题
5 昨天sql题,写个2道






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

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

相关文章

《动手学深度学习(PyTorch版)》笔记7.4

注&#xff1a;书中对代码的讲解并不详细&#xff0c;本文对很多细节做了详细注释。另外&#xff0c;书上的源代码是在Jupyter Notebook上运行的&#xff0c;较为分散&#xff0c;本文将代码集中起来&#xff0c;并加以完善&#xff0c;全部用vscode在python 3.9.18下测试通过&…

前端学习第四天

目录 一、复合选择器 1.后代选择器 2.子代选择器 3.并集选择器 4.交集选择器 5.伪类选择器 1.伪类-超链接&#xff08;拓展&#xff09; 二、CSS特性 1.继承性 2.层叠性 3.优先级 1.优先级-叠加计算规则 2.emmet写法 三、背景属性 1.背景图 ​编辑2.背景图平铺方…

【知识整理】一文理解系统服务高可用

一、如何理解高可用 1、什么是高可用 高可用性&#xff08;英语&#xff1a; High Availability&#xff0c;缩写为 HA&#xff09;&#xff0c;指系统无中断地执行其功能的能力&#xff0c;代表系统的可用性程度&#xff0c;是进行系统设计时的准则之一。 2、决定可用性的两…

指针进阶(上)

二级指针 二级指针是用来存放一级指针地址。 如何使用和解引用呢&#xff1f; #include <stdio.h>int main() {int a 5;int* p &a;int** p2 &p;**p2 10;printf("%d\n", a);return 0; }这里的解引用使用两颗星号的原因是&#xff1a;一个星号找到…

Python初学者学习记录——python基础综合案例:数据可视化——动态柱状图

一、案例效果 通过pyecharts可以实现数据的动态显示&#xff0c;直观的感受1960~2019年世界各国GDP的变化趋势 二、通过Bar构建基础柱状图 反转x轴和y轴 标签数值在右侧 from pyecharts.charts import Bar from pyecharts.options import LabelOpts# 构建柱状图对象 bar Bar()…

介绍docker

一&#xff1a;介绍docker&#xff1a; Docker 并没有单独的图形界面&#xff0c;它主要通过命令行来进行管理和操作 1、 docker ps&#xff1a;显示正在运行的容器。 docker images&#xff1a;显示本地的镜像。 docker run&#xff1a;创建并启动一个新容器。 docker stop&a…

台灯学生用哪个牌子好?学生用护眼台灯品牌推荐

晚上学习&#xff0c;有台灯肯定比没台灯好。只要是盏合格的、能用的台灯&#xff0c;都能给你一个稳定又亮堂的环境。但是有些不合格的台灯会给眼睛带来伤害&#xff0c;尤其是学习负担比较重的学生。那有哪些台灯是学生用着比较好用的呢&#xff1f; 一、学生使用护眼台灯的…

2-2 动手学深度学习v2-损失函数-笔记

损失函数&#xff0c;用来衡量预测值和真实值之间的区别。是机器学习里面一个非常重要的概念。 三个常用的损失函数 L2 loss、L1 loss、Huber’s Robust loss 均方损失 L2 Loss l ( y , y ′ ) 1 2 ( y − y ′ ) 2 l(y,y^{\prime})\frac{1}{2}(y-y^{\prime})^{2} l(y,y′)21…

Unity3d Shader篇(三)— 片元半兰伯特着色器解析

文章目录 前言一、片元半兰伯特着色器是什么&#xff1f;1. 片元漫反射着色器的工作原理2. 片元半兰伯特着色器的优缺点优点&#xff1a;缺点&#xff1a; 3. 公式 二、使用步骤1. Shader 属性定义2. SubShader 设置3. 渲染 Pass4. 定义结构体和顶点着色器函数5. 片元着色器函数…

计算机毕业设计 基于SpringBoot的线上教育培训办公系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…

centos7的git使用方法

下载git yum install git git克隆 git clone https...(图片中复制的内容) git提交到远程仓库 git add filename git commit -m "提交日志" git push git首次使用要配置邮箱和用户名 查看提交日志 git log 查看当前提交状态 git status

74HC154D-LED

一、引脚说明 1-11 13-17 &#xff1a;输出端。&#xff08;outputs (active LOW)&#xff09; 12&#xff1a;Gnd电源地 &#xff08;ground (0 V)&#xff09; 18-19&#xff1a;使能输入端、低电平有效 (enable inputs (active LOW)) 20-23&#xff1a;地址输入端 (addr…

ctfshow-web1~10-WP

web1 右键查看源码就能看到flag web2 打开网页提示无法查看源代码,右键也使用不了,那我们就在url前面加上view-source: view-source:http://83a83588-671e-4a94-9c6f-6857f9e20c2f.chall.ctf.show/ 访问后即可获得flag web3 右键源码也没看到信息,去查看一下请求头和响应…

私募证券基金动态-24年1月报

成交量&#xff1a;1月日均7,280.98亿元 2024年1月A股两市日均成交7,280.98亿元&#xff0c;环比下降5.40%、同比下降7.85%。1月整体22个交易日&#xff0c;无单日交易日成交金额过万亿&#xff0c;单日交易日最低成交金额为6,120.22亿元&#xff08;1月15日&#xff09;&…

【动态规划】【图论】【C++算法】1928规定时间内到达终点的最小花费

作者推荐 【动态规划】【状态压缩】【2次选择】【广度搜索】1494. 并行课程 II 本文涉及知识点 动态规划汇总 LeetCode1928. 规定时间内到达终点的最小花费 一个国家有 n 个城市&#xff0c;城市编号为 0 到 n - 1 &#xff0c;题目保证 所有城市 都由双向道路 连接在一起…

问题:淘宝网禁止出售保护动植物及其制品,以下哪种饰品可不以在淘宝上出售?() #学习方法#其他

问题&#xff1a;淘宝网禁止出售保护动植物及其制品,以下哪种饰品可不以在淘宝上出售&#xff1f;() A&#xff0e;钻石 B&#xff0e;玳瑁饰品 C&#xff0e;象牙饰品 D&#xff0e;犀牛角饰品 参考答案如图所示

vue3(笔记)

组合式Api setup-----相当于beforeCreate, create生命周期 reactive–定义状态 对象形式 响应式原理 toRefs— Pinia &#xff08;只有state、getters和actions&#xff09; 更加简洁的语法&#xff0c;完美支持Vue3的Composition api 和 对TypesCcript的完美支持

Vue3入门到实战笔记05--路由

使用路由需要做的事情&#xff1a; 1.确定好导航区、展示区 2.请来路由器 3. 制定路由的具体规则&#xff08;什么路径、对应着什么组件&#xff09; 4. 形成一个一个的.vue 1、 基本使用步骤 在cmd窗口安装: npm i vue-router在src当中创建一个router文件夹&#xff0c;并在…

docker之程序镜像的制作

目录 一、每种资源的预安装&#xff08;基础&#xff09; 安装 nginx安装 redis 二、dockerfile文件制作&#xff08;基础&#xff09; 打包 redis 镜像 创建镜像制作空间制作dockerfile 打包 nginx 镜像 三、创建组合镜像&#xff08;方式一&#xff09; 生成centos容器并…