[C++][第三方库][ODB]详细讲解

article/2025/8/15 23:01:36

目录

  • 1.介绍
  • 2.安装
    • 1.安装 build2
    • 2.安装 odb-compiler
    • 3.安装 ODB 运行时库
    • 4.安装MySQL和客户端开发包
    • 5.安装 boost profile 库
    • 6.总体操作
    • 7.测试样例
  • 3.ODB 常见操作
    • 1.ODB 类型映射
    • 2.ODB 编程
      • 1.指令
      • 2.示例
  • 4.类与接口
  • 5.使用


1.介绍

  • ODB框架:数据库ORM框架 --> 对象关系映射框架
  • 形象理解将数据结构与数据库表进行关系映射,通过数据结构的操作实现数据库中数据操作
    • 通过ODB框架实现MySQL数据库的关系映射操作

2.安装

1.安装 build2

  • 因为build2安装时,可能会版本更新,因此注意, 先从build2官网查看安装步骤
  • 如果安装过程中,因为网络问题超时失败,可以尝试:将超时时间设置的更长一些
    sh build2-install-0.17.0.sh --timeout 1800
    

2.安装 odb-compiler

#注意这里的gcc-13需要根据自己现有版本而定
~/workspace$ sudo apt-get install gcc-13-plugin-dev
~/workspace$ mkdir odb-build && cd odb-build~/workspace/odb-build$ bpkg create -d odb-gcc-N cc \config.cxx=g++ \config.cc.coptions=-O3 \config.bin.rpath=/usr/lib \config.install.root=/usr/ \config.install.sudo=sudo~/workspace/odb-build$ cd odb-gcc-N
~/workspace/odb-build/odb-gcc-N$ bpkg build odb@https://pkg.cppget.org/1/beta
~/workspace/odb-build/odb-gcc-N$ bpkg test odb
~/workspace/odb-build/odb-gcc-N$ bpkg install odb
~/workspace/odb-build/odb-gcc-N$ odb --version# 如果上述命令报错找不到odb,则执行下面的命令
$ sudo echo 'export PATH=${PATH}:/usr/local/bin' >> ~/.bashrc
$ export PATH=${PATH}:/usr/local/bin
$ odb --version

3.安装 ODB 运行时库

~/workspace/odb-build/odb-gcc-N$ cd ..~/workspace/odb-build$ bpkg create -d libodb-gcc-N cc \config.cxx=g++ \config.cc.coptions=-O3 \config.install.root=/usr/ \config.install.sudo=sudo~/workspace/odb-build$ cd libodb-gcc-N
~/workspace/odb-build/libodb-gcc-N$ bpkg add https://pkg.cppget.org/1/beta
~/workspace/odb-build/libodb-gcc-N$ bpkg fetch
~/workspace/odb-build/libodb-gcc-N$ bpkg build libodb
~/workspace/odb-build/libodb-gcc-N$ bpkg build libodb-mysql

4.安装MySQL和客户端开发包

  • 安装
    sudo apt install mysql-server
    sudo apt install -y libmysqlclient-dev
    
  • 配置MySQLsudo vim /etc/my.cnf或者/etc/mysql/my.cnf,有哪个修改哪个
    # 添加以下内容 
    [client] 
    default-character-set=utf8 
    [mysql] 
    default-character-set=utf8 
    [mysqld] 
    character-set-server=utf8 
    bind-address = 0.0.0.0 
    
  • 修改root用户密码
    sudo cat /etc/mysql/debian.cnf
    sudo mysql -u debian-sys-maint -p
    Enter password: # 这里输入上边看到的密码mysql> ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'PASSWORD';mysql> FLUSH PRIVILEGES;mysql> quit
    
  • 重启MySQL,并设置开机启动
    sudo systemctl restart mysql 
    sudo systemctl enable mysql
    

5.安装 boost profile 库

bpkg build libodb-boost

6.总体操作

  • 总体打包安装
    bpkg install --all --recursive
    
  • 总体卸载
    bpkg uninstall - all --recursive
    
  • 总体升级
    bpkg fetch
    bpkg status
    bpkg uninstall - all --recursive
    bpkg build --upgrade --recursive
    bpkg install --all --recursive
    

7.测试样例

  • 编写数据结构文件person.hpp
    #pragma once
    #include <string>
    #include <cstddef>
    #include <boost/date_time/posix_time/posix_time.hpp>// 在C++中,要使用ODB将类声明为持久化类,需要包含ODB的核心头文件,并使用#pragma db object指令
    // #pragma db object 指示 ODB 编译器将 person 类视为一个持久化类
    #include <odb/core.hxx>typedef boost::posix_time::ptime ptime;#pragma db object
    class Person
    {
    public:Person(const std::string &name, int age, const ptime &update): _name(name), _age(age), _update(update){}void age(int val) { _age = val; }int age() { return _age; }void name(const std::string &val) { _name = val; }std::string name() { return _name; }void update(const ptime &update) { _update = update; }std::string update() {return boost::posix_time::to_simple_string(_update);}private:// 将odb::access类作为Person类的友元// 这是使数据库支持代码可访问默认构造函数和数据成员所必需的// 如果类具有公共默认构造函数和公共数据成员或数据成员的公共访问器和修饰符,则不需要友元声明friend class odb::access;Person() {}// _id 成员前面的 pragma 告诉 ODB 编译器,以下成员是对象的标识符
    // auto说明符指示它是数据库分配的 ID
    #pragma db id auto      // 表示 ID 字段将自动生成(通常是数据库中的主键)。 unsigned long _id;unsigned short _age;std::string _name;
    #pragma db type("TIMESTAMP") not_nullboost::posix_time::ptime _update;
    };
    // 将 ODB 编译指示组合在一起,并放在类定义之后。它们也可以移动到一个单独的标头中,使原始类完全保持不变
    // #pragma db object(person)
    // #pragma db member(person::_name) id
    // 完成后,需要使用 odb 编译器将当前所写的代码生成数据库支持代码
    // odb -d mysql --generate-query --generate-schema person.hxx
    // 如果用到了 boost 库中的接口,则需要使用选项 : --profile boost/datetime
    // odb -d mysql --generate-query --generate-schema --profile boost/date-time person.hxx
    
  • 生成数据库支持的代码文件
    $ odb -d mysql --generate-query --generate-schema --profile boost/date-time person.hpp$ ls
    person.hpp  person-odb.cxx  person-odb.hxx  person-odb.ixx  person.sql
    
  • 编写主函数代码main.cc
    #include <string>
    #include <memory>
    #include <cstdlib>
    #include <iostream>
    #include <odb/database.hxx>
    #include <odb/mysql/database.hxx>
    #include "person.hpp"
    #include "person-odb.hxx"int main()
    {std::shared_ptr<odb::core::database> db(new odb::mysql::database("root", "SnowK8989", "TestDB", "127.0.0.1", 0, 0, "utf8"));if (!db){return -1;}ptime p = boost::posix_time::second_clock::local_time();Person Die("Die", 18, p);Person SnowK("SnowK", 19, p);typedef odb::query<Person> query;typedef odb::result<Person> result;// 新增数据{odb::core::transaction t(db->begin());size_t zid = db->persist(Die);size_t wid = db->persist(SnowK);t.commit();}// 查询数据{odb::core::transaction t (db->begin()); result r (db->query<Person>()); for (result::iterator i(r.begin()); i != r.end(); ++i) {std::cout << "Hello, " << i->name() << " ";std::cout << i->age() << " " << i->update() << std::endl; } t.commit();}return 0;
    }// 如果用到了boost库中的接口,需要链接库: -lodb-boost
    // c++ -o mysql_test mysql_test.cpp person-odb.cxx -lodb-mysqllodb - lodb - boost
    
  • 代码编译
    c++ -o test test.cpp person odb.cxx -lodb-mysql -lodb -lodb-boost
    

3.ODB 常见操作

1.ODB 类型映射

请添加图片描述


2.ODB 编程

1.指令

  • ODB(Open Database)在数据元结构定义时,使用预处理器指令(#pragma)来提供元数据
    • 这些元数据指示如何将C++类型映射到数据库模式
    • 这些#pragma指令是在C++代码中使用的,它们不是C++语言的一部分,而是特定于ODB 编译器的扩展
  • 常用#pragma指令
    • 表的映射

      • #pragma db object:用于声明一个类是数据库对象
        • 这个类将映射到数据库中的一个表
      • #pragma db table("table_name"):指定类映射到数据库中的表名
        • 如果不指定,则默认使用类名
    • 字段的映射

      • #pragma db id:标记类中的一个成员变量作为数据库表的主键
      • #pragma db column("column_name"):指定类成员映射到数据库表中的列名
        • 如果不指定,则默认使用成员变量的名字
      • #pragma db auto:指定成员变量的值在插入时自动生成
        • 例如:自动递增的主键
      • #pragma db type("type_name"):指定成员变量不应该被持久化到数据库中
      • #pragma db unique:指定成员变量或一组变量应该具有唯一性约束
      • #pragma db index("index_name"):指定成员变量应该被索引
      • #pragma db null:指定成员变量允许为空
        • odb::nullable<>也可以实现
      • #pragma db not_null:指定成员变量不允许为空
      • #pragma db default("default_value"):指定成员变量的默认值
    • 查询相关

      • #pragma db view:用于声明一个类是一个数据库视图,而不是一个表
      • #pragma db query("query"):用于定义自定义的查询函数
    • 其它

      • #pragma db session:用于声明一个全局或成员变量是数据库会话
      • #pragma db transient:指定成员变量不应该被持久化到数据库中
      • #pragma db convert("converter"):指定用于成员变量的自定义类型转换器
      • #pragma db pool("pool_name"):指定用于数据库连接的连接池
      • #pragma db trigger("trigger_name"):指定在插入、更新或删除操作时触发的触发器

2.示例

#pragma once
#include <string>
#include <cstddef>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <odb/nullable.hxx>
#include <odb/core.hxx>#pragma db object // 声明一个类是数据库对象
class Student
{
public:Student() {}Student(unsigned long sn, const std::string &name, unsigned short age, unsigned long cid) : _sn(sn), _name(name), _age(age), _classes_id(cid) {}void sn(unsigned long num) { _sn = num; }unsigned long sn() { return _sn; }void name(const std::string &name) { _name = name; }std::string name() { return _name; }void age(unsigned short num) { _age = num; }odb::nullable<unsigned short> age() { return _age; }void classes_id(unsigned long cid) { _classes_id = cid; }unsigned long classes_id() { return _classes_id; }private:// 将odb::access类作为Person类的友元// 这是使数据库支持代码可访问默认构造函数和数据成员所必需的friend class odb::access;// id: 标记成员变量为主键, auto: 值在插入时自动生成#pragma db id autounsigned long _id;// unique: 指定变量或一组变量具有唯一键约束#pragma db uniqueunsigned long _sn;std::string _name;odb::nullable<unsigned short> _age;// 指定成员变量应该被索引#pragma db indexunsigned long _classes_id;
};#pragma db object
class Classes
{
public:Classes() {}Classes(const std::string &name) : _name(name) {}void name(const std::string &name) { _name = name; }std::string name() { return _name; }private:friend class odb::access;#pragma db id autounsigned long _id;std::string _name;
};// 查询所有的学生信息, 并显示班级名称
#pragma db view object(Student)\object(Classes = classes : Student::_classes_id == classes::_id)\query((?)) // 用于自定义查询函数
struct Classes_Student
{// 指定类成员映射到数据库表中的列名#pragma db column(Student::_id)unsigned long id;#pragma db column(Student::_sn)unsigned long sn;#pragma db column(Student::_name)std::string name;#pragma db column(Student::_age)odb::nullable<unsigned short> age;#pragma db column(classes::_name)std::string classes_name;
};// 只查询学生姓名, (?): 外部调用时传入的过滤条件
#pragma db view query("select name from Student + (?)")
struct All_Name
{std::string name;
};// odb -d mysql --std c++11 --generate-query --generate-schema --profile boost/date-time student.hpp

4.类与接口

namespace odb
{ namespace mysql { // mysql连接池对象类class LIBODB_MYSQL_EXPORT new_connection_factory:  public connection_pool_factory{ connection_pool_factory (std::size_t max_connections = 0, std::size_t min_connections = 0, bool ping = true);}; }// 操作句柄类, 实现数据库的增删查改操作class LIBODB_EXPORT database { // 新增数据 persist (T& object); // 更新数据 void update (T& object);// 删除数据void erase (T& object); unsigned long long erase_query (const std::string&);// 过滤并删除unsigned long long erase_query (const odb::query<T>&);result<T> query (const std::string&); // 查询result<T> query (const odb::query<T>&, bool cache = true);typename result<T>::pointer_type query_one(const odb::query<T>&); // 获取事务对象指针virtual transaction_impl* begin () = 0; }; // 事务操作类class LIBODB_EXPORT transaction { transaction (transaction_impl*, bool make_current = true); void commit ();   // 事务提交操作void rollback (); // 事务回滚操作}// 针对可能为空的字段封装的类似于智能指针的类型template <typename T> class nullable { typedef T value_type; T&       get (); const T& get () const; T*       operator-> (); const T* operator-> () const; T&       operator* (); const T& operator* () const; };// 针对查询结果所封装的容器类 template <typename T> class result: result_base<T, class_traits<T>::kind> { result ();result (const result& r);iterator begin ();iterator end ();size_type size (); bool empty ();};// 针对查询封装的条件类class LIBODB_EXPORT query_base { explicit query_base (const std::string& native);const clause_type& clause ();};namespace mysql { template <typename T> class query: public query_base,public query_selector<T, id_mysql>::columns_type { query (const std::string& q);query (const query_base& q); query (bool v);};}     // 过滤条件类template <typename T> class query<T, mysql::query_base>: public mysql::query<T>  { query (bool v);query (const std::string& q);query (const mysql::query_base& q);} 
}

5.使用

  • Student.hpp
    #pragma once
    #include <string>
    #include <cstddef>
    #include <boost/date_time/posix_time/posix_time.hpp>
    #include <odb/nullable.hxx>
    #include <odb/core.hxx>#pragma db object // 声明一个类是数据库对象
    class Student
    {
    public:Student() {}Student(unsigned long sn, const std::string &name, unsigned short age, unsigned long cid) : _sn(sn), _name(name), _age(age), _classes_id(cid) {}void sn(unsigned long num) { _sn = num; }unsigned long sn() { return _sn; }void name(const std::string &name) { _name = name; }std::string name() { return _name; }void age(unsigned short num) { _age = num; }odb::nullable<unsigned short> age() { return _age; }void classes_id(unsigned long cid) { _classes_id = cid; }unsigned long classes_id() { return _classes_id; }private:// 将odb::access类作为Person类的友元// 这是使数据库支持代码可访问默认构造函数和数据成员所必需的friend class odb::access;// id: 标记成员变量为主键, auto: 值在插入时自动生成#pragma db id autounsigned long _id;// unique: 指定变量或一组变量具有唯一键约束#pragma db uniqueunsigned long _sn;std::string _name;odb::nullable<unsigned short> _age;// 指定成员变量应该被索引#pragma db indexunsigned long _classes_id;
    };#pragma db object
    class Classes
    {
    public:Classes() {}Classes(const std::string &name) : _name(name) {}void name(const std::string &name) { _name = name; }std::string name() { return _name; }private:friend class odb::access;#pragma db id autounsigned long _id;std::string _name;
    };// 查询所有的学生信息, 并显示班级名称
    #pragma db view object(Student)\object(Classes = classes : \Student::_classes_id == classes::_id)\query((?)) // 用于自定义查询函数
    struct Classes_Student
    {// 指定类成员映射到数据库表中的列名#pragma db column(Student::_id)unsigned long id;#pragma db column(Student::_sn)unsigned long sn;#pragma db column(Student::_name)std::string name;#pragma db column(Student::_age)odb::nullable<unsigned short> age;#pragma db column(classes::_name)std::string classes_name;
    };// 只查询学生姓名, (?): 外部调用时传入的过滤条件
    #pragma db view query("select name from Student" + (?))
    struct All_Name
    {std::string name;
    };// odb -d mysql --std c++11 --generate-query --generate-schema --profile boost/date-time student.hpp
    
  • main.cc
    #include <odb/database.hxx>
    #include <odb/mysql/database.hxx>
    #include <gflags/gflags.h>
    #include "student.hpp"
    #include "student-odb.hxx"DEFINE_string(host, "127.0.0.1", "Mysql服务器地址");
    DEFINE_int32(port, 0, "Mysql服务器端口");
    DEFINE_string(db, "TestDB", "数据库默认库名称");
    DEFINE_string(user, "root", "Mysql用户名");
    DEFINE_string(pwd, "SnowK8989", "Mysql密码");
    DEFINE_string(cset, "utf8", "Mysql客户端字符集");
    DEFINE_int32(max_pool, 3, "Mysql连接池最大连接数量");void Insert_Classes(odb::mysql::database& db)
    {try{// 3.获取事务对象, 开启事务odb::transaction trans(db.begin());Classes c1("Electronic 221");Classes c2("Electronic 222");db.persist(c1);db.persist(c2);// 5.提交事务trans.commit();}catch(const std::exception& e){std::cout << "插入数据出错: " << e.what() << std::endl;}
    }void Insert_Student(odb::mysql::database &db)
    {try{// 3.获取事务对象, 开启事务odb::transaction trans(db.begin());Student s1(1, "张三", 18, 1);Student s2(2, "李四", 19, 1);Student s3(3, "王五", 18, 1);Student s4(4, "赵六", 15, 2);Student s5(5, "刘七", 18, 2);Student s6(6, "孙八", 23, 2);db.persist(s1);db.persist(s2);db.persist(s3);db.persist(s4);db.persist(s5);db.persist(s6);// 5. 提交事务trans.commit();}catch (const std::exception &e){std::cout << "插入学生数据出错: " << e.what() << std::endl;}
    }// 先查询,再修改
    void Update_Student(odb::mysql::database &db, Student &stu)
    {try{// 3.获取事务对象, 开启事务odb::transaction trans(db.begin());db.update(stu);// 5. 提交事务trans.commit();}catch (const std::exception &e){std::cout << "更新学生数据出错: " << e.what() << std::endl;}
    }// TODO
    Student Select_Student(odb::mysql::database &db)
    {Student ret;try{// 3.获取事务对象, 开启事务odb::transaction trans(db.begin());odb::result<Student> r(db.query<Student>(odb::query<Student>::name == "张三"));if (r.size() != 1){std::cout << "数据量不对" << std::endl;return Student();}ret = *r.begin();// 5. 提交事务trans.commit();}catch (const std::exception &e){std::cout << "更新学生数据出错: " << e.what() << std::endl;}return ret;
    }void Remove_Student(odb::mysql::database &db)
    {try{// 3.获取事务对象, 开启事务odb::transaction trans(db.begin());// 查询和删除操作合并db.erase_query<Student>(odb::query<Student>::name == "李四");// 5. 提交事务trans.commit();}catch (const std::exception &e){std::cout << "更新学生数据出错: " << e.what() << std::endl;}
    }void Classes_Student(odb::mysql::database &db)
    {try{// 3.获取事务对象, 开启事务odb::transaction trans(db.begin());typedef odb::query<struct Classes_Student> query;typedef odb::result<struct Classes_Student> result;result r(db.query<struct Classes_Student>(query::classes::id == 1));for (auto it = r.begin(); it != r.end(); ++it){std::cout << it->id << std::endl;std::cout << it->sn << std::endl;std::cout << it->name << std::endl;std::cout << *it->age << std::endl; // nullable类型类似智能指针, 需要解引用std::cout << it->classes_name << std::endl;}// 5. 提交事务trans.commit();}catch (const std::exception &e){std::cout << "更新学生数据出错: " << e.what() << std::endl;}
    }void All_Student(odb::mysql::database &db)
    {try{// 3.获取事务对象, 开启事务odb::transaction trans(db.begin());typedef odb::query<Student> query;typedef odb::result<All_Name> result;result r(db.query<All_Name>(query::id == 1));for (auto it = r.begin(); it != r.end(); ++it){std::cout << it->name << std::endl;}// 5. 提交事务trans.commit();}catch (const std::exception &e){std::cout << "查询所有学生姓名数据出错: " << e.what() << std::endl;}
    }int main(int argc, char *argv[])
    {google::ParseCommandLineFlags(&argc, &argv, true);// 1.构造连接池工厂配置对象, 这里只能用unique_ptrauto cpf = std::make_unique<odb::mysql::connection_pool_factory>(FLAGS_max_pool, 0);// 2.构造数据库操作对象odb::mysql::database db(FLAGS_user, FLAGS_pwd, FLAGS_db, FLAGS_host, FLAGS_port, "", FLAGS_cset, 0, std::move(cpf));// 4.数据操作// Insert_Classes(db);// Insert_Student(db);// {//     Student stu = Select_Student(db);//     stu.age(22);//     Update_Student(db, stu);// }// Remove_Student(db);// Classes_Student(db);All_Student(db);return 0;
    }
    

http://www.hkcw.cn/article/mwCidSgBSj.shtml

相关文章

【Python】解决Python报错:ERROR: Could not find a version that satisfies the requirement

成功解决Python报错&#xff1a;ERROR: Could not find a version that satisfies the requirement。ERROR: Could not find a version that satisfies the requirement 是 Python 的包管理工具 pip 在安装包时可能遇到的错误。这通常意味着 pip 没有找到与给定版本要求匹配的包…

C语言 —— 此去经年梦浪荡魂音 - 深入理解指针(卷五)

目录 1. sizeof 和 strlen的区别 1.1 sizeof 1.2 strlen 2. 数组和指针习题解析 2.1 一维数组 2.2 字符数组 代码1&#xff1a; 代码2&#xff1a; 代码3: 代码4&#xff1a; 代码5&#xff1a; 代码6&#xff1a; 2.3 二维数组 3. 指针运算笔试题解析 3.1 3.…

【Python篇】PyQt5 超详细教程——由入门到精通(中篇一)

文章目录 PyQt5入门级超详细教程前言第4部分&#xff1a;事件处理与信号槽机制4.1 什么是信号与槽&#xff1f;4.2 信号与槽的基本用法4.3 信号与槽的基础示例代码详解&#xff1a; 4.4 处理不同的信号代码详解&#xff1a; 4.5 自定义信号与槽代码详解&#xff1a; 4.6 信号槽…

MathType的安装与word嵌入

博主近期在写论文&#xff0c;发现word编辑公式好像只能用MathType&#xff0c;于是就去下载安装&#xff0c;然后遇到了蛮多问题总结一下&#xff0c;希望能帮到有相同问题的大家~ 一.MathType的下载 博主是在官网直接下载的&#xff0c;个人觉得没啥问题&#xff0c;下的也…

matlab:二维绘图篇——plot绘图命令

目录 1.plot绘图命令 &#xff08;1)plot(x) 实例——实验数据曲线 实例——窗口分割 实例——随机矩阵 (2).plot(x,y) 实例——摩擦系数变化曲线 &#xff08;3&#xff09;plot(x1,y1,x2,y2,...) 实例——正弦图形 实例——正弦余弦图形 &#xff08;4&#xff09…

Python的包管理工具pip安装

Python的包管理工具pip安装 一、安装步骤1.检查 pip是否已安装2.安装 pip方法一&#xff1a;通过 ​ensurepip​ 模块安装(推荐)方法二&#xff1a;通过 ​get-pip.py​ 脚本安装&#xff08;经常应为网络域名问题连接不上&#xff09; 3.验证pip安装4.创建别名5.更新pip 二、常…

【Python篇】PyQt5 超详细教程——由入门到精通(序篇)

文章目录 PyQt5 超详细入门级教程前言序篇&#xff1a;1-3部分&#xff1a;PyQt5基础与常用控件第1部分&#xff1a;初识 PyQt5 和安装1.1 什么是 PyQt5&#xff1f;1.2 在 PyCharm 中安装 PyQt51.3 在 PyCharm 中编写第一个 PyQt5 应用程序1.4 代码详细解释1.5 在 PyCharm 中运…

C++第四十五弹---深入理解包装器:提升代码复用性与安全性的利器

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】【C详解】 目录 1 包装器 1.1、function包装器 1.2、bind 1 包装器 1.1、function包装器 function包装器 也叫作适配器。C中的function本质是一个类模板&…

【Java 学习】详细讲解---包和导包、Scanner类、输入源

1. 包 1.1 什么是包&#xff1f; 举个例子&#xff0c;你和你的同学有不同的家庭&#xff0c;你们都有自己的爸爸妈妈&#xff0c;都有自己的家。在自己的家中你们可以按照自己爱好摆放东西&#xff0c;都互不干扰。但是&#xff0c;假如你们的家都在一起&#xff0c;你们就不…

LEfSe分析:R语言一句代码轻松实现

数据和代码获取&#xff1a;请查看主页个人信息&#xff01;&#xff01;&#xff01; 大家好&#xff0c;今天我将介绍如何使用R语言进行LEfSe&#xff08;Linear discriminant analysis Effect Size&#xff09;分析及可视化。LEfSe是一种基于线性判别分析的算法&#xff0c;…

马斯克遭白宫背刺 提名撤销引失望

刚走一天就遭白宫“背刺”,马斯克对此表示失望。2023年10月11日,美国国家航空航天局在休斯敦约翰逊航天中心首次向公众展示了从小行星贝努采集到的样本图片和视频。5月31日,美国白宫宣布撤销对富豪贾里德艾萨克曼出任下一任NASA局长的提名。据报道,艾萨克曼与企业家马斯克关…

双腿戴假肢男子4小时登顶泰山 毅力与自信的见证

5月31日上午,山东泰安泰山景区天气晴朗。一位双腿安装假肢的男士一手拄着拐杖一手抓住扶手向上攀登的场景被游客上传到社交媒体,引发网友热议。6月1日下午,当事人盛先生介绍,这是他第三次登泰山了,从中天门到南天门花费了约4个小时。盛先生说,今年端午假期前,他出差来到…

南京大学通报施工方偷窃学生物品 施工单位被罚违约金

5月29日,南京大学基本建设处发布了一份关于对南京诚善科技有限公司执行合同违约金的通报。通报指出,南京诚善科技有限公司员工于5月13日在学校宿舍楼内偷窃学生物品。根据施工合同相关规定并经处办公会研究确认,南京大学基本建设处决定对该公司执行2000元违约金,从工程款中…

为省30块钱 卡车司机在青海缺氧离世 爱心卡友千里送别

46岁的河南卡车司机常志荣在青藏线因高原缺氧离世。今天上午,多名爱心卡友跨越2400多公里,将他的骨灰及车辆从五道梁地区送回老家安阳林州。5月27日,常志荣在青藏线五道梁地区遭遇严重缺氧不幸去世。车友任先生透露,出发前同行曾建议他至少携带两罐氧气,但他为了节省30元费…

樊振东将改变德国联赛竞争格局 新援加盟引关注

北京时间6月1日,德甲萨尔布吕肯俱乐部宣布中国运动员樊振东加盟该俱乐部,将参与2025-2026赛季德国乒乓球甲级联赛和欧洲冠军联赛。这并不意味着国内赛场上看不到樊振东的身影。目前樊振东仍处在奥运后的调整期,计划通过全国比赛以及国内外俱乐部比赛逐步恢复运动状态。樊振东…

少写一点,发布快一点:2025年的前端极简主义

我们先直白点&#xff1a;你大概并不需要那些 Button.js、PrimaryButton.js、OutlinePrimaryButton.js 甚至 MaybeIfItsFridayButton.js。 在2025年&#xff0c;我们被过度抽象的组件库淹没了——原子设计、过度工程化的 UI 库。 现在&#xff0c;该是我们聊聊「反潮流」的前端…

聊一聊接口测试中耗时请求如何合理安排?

目录 一、异步处理与轮询机制 轮询检查机制 二、 并行化测试执行 三、模拟与桩技术&#xff08;Mock/Stub&#xff09; 四、动态超时与重试策略 五、测试架构设计优化 分层测试策略 并行化执行 网络优化 六、测试用例分层管理 金字塔策略 七、 缓存与数据复用 响应…

VMware没有虚拟网卡,VMnet1,VMnet8显示黄色三角警告

VMware安装后没有虚拟网卡&#xff0c;VMnet1&#xff0c;VMnet8显示黄色三角警告 VMware安装后没有虚拟网卡&#xff0c;VMnet1&#xff0c;VMnet8显示黄色三角警告 VMware安装后没有虚拟网卡&#xff0c;VMnet1&#xff0c;VMnet8显示黄色三角警告 问题描述&#xff1a; 主机…

情侣和一家三口在迪士尼打架 因拍照起冲突

5月31日,有网友发布视频称,在上海迪士尼有一对情侣和一家三口发生了冲突,此事引发了广泛关注。视频中可以看到,双方在现场扭打,周围的人纷纷上前劝阻。据权威人士透露,事件发生在5月31日,地点并不是排队区域,而是游客自由打卡拍照的地方。情侣和一家三口因拍照问题产生…

猎德村龙舟文化与其他地区区别是什么 翻船事件引关注

端午节对于很多人来说只是一个普通的假期,但对于广东人来说却意义非凡。因为在这一天,他们要举行紧张刺激的龙舟比赛。猎德村在以往的比赛中总是表现亮眼,但今年还没正式开始就闹出了大笑话。三条新龙舟中有两条翻了,隔壁村因此疯狂嘲笑他们。网友们得知龙舟翻船的原因竟与…