C++ ODB框架詳解:現代C++對象關系映射解決方案

目錄

  • 框架簡介
  • 安裝與配置
  • 基礎概念
  • 實體映射
  • 數據庫操作
  • 查詢操作
  • 高級功能
  • 性能優化
  • 最佳實踐

框架簡介

ODB(Object-Relational Database)是一個專為C++設計的對象關系映射(ORM)框架,由CodeSynthesis公司開發。它提供了一種現代化的方式來處理C++應用程序中的數據庫操作,將復雜的SQL操作抽象為簡單的C++對象操作。

主要特性

  • 類型安全:編譯時類型檢查,避免運行時錯誤
  • 高性能:零開銷抽象,接近原生SQL性能
  • 多數據庫支持:MySQL、PostgreSQL、SQLite、Oracle、SQL Server
  • 自動代碼生成:基于C++類自動生成數據庫訪問代碼
  • 事務支持:完整的ACID事務處理
  • 查詢語言:類型安全的查詢DSL
  • 模式演化:數據庫模式版本管理

架構概述

┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   應用程序      │    │   ODB編譯器     │    │   數據庫        │
│                 │    │                 │    │                 │
│ C++對象模型     │?──?│ 代碼生成器      │?──?│ 關系模型        │
│                 │    │                 │    │                 │
│ 業務邏輯        │    │ SQL映射         │    │ 數據存儲        │
└─────────────────┘    └─────────────────┘    └─────────────────┘

安裝與配置

系統要求

  • C++11或更高版本編譯器
  • 支持的數據庫客戶端庫
  • CMake 3.5+(推薦)

安裝步驟

1. 下載ODB編譯器
# Ubuntu/Debian
sudo apt-get install odb libodb-dev# CentOS/RHEL
sudo yum install odb libodb-devel# 或從源碼編譯
wget https://www.codesynthesis.com/download/odb/2.4/odb-2.4.0.tar.gz
tar -xzf odb-2.4.0.tar.gz
cd odb-2.4.0
./configure --prefix=/usr/local
make && sudo make install
2. 安裝數據庫特定庫
# MySQL支持
sudo apt-get install libodb-mysql-dev# PostgreSQL支持  
sudo apt-get install libodb-pgsql-dev# SQLite支持
sudo apt-get install libodb-sqlite-dev
3. CMake配置
cmake_minimum_required(VERSION 3.5)
project(ODBExample)set(CMAKE_CXX_STANDARD 11)# 查找ODB庫
find_package(PkgConfig REQUIRED)
pkg_check_modules(ODB REQUIRED libodb)
pkg_check_modules(ODB_MYSQL REQUIRED libodb-mysql)# 設置包含目錄和鏈接庫
include_directories(${ODB_INCLUDE_DIRS} ${ODB_MYSQL_INCLUDE_DIRS})
link_directories(${ODB_LIBRARY_DIRS} ${ODB_MYSQL_LIBRARY_DIRS})# 添加可執行文件
add_executable(example main.cpp person.cxx person-odb.cxx)
target_link_libraries(example ${ODB_LIBRARIES} ${ODB_MYSQL_LIBRARIES})# ODB代碼生成規則
add_custom_command(OUTPUT person-odb.hxx person-odb.ixx person-odb.cxxCOMMAND odb --database mysql --generate-query --generate-schema person.hxxDEPENDS person.hxxCOMMENT "Generating ODB files"
)

基礎概念

持久化類

在ODB中,需要持久化到數據庫的C++類稱為持久化類。通過pragma指令標記:

#include <odb/core.hxx>
#include <string>#pragma db object
class Person {
private:friend class odb::access;#pragma db id autounsigned long id_;std::string first_name_;std::string last_name_;unsigned short age_;public:Person() = default;Person(const std::string& first, const std::string& last, unsigned short age): first_name_(first), last_name_(last), age_(age) {}// Gettersunsigned long id() const { return id_; }const std::string& first_name() const { return first_name_; }const std::string& last_name() const { return last_name_; }unsigned short age() const { return age_; }// Settersvoid first_name(const std::string& name) { first_name_ = name; }void last_name(const std::string& name) { last_name_ = name; }void age(unsigned short a) { age_ = a; }
};

數據庫連接

#include <odb/database.hxx>
#include <odb/mysql/database.hxx>
#include <memory>std::unique_ptr<odb::database> create_database() {return std::make_unique<odb::mysql::database>("user",           // 用戶名"password",       // 密碼"database_name",  // 數據庫名"localhost",      // 主機3306,            // 端口nullptr,         // socket"utf8"           // 字符集);
}

基本CRUD操作

#include "person.hxx"
#include "person-odb.hxx"
#include <odb/transaction.hxx>void basic_operations() {auto db = create_database();// 創建表結構{odb::transaction t(db->begin());db->execute("DROP TABLE IF EXISTS Person");db->execute(R"(CREATE TABLE Person (id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,first_name VARCHAR(255) NOT NULL,last_name VARCHAR(255) NOT NULL,age SMALLINT UNSIGNED NOT NULL))");t.commit();}// 插入數據{odb::transaction t(db->begin());Person john("John", "Doe", 30);Person jane("Jane", "Smith", 25);db->persist(john);db->persist(jane);t.commit();std::cout << "John ID: " << john.id() << std::endl;std::cout << "Jane ID: " << jane.id() << std::endl;}// 查詢數據{odb::transaction t(db->begin());std::unique_ptr<Person> p(db->load<Person>(1));std::cout << "Loaded: " << p->first_name() << " " << p->last_name() << std::endl;t.commit();}// 更新數據{odb::transaction t(db->begin());std::unique_ptr<Person> p(db->load<Person>(1));p->age(31);db->update(*p);t.commit();}// 刪除數據{odb::transaction t(db->begin());db->erase<Person>(2);t.commit();}
}#### 多對多關系```cpp
#pragma db object
class Student {
private:friend class odb::access;#pragma db id autounsigned long id_;std::string name_;#pragma db many_to_many("student_course")std::vector<odb::lazy_shared_ptr<Course>> courses_;public:// 構造函數和訪問器...
};#pragma db object
class Course {
private:friend class odb::access;#pragma db id autounsigned long id_;std::string title_;#pragma db many_to_many("student_course") inverse(courses_)std::vector<odb::lazy_weak_ptr<Student>> students_;public:// 構造函數和訪問器...
};

繼承映射

#pragma db object polymorphic
class Animal {
private:friend class odb::access;#pragma db id autounsigned long id_;std::string name_;public:virtual ~Animal() = default;// 構造函數和訪問器...
};#pragma db object
class Dog : public Animal {
private:friend class odb::access;std::string breed_;public:// 構造函數和訪問器...
};#pragma db object
class Cat : public Animal {
private:friend class odb::access;bool indoor_;public:// 構造函數和訪問器...
};

數據庫操作

事務管理

#include <odb/transaction.hxx>void transaction_example() {auto db = create_database();try {odb::transaction t(db->begin());// 批量操作for (int i = 0; i < 100; ++i) {Person p("User" + std::to_string(i), "Test", 20 + i % 50);db->persist(p);}t.commit();std::cout << "Transaction committed successfully" << std::endl;}catch (const odb::exception& e) {std::cerr << "Database error: " << e.what() << std::endl;// 事務會自動回滾}
}// 嵌套事務
void nested_transaction_example() {auto db = create_database();odb::transaction outer(db->begin());try {Person p1("Alice", "Johnson", 28);db->persist(p1);// 保存點odb::transaction inner(db->begin());try {Person p2("Bob", "Wilson", 35);db->persist(p2);inner.commit();}catch (...) {// inner事務回滾,但outer事務繼續}outer.commit();}catch (...) {// outer事務回滾}
}

批量操作

void batch_operations() {auto db = create_database();// 批量插入{odb::transaction t(db->begin());std::vector<Person> people;for (int i = 0; i < 1000; ++i) {people.emplace_back("User" + std::to_string(i), "Batch", 20 + i % 50);}for (auto& person : people) {db->persist(person);}t.commit();}// 批量更新{odb::transaction t(db->begin());db->execute("UPDATE Person SET age = age + 1 WHERE age < 30");t.commit();}// 批量刪除{odb::transaction t(db->begin());db->erase_query<Person>(odb::query<Person>::age > 65);t.commit();}
}

查詢操作

基礎查詢

#include "person-odb.hxx"void basic_queries() {auto db = create_database();odb::transaction t(db->begin());// 簡單查詢typedef odb::query<Person> query;typedef odb::result<Person> result;// 按年齡查詢result r(db->query<Person>(query::age >= 25 && query::age <= 35));for (const auto& person : r) {std::cout << person.first_name() << " " << person.last_name() << " (age: " << person.age() << ")" << std::endl;}// 按姓名查詢result r2(db->query<Person>(query::first_name == "John"));// 模糊查詢result r3(db->query<Person>(query::last_name.like("%son")));// 排序查詢result r4(db->query<Person>(query::age > 20 + "ORDER BY" + query::age));t.commit();
}

高級查詢

void advanced_queries() {auto db = create_database();odb::transaction t(db->begin());typedef odb::query<Person> query;typedef odb::result<Person> result;// 參數化查詢std::string name_pattern = "J%";int min_age = 25;result r(db->query<Person>(query::first_name.like(query::_ref(name_pattern)) &&query::age >= query::_val(min_age)));// 聚合查詢typedef odb::query<PersonStat> stat_query;typedef odb::result<PersonStat> stat_result;#pragma db view object(Person)struct PersonStat {#pragma db column("count(*)")std::size_t count;#pragma db column("avg(age)")double avg_age;#pragma db column("min(age)")unsigned short min_age;#pragma db column("max(age)")unsigned short max_age;};stat_result sr(db->query<PersonStat>());const PersonStat& stat = *sr.begin();std::cout << "Total persons: " << stat.count << std::endl;std::cout << "Average age: " << stat.avg_age << std::endl;// 連接查詢typedef odb::query<PersonAddress> pa_query;typedef odb::result<PersonAddress> pa_result;#pragma db view object(Person) object(Address)struct PersonAddress {#pragma db column(Person::first_name_)std::string first_name;#pragma db column(Person::last_name_)std::string last_name;#pragma db column(Address::city_)std::string city;};pa_result par(db->query<PersonAddress>(pa_query::Person::address == pa_query::Address::id &&pa_query::Address::city == "New York"));t.commit();
}

延遲加載

void lazy_loading_example() {auto db = create_database();// 保存數據{odb::transaction t(db->begin());auto dept = std::make_shared<Department>("Engineering");db->persist(*dept);Employee emp1("Alice", dept);Employee emp2("Bob", dept);db->persist(emp1);db->persist(emp2);t.commit();}// 延遲加載{odb::transaction t(db->begin());std::unique_ptr<Employee> emp(db->load<Employee>(1));// 此時department_還未加載std::cout << "Employee: " << emp->name() << std::endl;// 訪問時才加載if (emp->department().loaded()) {std::cout << "Department already loaded" << std::endl;} else {std::cout << "Loading department..." << std::endl;auto dept = emp->department().load();std::cout << "Department: " << dept->name() << std::endl;}t.commit();}
}

高級功能

視圖(Views)

// 簡單視圖
#pragma db view object(Person)
struct PersonView {#pragma db column(Person::first_name_ + " " + Person::last_name_)std::string full_name;#pragma db column(Person::age_)unsigned short age;
};// 復雜視圖
#pragma db view query("SELECT p.first_name, p.last_name, a.city " \"FROM Person p " \"LEFT JOIN Address a ON p.address_id = a.id " \"WHERE p.age > (?) AND a.city IS NOT NULL")
struct PersonCityView {std::string first_name;std::string last_name;std::string city;
};void view_example() {auto db = create_database();odb::transaction t(db->begin());// 使用簡單視圖typedef odb::result<PersonView> view_result;view_result vr(db->query<PersonView>());for (const auto& pv : vr) {std::cout << pv.full_name << " (age: " << pv.age << ")" << std::endl;}// 使用參數化視圖typedef odb::result<PersonCityView> city_result;city_result cr(db->query<PersonCityView>(25));for (const auto& pcv : cr) {std::cout << pcv.first_name << " " << pcv.last_name << " lives in " << pcv.city << std::endl;}t.commit();
}

回調函數

#pragma db object callback(db_callback)
class Person {
private:friend class odb::access;#pragma db id autounsigned long id_;std::string first_name_;std::string last_name_;unsigned short age_;#pragma db transientmutable std::string cached_full_name_;public:// 構造函數和訪問器...// 回調函數void db_callback(odb::callback_event e, odb::database& db) const {switch (e) {case odb::callback_event::pre_persist:std::cout << "About to persist: " << first_name_ << std::endl;break;case odb::callback_event::post_persist:std::cout << "Persisted with ID: " << id_ << std::endl;break;case odb::callback_event::pre_load:cached_full_name_.clear();break;case odb::callback_event::post_load:cached_full_name_ = first_name_ + " " + last_name_;std::cout << "Loaded: " << cached_full_name_ << std::endl;break;case odb::callback_event::pre_update:std::cout << "About to update: " << first_name_ << std::endl;break;case odb::callback_event::post_update:std::cout << "Updated: " << first_name_ << std::endl;break;case odb::callback_event::pre_erase:std::cout << "About to erase: " << first_name_ << std::endl;break;}}
};

模式演化

// 版本1的Person類
#pragma db object table("person_v1")
class PersonV1 {
private:friend class odb::access;#pragma db id autounsigned long id_;std::string name_;unsigned short age_;
};// 版本2的Person類 - 添加了email字段
#pragma db object table("person_v2")
class PersonV2 {
private:friend class odb::access;#pragma db id autounsigned long id_;std::string first_name_;std::string last_name_;unsigned short age_;#pragma db nullstd::string email_;
};// 數據遷移
void migrate_schema() {auto db = create_database();odb::transaction t(db->begin());// 創建新表db->execute(R"(CREATE TABLE person_v2 (id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,first_name VARCHAR(255) NOT NULL,last_name VARCHAR(255) NOT NULL,age SMALLINT UNSIGNED NOT NULL,email VARCHAR(255)))");// 遷移數據db->execute(R"(INSERT INTO person_v2 (id, first_name, last_name, age)SELECT id, SUBSTRING_INDEX(name, ' ', 1) as first_name,SUBSTRING_INDEX(name, ' ', -1) as last_name,ageFROM person_v1)");// 刪除舊表db->execute("DROP TABLE person_v1");t.commit();
}

性能優化

連接池

#include <odb/connection-pool-factory.hxx>class DatabaseManager {
private:std::unique_ptr<odb::database> db_;public:DatabaseManager() {// 創建連接池工廠std::unique_ptr<odb::connection_pool_factory> pool_factory(new odb::connection_pool_factory(10, 0)  // 最大10個連接,無最小連接數);db_ = std::make_unique<odb::mysql::database>("user", "password", "database", "localhost", 3306,nullptr, "utf8", 0, std::move(pool_factory));}odb::database& get_database() { return *db_; }
};// 單例模式
DatabaseManager& get_db_manager() {static DatabaseManager manager;return manager;
}

預編譯語句

void prepared_statement_example() {auto db = create_database();// 預編譯查詢typedef odb::query<Person> query;typedef odb::prepared_query<Person> prepared_query;odb::transaction t(db->begin());// 準備查詢語句prepared_query pq(db->prepare_query<Person>("find_by_age", query::age >= query::_ref(age_param)));// 多次執行for (int age = 20; age <= 30; ++age) {int age_param = age;odb::result<Person> r(pq.execute());std::cout << "People aged " << age << ":" << std::endl;for (const auto& person : r) {std::cout << "  " << person.first_name() << " " << person.last_name() << std::endl;}}t.commit();
}

批量操作優化

void optimized_batch_operations() {auto db = create_database();// 使用事務批量插入const size_t batch_size = 1000;std::vector<Person> people;// 準備數據for (size_t i = 0; i < 10000; ++i) {people.emplace_back("User" + std::to_string(i), "Test", 20 + i % 50);}// 分批插入for (size_t i = 0; i < people.size(); i += batch_size) {odb::transaction t(db->begin());size_t end = std::min(i + batch_size, people.size());for (size_t j = i; j < end; ++j) {db->persist(people[j]);}t.commit();std::cout << "Inserted batch " << (i / batch_size + 1) << std::endl;}
}

查詢優化

void query_optimization() {auto db = create_database();odb::transaction t(db->begin());typedef odb::query<Person> query;typedef odb::result<Person> result;// 使用索引result r1(db->query<Person>(query::last_name == "Smith" + "ORDER BY" + query::first_name));// 限制結果集大小result r2(db->query<Person>(query::age > 25 + "LIMIT 100"));// 使用緩存result r3(db->query<Person>(query::age >= 30));std::vector<Person> cached_results(r3.begin(), r3.end());// 延遲加載優化typedef odb::query<Employee> emp_query;typedef odb::result<Employee> emp_result;emp_result er(db->query<Employee>(emp_query::department->name == "Engineering"));for (auto& emp : er) {// 批量加載關聯對象if (!emp.department().loaded()) {emp.department().load();}}t.commit();
}

最佳實踐

1. 項目結構

project/
├── src/
│   ├── models/           # 實體類
│   │   ├── person.hxx
│   │   ├── department.hxx
│   │   └── employee.hxx
│   ├── dao/             # 數據訪問對象
│   │   ├── person_dao.hxx
│   │   └── person_dao.cxx
│   ├── services/        # 業務邏輯
│   │   ├── person_service.hxx
│   │   └── person_service.cxx
│   └── main.cxx
├── generated/           # ODB生成的文件
│   ├── person-odb.hxx
│   ├── person-odb.ixx
│   └── person-odb.cxx
├── sql/                # SQL腳本
│   ├── schema.sql
│   └── migrations/
└── CMakeLists.txt

2. DAO模式實現

// person_dao.hxx
#pragma once
#include "models/person.hxx"
#include <odb/database.hxx>
#include <memory>
#include <vector>class PersonDAO {
private:std::shared_ptr<odb::database> db_;public:explicit PersonDAO(std::shared_ptr<odb::database> db) : db_(db) {}// CRUD操作void create(Person& person);std::unique_ptr<Person> find_by_id(unsigned long id);std::vector<Person> find_by_age_range(unsigned short min_age, unsigned short max_age);void update(const Person& person);void remove(unsigned long id);// 統計操作size_t count_all();double average_age();
};// person_dao.cxx
#include "dao/person_dao.hxx"
#include "generated/person-odb.hxx"
#include <odb/transaction.hxx>void PersonDAO::create(Person& person) {odb::transaction t(db_->begin());db_->persist(person);t.commit();
}std::unique_ptr<Person> PersonDAO::find_by_id(unsigned long id) {odb::transaction t(db_->begin());auto result = db_->load<Person>(id);t.commit();return result;
}std::vector<Person> PersonDAO::find_by_age_range(unsigned short min_age, unsigned short max_age) {odb::transaction t(db_->begin());typedef odb::query<Person> query;typedef odb::result<Person> result;result r(db_->query<Person>(query::age >= min_age && query::age <= max_age));std::vector<Person> people(r.begin(), r.end());t.commit();return people;
}void PersonDAO::update(const Person& person) {odb::transaction t(db_->begin());db_->update(person);t.commit();
}void PersonDAO::remove(unsigned long id) {odb::transaction t(db_->begin());db_->erase<Person>(id);t.commit();
}

3. 服務層實現

// person_service.hxx
#pragma once
#include "dao/person_dao.hxx"
#include <string>class PersonService {
private:std::unique_ptr<PersonDAO> dao_;public:explicit PersonService(std::shared_ptr<odb::database> db): dao_(std::make_unique<PersonDAO>(db)) {}// 業務方法unsigned long register_person(const std::string& first_name, const std::string& last_name, unsigned short age);bool update_person_age(unsigned long id, unsigned short new_age);std::vector<Person> get_adults();bool delete_person(unsigned long id);// 統計方法size_t get_total_count();double get_average_age();
};// person_service.cxx
#include "services/person_service.hxx"unsigned long PersonService::register_person(const std::string& first_name,const std::string& last_name,unsigned short age) {if (first_name.empty() || last_name.empty()) {throw std::invalid_argument("Name cannot be empty");}if (age > 150) {throw std::invalid_argument("Invalid age");}Person person(first_name, last_name, age);dao_->create(person);return person.id();
}bool PersonService::update_person_age(unsigned long id, unsigned short new_age) {try {auto person = dao_->find_by_id(id);if (!person) {return false;}person->age(new_age);dao_->update(*person);return true;}catch (const odb::exception&) {return false;}
}std::vector<Person> PersonService::get_adults() {return dao_->find_by_age_range(18, 150);
}

4. 錯誤處理

#include <odb/exception.hxx>void error_handling_example() {try {auto db = create_database();odb::transaction t(db->begin());// 數據庫操作Person person("John", "Doe", 30);db->persist(person);t.commit();}catch (const odb::database_exception& e) {std::cerr << "Database error: " << e.what() << std::endl;std::cerr << "Database message: " << e.message() << std::endl;}catch (const odb::connection_lost& e) {std::cerr << "Connection lost: " << e.what() << std::endl;// 實現重連邏輯}catch (const odb::timeout& e) {std::cerr << "Operation timeout: " << e.what() << std::endl;}catch (const odb::object_not_persistent& e) {std::cerr << "Object not persistent: " << e.what() << std::endl;}catch (const odb::object_already_persistent& e) {std::cerr << "Object already persistent: " << e.what() << std::endl;}catch (const odb::exception& e) {std::cerr << "ODB error: " << e.what() << std::endl;}catch (const std::exception& e) {std::cerr << "Standard error: " << e.what() << std::endl;}
}

5. 配置管理

// config.hxx
#pragma once
#include <string>struct DatabaseConfig {std::string host = "localhost";unsigned int port = 3306;std::string database = "test";std::string user = "root";std::string password = "";std::string charset = "utf8";unsigned int pool_size = 10;unsigned int timeout = 30;
};class ConfigManager {
private:DatabaseConfig db_config_;public:void load_from_file(const std::string& filename);void load_from_env();const DatabaseConfig& get_db_config() const { return db_config_; }
};// 使用配置
std::unique_ptr<odb::database> create_configured_database() {ConfigManager config;config.load_from_file("config.json");const auto& db_config = config.get_db_config();std::unique_ptr<odb::connection_pool_factory> pool_factory(new odb::connection_pool_factory(db_config.pool_size, 0));return std::make_unique<odb::mysql::database>(db_config.user,db_config.password,db_config.database,db_config.host,db_config.port,nullptr,db_config.charset,0,std::move(pool_factory));
}

總結

ODB框架為C++開發者提供了一個強大而靈活的ORM解決方案。它的主要優勢包括:

  1. 類型安全:編譯時檢查,減少運行時錯誤
  2. 高性能:接近原生SQL的性能表現
  3. 多數據庫支持:支持主流關系數據庫
  4. 現代C++特性:充分利用C++11/14/17特性
  5. 靈活的映射:支持復雜的對象關系映射

在實際項目中使用ODB時,建議:

  • 合理設計實體類和關系映射
  • 使用DAO模式組織數據訪問代碼
  • 實現適當的錯誤處理和事務管理
  • 利用連接池和預編譯語句優化性能
  • 遵循最佳實踐,保持代碼的可維護性

通過正確使用ODB框架,可以顯著提高C++應用程序的數據庫操作效率和代碼質量。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/82746.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/82746.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/82746.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Ai書簽管理工具開發全記錄(一):項目總覽與技術藍圖

文章目錄 Ai書簽管理工具開發全記錄&#xff08;一&#xff09;&#xff1a;項目總覽與技術藍圖 ?1. 項目背景與核心價值 &#x1f4a1;1.1. 核心特點 2. 技術架構分析 &#x1f3d7;?功能架構全景圖典型工作流 3. 核心技術棧選擇 &#x1f6e0;?4. 預期使用功能說明 &#…

GUI 編程——python

GUI 編程核心概念 GUI&#xff08;圖形用戶界面&#xff0c;Graphical User Interface&#xff09; 是一種通過圖形元素&#xff08;窗口、按鈕、菜單等&#xff09;與用戶交互的應用程序形式&#xff0c;相比命令行界面更直觀易用。以下是學習 GUI 編程的基礎概念和流程&…

【Doris基礎】Apache Doris 基本架構深度解析:從存儲到查詢的完整技術演進

目錄 1 引言 2 Doris 架構全景圖 2 核心組件技術解析 2.1 Frontend 層&#xff08;FE&#xff09; 2.2 Backend 層&#xff08;BE&#xff09; 3 數據存儲與復制機制 3.1 存儲架構演進 3.2 副本復制策略 4 查詢處理全流程解析 4.1 查詢生命周期 5 高可用設計 5.1 F…

光電賦能低空場景,靈途科技助力無人機持續升級

2025 UASE 主題為“步入低空經濟新時代”的“2025第九屆世界無人機大會暨國際低空經濟與無人系統博覽會/第十屆深圳國際無人機展覽會”5月23日在深圳會展中心隆重開幕。本屆展會匯聚了全球800余家企業參展&#xff0c;展示5000多款無人機及系統設備&#xff0c;全面呈現低空經…

iOS QQ抽屜式導航的實現

QQ個人中心的側滑功能(通常稱為"抽屜式導航")可以通過以下幾種方式在iOS中實現&#xff1a; 主要實現方案 使用第三方庫 最快速的方式是使用成熟的第三方庫&#xff1a; SWRevealViewController&#xff1a;最流行的側滑菜單庫MMDrawerController&#xff1a;另一…

【Pandas】pandas DataFrame drop

Pandas2.2 DataFrame Reindexing selection label manipulation 方法描述DataFrame.add_prefix(prefix[, axis])用于在 DataFrame 的行標簽或列標簽前添加指定前綴的方法DataFrame.add_suffix(suffix[, axis])用于在 DataFrame 的行標簽或列標簽后添加指定后綴的方法DataFram…

長短期記憶網絡 (LSTM) 詳解:從原理到應用

一、引言&#xff1a;序列數據處理的挑戰? 在自然語言處理、語音識別、時間序列分析等領域&#xff0c;數據通常以序列形式存在&#xff0c;前后數據點之間存在依賴關系。傳統循環神經網絡 (RNN) 雖然能捕捉序列依賴&#xff0c;但存在嚴重的梯度消失 / 爆炸問題&#xff0c;…

三天掌握PyTorch精髓:從感知機到ResNet的快速進階方法論

本文較長&#xff0c;建議點贊收藏&#xff0c;以免遺失。更多AI大模型應用開發學習視頻及資料&#xff0c;盡在聚客AI學院。 一、分析式AI基礎與深度學習核心概念 1.1 深度學習三要素 數學基礎&#xff1a; f(x;W,b)σ(Wxb)(單層感知機) 1.2 PyTorch核心組件 張量操作示例…

Linux操作系統概述

一、操作系統的作用 1、五大基本功能 &#xff08;1&#xff09;進程和線程的管理&#xff1a;進程線程的狀態、控制、同步互斥、通信調度等 (2&#xff09;存儲管理&#xff1a;分配/回收、地址轉換、存儲保護等 (3&#xff09;文件管理&#xff1a;文件目錄、文件操作、磁盤…

Python爬蟲第22節- 結合Selenium識別滑動驗證碼實戰

目錄 一、引言 二、滑動驗證碼原理與反爬機制 2.1 驗證碼原理 2.2 反爬機制 三、工程實戰&#xff1a;滑動驗證碼識別全流程 3.1 工程準備 3.1.1 環境依賴 3.1.2 目標網站與驗證碼識別案例 3.2 核心破解流程 3.2.1 自動化打開網頁與登錄 3.2.2 獲取驗證碼圖片&#…

NSSCTF-[NISACTF 2022]huaji?

下載附件得到文件 放到kali里面看看 發現是一張圖片 用binwalk命令對其進行分離 發現需要密碼 用010打開圖片進行查看 對其進行解密 分別得到 ctf_NISA_2022 nisa_2022 發現ctf_NISA_2022是密碼 得到flag NSSCTF{Nls_FumYEnnOjy}

nt!CcGetVacbMiss函數分析之設置好nt!_VACB然后調用函數nt!SetVacb

第一部分&#xff1a;MmMapViewInSystemCache函數返回 Status MmMapViewInSystemCache (SharedCacheMap->Section, &Vacb->BaseAddress, &NormalOffset, …

Uniapp+UView+Uni-star打包小程序極簡方案

一、減少主包體積 主包污染源&#xff08;全局文件依賴&#xff09;勁量獨立導入 componentsstaticmain.jsApp.vueuni.css 分包配置缺陷&#xff0c;未配置manifest.json中mp-weixin節點 "usingComponents" : true,"lazyCodeLoading" : "requiredC…

Teigha應用——解析CAD文件(DWG格式)Teigha在CAD C#二次開發中的基本應用

Teigha是一款專為開發者設計的工具&#xff0c;其核心技術在于強大的API和豐富的功能集&#xff0c;提供了一系列工具和方法&#xff0c;使開發者能夠輕松地讀取、解析和操作DWG文件。它支持多種操作系統&#xff0c;能在處理大型DWG文件時保持高效性能&#xff0c;還可用于構建…

JavaWeb:SpringBoot Bean管理

獲取Bean Bean作用域 解決循環依賴方式 1.粗暴刪除依賴 2.打破依賴配置 3.使用lazy注解 引入第三方Bean

Lua 腳本在 Redis 中的運用-23(Lua 腳本語法教程)

在 Redis 中編寫和執行 Lua 腳本 Lua 腳本是在 Redis 中執行自定義邏輯的強大功能&#xff0c;可以直接在 Redis 服務器上執行。這減少了延遲&#xff0c;提高了性能&#xff0c;并能夠實現客戶端腳本難以或不可能實現的原子操作。通過在 Redis 中嵌入 Lua 腳本&#xff0c;您…

從零實現本地語音識別(FunASR)

FunASR 是達摩院開源的綜合性語音處理工具包&#xff0c;提供語音識別&#xff08;ASR&#xff09;、語音活動檢測&#xff08;VAD&#xff09;、標點恢復&#xff08;PUNC&#xff09;等全流程功能&#xff0c;支持多種主流模型&#xff08;如 Paraformer、Whisper、SenseVoic…

deepseek開源資料匯總

參考&#xff1a;DeepSeek“開源周”收官&#xff0c;連續五天到底都發布了什么? 目錄 一、首日開源-FlashMLA 二、Day2 DeepEP 三、Day3 DeepGEMM 四、Day4 DualPipe & EPLB 五、Day5 3FS & Smallpond 總結 一、首日開源-FlashMLA 多頭部潛在注意力機制&#x…

【C++ Qt】認識Qt、Qt 項目搭建流程(圖文并茂、通俗易懂)

每日激勵&#xff1a;“不設限和自我肯定的心態&#xff1a;I can do all things。 — Stephen Curry” 緒論?&#xff1a; 本章將開啟Qt的學習&#xff0c;Qt是一個較為古老但仍然在GUI圖形化界面設計中有著舉足輕重的地位&#xff0c;因為它適合嵌入式和多種平臺而被廣泛使用…

AI應用 Markdown 渲染對比與原生實現方案

DeepSeek、豆包、騰訊元寶、ChatGPT 渲染實現對比表 產品解析方式渲染引擎/庫UI 組件架構Markdown支持范圍流程圖/導圖支持擴展架構及裁剪流式解析渲染DeepSeek原生解析&#xff08;非WebView&#xff09;采用 CommonMark 標準解析器&#xff08;推測使用 Markwon 庫&#xff…