mabatis 中

手动实现MaBatis底层机制

  • 实现任务阶段一
    • 🍍完成读取配置文件, 得到数据库连接
      • 🥦分析 + 代码实现
      • 🥦完成测试
  • 实现任务阶段二
    • 🍍编写执行器, 输入SQL语句, 完成操作
      • 🥦分析 + 代码实现
      • 🥦完成测试
  • 实现任务阶段三
    • 🍍将Sqlsession封装到执行器
      • 🥦分析 + 代码实现
      • 🥦完成测试
  • 实现任务阶段四
    • 🍍开发Mapper接口和Mapper.xml
      • 🥦分析 + 代码实现
  • 实现任务阶段五
    • 🍍开发Mapper接口相映射的MapperBean
      • 🥦分析 + 代码实现
  • 实现任务阶段六
    • 🍍在ZzwConfiguration读取xxxMapper.xml, 能够创建MapperBean对象
      • 🥦分析 + 代码实现
      • 🥦完成测试
  • 实现任务阶段七
    • 🍍实现动态代理Mapper的方法
      • 🥦分析 + 代码实现
      • 🥦完成测试
      • 🥦Debug原生MyBatis-DeaultSqlSession不同方法
      • 🥦Debug执行流程

上一篇, 我们学习到了 mabatis 上

接下来我们学习, 手动实现MaBatis底层机制

在这里插入图片描述

实现任务阶段一

🍍完成读取配置文件, 得到数据库连接

🥦分析 + 代码实现

●分析示意图
在这里插入图片描述

1.创建src/main/resouces/zzw_mybatis.xml 不一定非叫 zzw_mybatis
在这里插入图片描述

<?xml version="1.0" encoding="UTF-8" ?>
<database>
    <!--配置连接数据库的信息-->
    <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql://127.0.0.1:3306/zzw_mybatis?useSSL=true&amp;useUnicode=true&amp;characterEncoding=UTF-8"/>
    <property name="username" value="root"/>
    <property name="password" value="zzw"/>
</database>

2.创建com.zzw.zzwmybatis.sqlsession.Zzwconfiguration.java
遍历xml指定元素 参考
数据库连接的5种方式 参考

/**
 * @author 赵志伟
 * @version 1.0
 * 读取xml文件, 建立连接
 */
public class ZzwConfiguration {

    //属性-类的加载器
    private static ClassLoader loader = ClassLoader.getSystemClassLoader();

    //读取xml文件信息, 并处理
    //Connection 是java.sql包下的
    public Connection build(String resource) {

        Connection connection = null;//java.sql

        //1.得到解析器, 解析配置文件 dom4j
        SAXReader reader = new SAXReader();
        //2.加载配置文件zzw_mybatis.xml, 获取到对应的InputStream
        InputStream inputStream = loader.getResourceAsStream(resource);
        try {
            //3.得到xml文件的文档
            Document document = reader.read(inputStream);
            //4.获取rootElement / zzw_mybatis.xml的根元素, 即<database/>
            Element rootElement = document.getRootElement();
            System.out.println("root="+ rootElement.getName());//root=database
            //5.解析rootElement, 返回Connection => 单独写一个方法
            connection = evalDataSource(rootElement);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return connection;
    }

    //方法会解析zzw_config.xml信息, 并返回connection
    //eval: 评估/解析
    private Connection evalDataSource(Element node) {
        if (!"database".equals(node.getName())) {
            throw new RuntimeException("root 节点应该是<database/>");
        }
        //连接DB的必要参数
        String driverClassName = null;
        String url = null;
        String username = null;
        String password = null;

        //遍历node下的子节点, 获取属性值
        List<Element> properties = node.elements("property");
        for (Element property : properties) {

            String name = property.attributeValue("name");
            String value = property.attributeValue("value");

            //判断是否得name和value
            if (name == null || value == null) {
                throw new RuntimeException("property 节点没有设置name或者value属性");
            }

            switch (name) {
                case "driverClassName":
                    driverClassName = value;
                    break;
                case "url":
                    url = value;
                    break;
                case "username":
                    username = value;
                    break;
                case "password":
                    password = value;
                    break;
                default:
                    throw new RuntimeException("属性名没有匹配到");
            }
        }
        Connection connection = null;
        try {
            Class.forName(driverClassName);
            connection = DriverManager.getConnection(url, username, password);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return connection; //返回Connection
    }
}

🥦完成测试

com.zzw.test.ZzwMyBatisTest.java

在这里插入图片描述

public class ZzwMyBatisTest {
    @Test
    public void build() {
        ZzwConfiguration zzwConfiguration = new ZzwConfiguration();
        Connection connection = zzwConfiguration.build("zzw_mybatis.xml");
        System.out.println("connection--" + connection);
    }
}

实现任务阶段二

🍍编写执行器, 输入SQL语句, 完成操作

🥦分析 + 代码实现

●分析示意图
说明: 我们把对数据库的操作, 会封装到一套Executor机制中, 程序具有更好的扩展性, 结构更加清晰

下图在原生mybatis的项目中可以看到
在这里插入图片描述在这里插入图片描述

●代码实现
1.新建com.zzw.entity.Monster.java

/**
 * @author 赵志伟
 * @version 1.0
 * Monster和 monster表有映射关系
 *
 * 解读
 * @Getter 就会给所有属性 生成对应的getter方法
 * @Setter 就会给所有属性 生成对应的setter方法
 * @ToString 生成 toString...
 * @NoArgsConstructor 生成无参构造器
 * @AllArgsConstructor 生成全参构造器
 * @Data 注解 
 * 如何选择主要还是看自己的需求
 */
//@Getter
//@Setter
//@ToString
//@NoArgsConstructor
//@AllArgsConstructor
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Monster {
    private Integer id;
    private Integer age;
    private Date birthday;//java.util
    private String email;
    private Integer gender;
    private String name;
    private Double salary;
}

在这里插入图片描述

@Data注解包含了其他注解
在这里插入图片描述

2.新建com.zzw.zzwmybatis.sqlsession.Executor接口

public interface Executor {
    //泛型方法
    public <T> T query(String sql, Object parameter);
}

3.新建com.zzw.zzwmybatis.sqlsession.ZzwExecutor.java

自定义泛型方法, 参考

public class ZzwExecutor implements Executor {

    //属性
    private ZzwConfiguration zzwConfiguration =
            new ZzwConfiguration();

    /**
     * 根据 sql 查询结果
     * @param statement
     * @param parameter
     * @return
     * @param <T>
     */
    @Override
    public <T> T query(String sql, Object parameter) {
        //得到连接Connection
        Connection connection = getConnection();
        //查询返回的结果集
        ResultSet resultSet = null;
        PreparedStatement preparedStatement = null;

        try {
            preparedStatement = connection.prepareStatement(sql);
            //设置参数, 如果参数多, 可以使用数组处理
            preparedStatement.setString(1, parameter.toString());
            resultSet = preparedStatement.executeQuery();
            //把resultSet数据封装到对象-monster
            //说明: 这里做了简化处理
            //认为放回的结果就是一个monster记录
            //完善的写法是一套反射机制
            Monster monster = new Monster();

            //遍历结果集, 把数据封装到monster对象
            while (resultSet.next()) {
                monster.setId(resultSet.getInt("id"));
                monster.setAge(resultSet.getInt("age"));
                monster.setBirthday(resultSet.getDate("birthday"));
                monster.setEmail(resultSet.getString("email"));
                monster.setGender(resultSet.getInt("gender"));
                monster.setName(resultSet.getString("name"));
                monster.setSalary(resultSet.getDouble("salary"));
            }
            return (T) monster;
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            try {
                if (resultSet != null) {
                    resultSet.close();
                }
                if (preparedStatement != null) {
                    preparedStatement.close();
                }
                if (connection != null) {
                    connection.close();
                }
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }
    }

    //编写方法, 通过ZzwConfiguration对象, 返回连接
    private Connection getConnection() {
        Connection connection = zzwConfiguration.build("zzw_mybatis.xml");
        return connection;
    }
}

🥦完成测试

public class ZzwMyBatisTest {
    @Test
    public void query() {
        ZzwExecutor executor = new ZzwExecutor();
        Monster monster
                = executor.query("SELECT * FROM `monster` WHERE id = ?", 1);
        System.out.println("monster--" + monster);
    }
}

实现任务阶段三

🍍将Sqlsession封装到执行器

🥦分析 + 代码实现

●分析示意图. 先观察原生MyBatisSqlSession接口和默认实现. 在原生mybatis项目中
在这里插入图片描述在这里插入图片描述

●功能实现

●代码实现
1.创建com.zzw.zzwmybatis.sqlsession.ZzwSqlSession.java

/**
 * @author 赵志伟
 * @version 1.0
 * ZzwSqlSession: 搭建Configuration (连接) 和 Executor 之间的桥梁
 * 这里有操作DB的具体方法
 */
public class ZzwSqlSession {
    //属性
    //执行器
    private Executor executor = new ZzwExecutor();
    //配置
    private ZzwConfiguration zzwConfiguration =
            new ZzwConfiguration();

    //编写方法selectOne, 返回一条记录-对象[做了简化]
    //说明: 在原生的mybatis中, statement不是sql, 而是要执行的接口方法
    //这里我们是做了简化
    public <T> T selectOne(String statement, Object parameter) {
        return executor.query(statement, parameter);
    }

    //selectList - update - delete - insert
}

🥦完成测试

public class ZzwMyBatisTest {
    @Test
    public void selectOne() {
        ZzwSqlSession zzwSqlSession = new ZzwSqlSession();
        Monster monster =
                zzwSqlSession.selectOne("select * from `monster` where id = ?", 1);
        System.out.println("monster--" + monster);
    }
}

实现任务阶段四

🍍开发Mapper接口和Mapper.xml

🥦分析 + 代码实现

●分析示意图
在这里插入图片描述在这里插入图片描述

●代码实现
1.创建com.zzw.mapper.MonsterMapper接口

/**
 * @author 赵志伟
 * @version 1.0
 * MonsterMapper: 声明对db的crud方法
 */
public interface MonsterMapper {
    //查询方法
    public Monster getMonsterById(Integer id);
}

2.src/main/resources(类路径)下新建 MonsterMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<mapper namespace="com.zzw.mapper.MonsterMapper">
    <!--实现配置接口方法getMonsterById-->
    <select id="getMonsterById" resultType="com.zzw.entity.Monster">
        select * from monster where id = ?
    </select>
</mapper>

实现任务阶段五

🍍开发Mapper接口相映射的MapperBean

🥦分析 + 代码实现

●分析示意图
在这里插入图片描述

●代码实现
1.创建com.zzw.zzwmybatis.config.Function.java

/**
 * @author 赵志伟
 * @version 1.0
 * Function: 记录对应的Mapper的方法信息
 */
@Setter
@Getter
@ToString
public class Function {
    //属性
    private String sqlType;//sql类型. 比如select, insert, update, delete
    private String funcName;//方法名
    private String sql;//执行sql语句
    private Object resultType;//返回类型
    private String parameter;//参数类型
}

2.创建com.zzw.zzwmybatis.config.MapperBean.java

/**
 * @author 赵志伟
 * @version 1.0
 * MapperBean: 将Mapper信息, 进行封装
 */
@Setter
@Getter
@ToString
public class MapperBean {
    private String interfaceName;//接口的全路径-接口名
    
    //接口下的所有方法-集合
    private List<Function> functions;
}

实现任务阶段六

🍍在ZzwConfiguration读取xxxMapper.xml, 能够创建MapperBean对象

🥦分析 + 代码实现

●分析示意图

●代码实现
1.修改com.zzw.zzwmybatis.sqlsession.Zzwconfiguration.java, 增加方法

//读取xxxMapper.xml, 能够创建MapperBean对象
//path 就是xml的路径+文件名, 是从类的加载路径计算的
//如果: xxxMapper.xml 文件是放在resources目录下, 直接传入xml文件名即可
public MapperBean readMapper(String path) {

    MapperBean mapperBean = new MapperBean();

    //1.得到解析器 -> dom4j
    SAXReader reader = new SAXReader();
    //2.获取到xml文件对应的InputStream
    InputStream inputStream = loader.getResourceAsStream(path);
    try {
        //3.得到xml文件的文档
        Document document = reader.read(inputStream);
        //4.获取xml文档的根元素 <mapper/>
        Element rootElement = document.getRootElement();
        System.out.println("root="+ rootElement);

        //获取到namespace
        String namespace = rootElement.attributeValue("namespace").trim();
        //设置mapperBean的属性interfaceName
        mapperBean.setInterfaceName(namespace);

        //得到rootElement的迭代器-可以遍历它的子节点/子元素-生成Function
        Iterator<Element> rootIterator = rootElement.elementIterator();

        //保存接口下所有的方法信息
        List<Function> functions = new ArrayList<>();
        //遍历它的子节点/子元素-生成Function
        while (rootIterator.hasNext()) {
            //取出一个子元素-dom4j.Element
            Element element = rootIterator.next();
            /*
            <select id="getMonsterById" resultType="com.zzw.entity.Monster">
                select * from monster where id = ?
            </select>
             */
            Function function = new Function();
            String sqlType = element.getName().trim();
            String funcName = element.attributeValue("id").trim();
            String sql = element.getTextTrim();//等价于: getText().trim()
            //resultType是返回类型的全路径-即全类名
            String resultType = element.attributeValue("resultType").trim();
            //开始封装
            function.setSqlType(sqlType);
            function.setFuncName(funcName);
            function.setSql(sql);
            //这里多说一句 function-private Object resultType; 是resultType实例
            //所以我们使用反射生成一个对象, setResultType
            Object instance = Class.forName(resultType).newInstance();
            function.setResultType(instance);

            //将封装好的function对象放人到 list
            functions.add(function);
        }
        //while循环结束后, 将function的list设置
        mapperBean.setFunctions(functions);
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
    return mapperBean;
}

🥦完成测试

public class ZzwMyBatisTest {
    @Test
    public void readMapper() {
        ZzwConfiguration zzwConfiguration = new ZzwConfiguration();
        MapperBean mapperBean = zzwConfiguration.readMapper("MonsterMapper.xml");
        System.out.println("mapperBean--" + mapperBean);
        System.out.println("ok~~");
    }
}

实现任务阶段七

🍍实现动态代理Mapper的方法

🥦分析 + 代码实现

●分析示意图
无

前面我们有2个地方学习过动态代理, 切面编程的底层支撑是动态代理
动态代理: AOP切面编程
动态代理: 手动实现spring底层机制

●代码实现
1.新增com.zzw.zzwmybatis.sqlsession.ZzwMapperProxy.java
转String类型

/**
 * @author 赵志伟
 * @version 1.0
 * ZzwMapperProxy: 动态代理生成Mapper对象, 调用ZzwExecutor方法
 */
@SuppressWarnings({"all"})
public class ZzwMapperProxy implements InvocationHandler {
    //属性
    private ZzwSqlSession zzwSqlSession;
    private String mapperFile;
    private ZzwConfiguration zzwConfiguration;

    //构造器
    public ZzwMapperProxy(ZzwSqlSession zzwSqlSession,
                          ZzwConfiguration zzwConfiguration,
                          Class clazz) {
        this.zzwSqlSession = zzwSqlSession;
        this.zzwConfiguration = zzwConfiguration;
        this.mapperFile = clazz.getSimpleName() + ".xml";
    }

    //前面讲解spring时, 讲过动态代理知识
    //提示: 当执行Mapper接口的代理对象方法时, 会执行到invoke方法
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        MapperBean mapperBean =
                zzwConfiguration.readMapper(this.mapperFile);

        //判断是否是xml文件对应的接口
        if (!method.getDeclaringClass().getName().equals(mapperBean.getInterfaceName())) {
            return null;
        }

        //取出mapperBean的functions
        List<Function> functions = mapperBean.getFunctions();
        //判断当前mapperBean解析对应MapperXML后, 有方法
        if (functions != null && functions.size() != 0) {

            for (Function function : functions) {
                //当前要执行的方法和function.getFuncName()一样
                //说明我们可以从当前遍历的function对象中, 取出相应的信息sql, 并执行方法
                if (method.getName().equals(function.getFuncName())) {{
                    //如果我们当前的function 要执行的sqlType是select
                    //我们就去执行selectOne
                    /**
                     * 说明:
                     * 1. 如果要执行的方法是select, 就对应执行selectOne
                     * 2. 因为我们在ZzwSqlSession就写了一个 selectOne
                     * 3. 实际上ZzwSqlSession对应不同的方法(多个方法)
                     * , 根据不同的匹配情况调用不同方法, 并且还需要进行参数解析处理, 还有比较复杂的字符串处理, 拼接sql, 处理返回类型等等工作
                     * 4. 因为我们主要是想讲解mybatis 生成mapper动态代理对象, 调用方法的机制, 所以我们做了简化
                     */
                    if ("select".equals(function.getSqlType())) {
                        return zzwSqlSession.selectOne(function.getSql(), String.valueOf(args[0]));
                    }
                }}
            }
        }
        return null;
    }
}

2.修改com.zzw.zzwmybatis.sqlsession.ZzwSqlSession, 增加方法

/**
 * 1. 返回mapper的动态代理对象
 * 2. 这里的clazz 到时传入的是 MonsterMapper.class
 * 3. 放回的就是MonsterMapper接口代理对象
 * 4. 当执行接口方法时(通过代理对象调用), 根据动态代理机制, 会执行到ZzwMapperProxy-invoke
 * @param clazz
 * @return
 * @param <T>
 */
public <T> T getMapper(Class<T> clazz) {
    //返回动态代理对象
    return (T) Proxy.newProxyInstance(clazz.getClassLoader(), new Class[]{clazz}, new ZzwMapperProxy(this, zzwConfiguration, clazz));
}

🥦完成测试

1.测试com.zzw.test.ZzwMyBatisTest

public class ZzwMyBatisTest {
    @Test
    public void getMapper() {
        ZzwSqlSession zzwSqlSession = new ZzwSqlSession();
        MonsterMapper mapper = zzwSqlSession.getMapper(MonsterMapper.class);
        System.out.println("mapper运行类型=" + mapper.getClass());//mapper是一个代理对象
        Monster monster = mapper.getMonsterById(1);
        System.out.println("monster--" + monster);
    }
}

2.新建com.zzw.zzwmybatis.sqlsession.ZzwSessionFactory

/**
 * @author 赵志伟
 * @version 1.0
 * ZzwSessionFactory: 会话工厂-返回会话ZzwSqlSession
 */
public class ZzwSessionFactory {

    public static ZzwSqlSession openSession() {
        return new ZzwSqlSession();
    }
}

3.测试com.zzw.test.ZzwMyBatisTest

public class ZzwMyBatisTest {
    @Test
    public void openSession() {
        ZzwSqlSession zzwSqlSession = ZzwSessionFactory.openSession();
        MonsterMapper mapper = zzwSqlSession.getMapper(MonsterMapper.class);
        Monster monster = mapper.getMonsterById(1);
        System.out.println("monster--" + monster);
    }
}

🥦Debug原生MyBatis-DeaultSqlSession不同方法

找到mybatis项目, 在DefaultSqlSessionselectOne方法打上断点, 测试select方法

同时证明:原生的mybatis中,selectOne方法的statement参数不是sql, 而是要执行的接口方法

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

Step Into, 追到BaseExecutordoQuery方法

在这里插入图片描述

继续 Step Into

在这里插入图片描述

继续 Step Into

在这里插入图片描述

继续 Step Into

在这里插入图片描述

继续 Step Into

在这里插入图片描述

继续 Step Into

在这里插入图片描述

继续 Step Into

在这里插入图片描述

继续 Step Into, doQuery里面就是原生的Jdbc代码了

在这里插入图片描述

DefaultSqlSessioninsert方法打上断点, 测试insert方法
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

Step Into

在这里插入图片描述

继续 Step Into

在这里插入图片描述

继续 Step Into

在这里插入图片描述

继续 Step Into, doUpdate方法里面就是原生的Jdbc代码了

在这里插入图片描述

DefaultSqlSessiondelete方法打上断点, 测试delete方法
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

DefaultSqlSessionupdate方法打上断点, 测试update方法
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

🥦Debug执行流程

回到自己写的zzw-mybatis项目, 开始debug
在这里插入图片描述

Step Into

在这里插入图片描述

Step Into

在这里插入图片描述

Step Out

在这里插入图片描述

估值

在这里插入图片描述

Step Into

在这里插入图片描述

Step Out

在这里插入图片描述

估值, mapper是个代理对象

在这里插入图片描述

ZzwMapperProxyinvoke方法下个断点, 直接放行

在这里插入图片描述

mapperBean估值

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

Step Into

在这里插入图片描述

继续 Step Into

在这里插入图片描述

查看传进来的参数

在这里插入图片描述

拿到Jdbc的结果集

在这里插入图片描述

Step Out

在这里插入图片描述

monster进行估值

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Redis缓存预热-缓存穿透-缓存雪崩-缓存击穿

什么叫缓存穿透? 模拟一个场景: 前端用户发送请求获取数据,后端首先会在缓存Redis中查询,如果能查到数据,则直接返回.如果缓存中查不到数据,则要去数据库查询,如果数据库有,将数据保存到Redis缓存中并且返回用户数据.如果数据库没有则返回null; 这个缓存穿透的问题就是这个…

使用python将数据输出为图表图片

数据示例&#xff08;数组或其他&#xff09;&#xff1a; hourly_data {00:00: 10,01:00: 15,02:00: 20,03:00: 25,04:00: 30,# 添加更多数据... }示例输出&#xff08;图片&#xff09;&#xff1a; python代码&#xff1a; 下面代码中使用了matplotlib库&#xff0c;如果…

Mac系统:mysql+jdk+neo4j

mysql 指令 //启动MySQL服务 sudo /usr/local/mysql/support-files/mysql.server start//停止MySQL服务 sudo /usr/local/mysql/support-files/mysql.server stop //连接MySQL数据库&#xff0c;在进行这一步前要先关掉服务 mysql -u root -p //检查MySQL服务状态 sudo /us…

JDK17镜像制作

背景 获取JDK17 wget https://download.oracle.com/java/17/latest/jdk-17_linux-x64_bin.tar.gz 解压JDK tar -zxvf jdk-17_linux-x64_bin.tar.gz 制作JRE 由于jdk的体积比较大&#xff0c;可以使用jre来作为运行环境&#xff0c;jdk1.8及以前版本&#xff0c;自带jre&#…

力扣--动态规划/回溯算法131.分割回文串

思路分析&#xff1a; 动态规划 (DP)&#xff1a; 使用动态规划数组 dp&#xff0c;其中 dp[i][j] 表示从字符串 s[i] 到 s[j] 是否为回文子串。预处理动态规划数组&#xff1a; 从字符串末尾开始&#xff0c;遍历每个字符组合&#xff0c;判断是否为回文子串&#xff0c;填充…

后悔没有早点看到这份产品说明书模板

产品说明书是连接产品与消费者的桥梁&#xff0c;它对产品具有多重好处。一份设计精良、内容准确的产品说明书有助于消费者全面了解产品&#xff0c;确保用户正确使用产品&#xff1b;减少消费者因误操作导致的故障&#xff0c;降低企业的售后服务成本&#xff1b;增强消费者对…

GaLore的全称是“Gradient Low-Rank Projection“,翻译过来就是“梯度低秩投影“

鉴于大家对GaLore比较感兴趣,我今天试着结合论文做一个更深入的解读: GaLore的全称是"Gradient Low-Rank Projection",翻译过来就是"梯度低秩投影"。它的核心思想是通过降低优化器状态的秩,来大幅减少内存占用。 在训练大模型时,我们需要存储三类数据:模型…

操作系统基础

进程与线程 进程之间如何通讯 用户态与核心态 进程空间 操作系统内存管理 TBL TBL 多级页表虽然解决了空间上的问题&#xff0c;但是我们发现这种方式需要走多道转换才能找到映射的物理内存地址&#xff0c;经过的多道转换造成了时间上的开销。 程序是局部性的&#xff0c;即…

新质生产力简介

新质生产力简介 新质生产力概述&#xff1a; 新质生产力是以科技创新为核心&#xff0c;实现关键性颠覆性技术突破&#xff0c;推动社会经济发展的高效能、高质量生产力。 新质生产力的本质 新质生产力的本质是“科技创新” 新质生产力的核心是科技创新 新质生产力简介 新质…

全面对比Amazon DocumentDB 与 MongoDB

在云中部署 MongoDB 似乎有多种选择。例如&#xff0c;Amazon DocumentDB自称是完全支持 MongoDB API 的 AWS 原生数据库。虽然它支持一些 MongoDB 功能&#xff0c;但需要注意的是 DocumentDB 并不完全兼容 MongoDB。要在 AWS 上访问功能齐全的“MongoDB 即服务”&#xff0c;…

微服务技术栈SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式(五):分布式搜索 ES-上

文章目录 一、ElasticSearch1.1 概述1.2 倒排索引1.3 ES与MySQL的概念对比 二、 安装2.1 部署单点ES2.2 部署kibana 三、安装IK分词器3.1 在线安装ik插件&#xff08;较慢&#xff09;3.2 离线安装ik插件&#xff08;推荐&#xff09;3.3 扩展词词典3.4 停用词词典 四、索引库操…

【数据结构】汇总二、线性表(逻辑结构、物理(存储)结构、基本操作、1.顺序表2.单链表3.双链表4.循环链表5.静态链表6.顺序表与链表的对比不同)

文章目录 线性表linear list逻辑结构物理&#xff08;存储&#xff09;结构基本操作1.顺序表1.0特点1.1静态分配1.2动态分配1.3插入1.4删除1.5查找1.5.1按位查找1.5.2按值查找 2.单链表2.1不带头结点的单链表2.2带头结点的单链表2.3插入2.3.1按位序插入2.3.1.1带头结点2.3.1.2不…

MIT6.828LAB4 (4)

LAB3_Part C: Preemptive Multitasking and Inter-Process communication (IPC) 文章目录 LAB3_Part C: Preemptive Multitasking and Inter-Process communication (IPC)前言练习13练习14练习15总结 前言 记录一下自己的学习过程 实验内容翻译&#xff1a; https://gitee.com/…

Python 导入Excel三维坐标数据 生成三维曲面地形图(体) 5-3、线条平滑曲面且可通过面观察柱体变化(三)

环境 python:python-3.12.0-amd64 包: matplotlib 3.8.2 pandas 2.1.4 openpyxl 3.1.2 scipy 1.12.0 import pandas as pd import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D from scipy.interpolate import griddata from matplotlib.c…

Vue-Router路由介绍和使用

vue属于单页面应用&#xff0c;路由就是根据浏览器路径不同&#xff0c;用不同的试图组件替换这个页面内容 开启路由功能 如图在创建项目时候勾选rouler 这样创建好的项目就有路由功能 下一步 不同的访问路径 展示不同的页面内容 路由配置 路由连接组件 浏览器会解析为超链接 …

OpenCV开发笔记(七十六):相机标定(一):识别棋盘并绘制角点

若该文为原创文章&#xff0c;转载请注明原文出处 本文章博客地址&#xff1a;https://blog.csdn.net/qq21497936/article/details/136535848 各位读者&#xff0c;知识无穷而人力有穷&#xff0c;要么改需求&#xff0c;要么找专业人士&#xff0c;要么自己研究 红胖子(红模仿…

爬虫练习:获取某网站的房价信息

一、相关网站 二、相关代码 import requests from lxml import etree import csv with open(房天下数据.csv, w, newline, encodingutf-8) as csvfile:fieldnames [名称, 地点,价格,总价,联系电话]writer csv.DictWriter(csvfile, fieldnamesfieldnames)writer.writeheader…

MySQL临时表创建出错(OS errno 13 - Permission denied)

一个客户向我抱怨&#xff1a;在MySQL查询小表没有问题&#xff0c;查询大表出错&#xff0c;下面是他发给我的出错的部分截屏&#xff08;客户的表名被我隐藏了&#xff09;。 这里的给出的信息已经比较明显了&#xff0c;是向/tmp目录中创建临时表失败&#xff08;临时表的路…

在用Java写算法的时候如何加快读写速度

对于解决该方法我们一般如下操作&#xff0c;不需要知道为什么&#xff0c;有模板&#xff08;个人观点&#xff09; 使用BufferedReader代替Scanner&#xff1a;Scanner类在读取大量输入时性能较差&#xff0c;而BufferedReader具有更高的读取速度。可以使用BufferedReader的r…

B端系统:漂亮就行。扯淡,漂亮仅占五分之一!

Hi&#xff0c;我是贝格前端工场&#xff0c;接触N多B端系统&#xff0c;也优化升级过N多。在这个过程中&#xff0c;仅仅美观是不够的&#xff0c;所以我拓展出来的B端系统五度评价指标&#xff0c;本篇着重讲易用性指标&#xff0c;欢迎老铁们评论点赞转发&#xff0c;有需求…