mcpField
M
matlab-map-database-objects

matlab-map-database-objects

github.com/matlab数据与数据库1.2k54 次安装1 天前更新
代码仓库

关于 matlab-map-database-objects

此 MATLAB 技能介绍 Database Toolbox 的 ORM 层,用于将 MATLAB 类映射到关系数据库表,并以对象读写和更新数据。适合需要对象身份、类型约束或业务逻辑的数据库工作流;要求 MATLAB R2023b 或更高版本。

主要功能

  1. 01将 Mappable 类映射到数据库表
  2. 02使用 ormread 读取对象
  3. 03使用 ormwrite 写入对象
  4. 04使用 ormupdate 更新记录
  5. 05通过 orm2sql 检查建表语句

适用场景

  1. 01将 MATLAB 类映射为关系表
  2. 02把数据库行读取为 MATLAB 对象
  3. 03修改对象后更新数据库记录
  4. 04从类定义核对 SQL 表结构

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/matlab/matlab-agentic-toolkit --skill matlab-map-database-objects

安装后在 Claude Code 中输入/matlab-map-database-objects确认已加载。

附带文件manifest.yaml

详细介绍

MATLAB 对象关系映射

使用 Database Toolbox 中的对象关系映射(ORM)层,将 MATLAB 类映射到关系数据库表。定义带有属性到列映射的 Mappable 类,并使用 ormread、ormwrite 和 ormupdate 对对象执行 CRUD 操作。自 R2023b 起可用。

何时使用此技能

  • 将 MATLAB 类映射到数据库表
  • 将数据库行读取为 MATLAB 对象
  • 将 MATLAB 对象写入数据库表
  • 根据修改后的对象更新数据库行
  • 根据类定义生成 SQL CREATE TABLE 语句
  • 面向对象的数据库工作流
  • 用户提及以下关键词:ORM、对象关系映射、Mappable、ormread、ormwrite、ormupdate、orm2sql、类映射、属性映射、对象数据库

何时不使用

  • 临时查询或数据探索——改用 sqlread/fetch 和 RowFilter
  • 数千行数据的批量导入/导出——批量操作中 ORM 比 sqlwrite/sqlread 慢
  • MongoDB、Cassandra 或 Neo4j——ORM 仅适用于关系数据库(JDBC、ODBC、原生 MySQL/PostgreSQL/SQLite)
  • R2023b 之前的 MATLAB 版本——不支持 ORM

关键规则

ORM 要求
  • 始终继承 database.orm.mixin.Mappable——这是使用 ORM 功能的必要条件。
  • 始终至少定义一个 PrimaryKey 属性——ORM 需要它来标识对象。
  • 始终使用类级属性 TableName 指定数据库表名。
  • 始终包含一个可处理 nargin == 0 的构造函数(允许 ORM 预分配)。
  • ORM 要求使用 R2023b 或更高版本。
支持的连接
  • ORM 支持:JDBC、ODBC、PostgreSQL 原生连接、MySQL 原生连接、SQLite 原生连接、DuckDB 原生连接。
  • ORM 不支持:MongoDB(mongoc)、Cassandra(apacheCassandra)或 Neo4j。

决策框架

场景使用 ORM使用 sqlread/sqlwrite
需要对象标识和业务逻辑是否
需要基于类的类型安全是否
读写时需要进行领域验证是否
临时查询或探索否是
批量操作(数千行)否是(更快)
不需要对象映射否是

核心概念

定义 Mappable 类

Mappable 类将 MATLAB 属性映射到数据库列:

classdef (TableName = "employees") Employee < database.orm.mixin.Mappable

    properties (PrimaryKey, ColumnName = "EmployeeID")
        ID int32
    end

    properties
        Name string
        Department string
        Salary double
    end

    properties (ColumnName = "HireDate", ColumnType = "date")
        StartDate datetime
    end

    methods
        function obj = Employee(id, name, dept, salary, startDate)
            if nargin ~= 0
                obj.ID = id;
                obj.Name = name;
                obj.Department = dept;
                obj.Salary = salary;
                obj.StartDate = startDate;
            end
        end

        function obj = promote(obj, raise)
            obj.Salary = obj.Salary + raise;
        end
    end
end
属性特性参考
特性用途示例
PrimaryKey将属性标记为主键(必需)properties (PrimaryKey)
ColumnName将属性映射到名称不同的列properties (ColumnName = "EmpID")
ColumnType指定数据库列类型properties (ColumnType = "date")
TableName用于指定目标表名的类级属性classdef (TableName = "employees")
常见错误
% INCORRECT — class without PrimaryKey (ormwrite will error)
classdef (TableName = "employees") Employee < database.orm.mixin.Mappable
    properties
        Name string
        Dept string
    end
end
% ormwrite(conn, emp) → Error: No PrimaryKey defined

% CORRECT — PrimaryKey is required for ORM operations
classdef (TableName = "employees") Employee < database.orm.mixin.Mappable
    properties(PrimaryKey)
        EmployeeID int32
    end
    properties
        Name string
        Dept string
    end
end

% INCORRECT — class not inheriting Mappable
classdef Employee
    properties(PrimaryKey)
        EmployeeID int32
    end
end
% ormread(conn, "Employee") → Error! Not a Mappable class.

% CORRECT — must inherit from database.orm.mixin.Mappable
classdef Employee < database.orm.mixin.Mappable
    properties(PrimaryKey)
        EmployeeID int32
    end
end

% INCORRECT — constructor without nargin==0 guard
classdef (TableName = "emp") Employee < database.orm.mixin.Mappable
    methods
        function obj = Employee(id, name)
            obj.EmployeeID = id;
            obj.Name = name;
        end
    end
end
% ormread will fail because ORM needs to construct empty objects

% CORRECT — nargin==0 guard allows ORM to construct empty objects
classdef (TableName = "emp") Employee < database.orm.mixin.Mappable
    methods
        function obj = Employee(id, name)
            if nargin == 0
                return;
            end
            obj.EmployeeID = id;
            obj.Name = name;
        end
    end
end
使用 ormwrite 写入对象
% Create and insert a single object
emp = Employee(1, "Alice", "Engineering", 95000, datetime(2023,3,15));
ormwrite(conn, emp);

% Create and insert an array of objects
emps = [Employee(2, "Bob", "Sales", 72000, datetime(2023,6,1)), ...
        Employee(3, "Carol", "Engineering", 105000, datetime(2022,1,10))];
ormwrite(conn, emps);
使用 ormread 读取对象
% Read all objects
allEmployees = ormread(conn, "Employee");

% Read with a row filter
rf = rowfilter("Salary");
highEarners = ormread(conn, "Employee", RowFilter=rf.Salary > 90000);

% Refresh an existing object from database
emp = ormread(conn, emp);
使用 ormupdate 更新对象
% Modify object in MATLAB
emp = promote(emp, 5000);

% Push changes to database
ormupdate(conn, emp);
删除记录

ORM 不提供 ormdelete 函数。使用 execute 执行删除:

execute(conn, "DELETE FROM employees WHERE EmployeeID = 42");
错误处理
try
    ormwrite(conn, employeeObj);
catch ME
    if contains(ME.message, "UNIQUE") || contains(ME.message, "primary key")
        warning("Duplicate primary key. Use ormupdate instead.");
        ormupdate(conn, employeeObj);
    else
        rethrow(ME);
    end
end
根据类定义生成 SQL
% View the CREATE TABLE SQL that corresponds to the class
sql = orm2sql(conn, "Employee");
disp(sql);
% Output: "CREATE TABLE employees (EmployeeID integer, Name text, ...)"

完整示例

示例 1:完整的 ORM 工作流——定义、写入、读取、更新

步骤 1:定义类(保存为 Product.m):

classdef (TableName = "products") Product < database.orm.mixin.Mappable

    properties (PrimaryKey, ColumnName = "ProductNumber")
        ID int32
    end

    properties
        Name string
        Description string
        Quantity int32
    end

    properties (ColumnName = "UnitCost")
        CostPerItem double
    end

    properties (ColumnType = "date")
        InventoryDate datetime
    end

    methods
        function obj = Product(id, name, desc, cost, qty, invDate)
            if nargin ~= 0
                obj.ID = id;
                obj.Name = name;
                obj.Description = desc;
                obj.CostPerItem = cost;
                obj.Quantity = qty;
                obj.InventoryDate = invDate;
            end
        end

        function obj = restock(obj, amount)
            obj.Quantity = obj.Quantity + amount;
            obj.InventoryDate = datetime("today");
        end
    end
end

步骤 2:使用 ORM 操作(保存为 ormWorkflow.m):

(使用上文定义的 Product 类。)

% Connect to SQLite (no driver needed)
conn = sqlite("inventory.db", "create");

% Create and insert products
p1 = Product(1, "Widget", "Small widget", 9.99, 100, datetime(2024,1,1));
p2 = Product(2, "Gadget", "Large gadget", 29.99, 50, datetime(2024,1,1));
ormwrite(conn, [p1, p2]);

% Read all products back as objects
allProducts = ormread(conn, "Product");
disp(allProducts(1));

% Filter: find products under $15
rf = rowfilter("CostPerItem");
cheapProducts = ormread(conn, "Product", RowFilter=rf.CostPerItem < 15);

% Update: restock a product
cheapProducts(1) = restock(cheapProducts(1), 200);
ormupdate(conn, cheapProducts(1));

% Verify
refreshed = ormread(conn, cheapProducts(1));
disp(refreshed.Quantity); % Should be 300

close(conn);

最佳实践

  • 始终将 Mappable 类定义在单独的 .m 文件中——每个文件一个类(MATLAB 要求)。
  • 始终包含一个能够处理 nargin == 0 的构造函数(支持预分配)。
  • 始终只将一个属性块标记为 PrimaryKey。
  • 当 MATLAB 属性名与数据库列名不同时,使用 ColumnName。
  • 对于需要显式映射的类型,使用 ColumnType(例如,datetime 类型使用 "date")。
  • 使用带有 RowFilter 的 ormread 仅导入所需对象——筛选条件会下推到数据库。
  • 写入前使用 orm2sql 验证类映射是否与预期的数据库架构匹配。
  • 在 MATLAB 中使用类方法修改对象,然后使用 ormupdate 推送更改。

常见模式

模式 1:定义-写入-读取-更新
% Define class → Product.m
p = Product(1, "Item", "Desc", 9.99, 10, datetime("today"));
ormwrite(conn, p);
p = ormread(conn, p);        % Refresh from DB
p = restock(p, 50);          % Modify in MATLAB
ormupdate(conn, p);          % Push to DB
模式 2:使用业务逻辑进行筛选读取
rf = rowfilter("Quantity");
lowStock = ormread(conn, "Product", RowFilter=rf.Quantity < 10);
for i = 1:numel(lowStock)
    lowStock(i) = restock(lowStock(i), 100);
    ormupdate(conn, lowStock(i));
end
模式 3:架构验证
sql = orm2sql(conn, "MyClass");
disp(sql); % Verify CREATE TABLE matches expectations

检查清单

完成前,请确认:

  • Mappable 类继承自 database.orm.mixin.Mappable
  • 类的 classdef 上具有 TableName 属性
  • 至少一个属性块具有 PrimaryKey 属性
  • 构造函数能够处理用于预分配的 nargin == 0
  • 类保存在单独的 .m 文件中
  • 已建立并验证连接(isopen(conn))
  • 连接类型受支持(JDBC、ODBC、MySQL/PostgreSQL/SQLite/DuckDB 原生连接)
  • 使用 R2023b 或更高版本(较早版本不支持 ORM)

故障排除

问题:ormwrite 失败并提示“class is not Mappable”

  • 解决方案:确保该类继承自 database.orm.mixin.Mappable。类定义必须包含 < database.orm.mixin.Mappable。

问题:ormread 返回空数组

  • 解决方案:使用 sqlfind(conn, tableName) 确认数据库中存在该表。确认类的 TableName 属性与实际表名一致。

问题:ormupdate 未更改数据库值

  • 解决方案:ormupdate 根据主键匹配行。确认对象的主键属性值存在于数据库中。使用 ormread 刷新并检查。

问题:属性到列的映射不正确

  • 解决方案:使用 orm2sql(conn, "ClassName") 检查生成的 SQL。确认 ColumnName 和 ColumnType 属性与数据库架构匹配。

问题:找不到 ORM 函数(“Undefined function”)

  • 解决方案:ORM 需要 R2023b 或更高版本。使用 ver('database') 检查版本。对于较早版本,请改用 sqlread/sqlwrite。

版权所有 2026 The MathWorks, Inc.


评论

支持 Markdown