
Spec
Database Design Specification
This document describes how to use definitions from the domain directory in .proto files to map domain models to tables, columns, and views in relational databases. It serves as a convention for both humans and large language models.
Main dependencies:
apihug/protobuf/domain/persistence.protoapihug/protobuf/domain/view.protoapihug/protobuf/domain/annotations.protoapihug/protobuf/extend/common.proto.proto file for description.syntax = "proto3";
package your.domain;
import "apihug/protobuf/domain/annotations.proto";
message Pet { ... }.(hope.persistence.table):
message Pet {
option (hope.persistence.table) = {
name: "PET"; // Table name, recommended uppercase with underscores
description: "宠物"; // Table description
// Optional: catalog, schema
// Optional: unique_constraints, indexes
// Optional: views, wires, liquibase
};
// Field definitions see next section
}
name should be consistent with the actual database table name; description uses natural language to briefly explain business meaning.(hope.persistence.column) metadata:
string name = 1 [(hope.persistence.column) = {
name: "NAME";
description: "宠物名称";
nullable: FALSE;
type: VARCHAR;
}];
id: Whether it is a primary key column, type is hope.common.BoolType.generated_value: Primary key generation strategy, including strategy (e.g., UUID, SEQUENCE, etc.) and generator name.unique: Whether it is a unique key.nullable: Whether NULL is allowed.insertable / updatable: Whether it participates in insert / update operations.searchable / sortable: Whether it is used for filtering / sorting.type: Use Column.Type to specify SQL type, such as VARCHAR, INTEGER, DATE, etc.length (google.protobuf.Int32Value).precision and scale to control precision.enum_type: STRING or CODE, representing which enum representation to persist.table: When the field is in an auxiliary table, specify the table name.column_definition: Custom SQL fragment, only use when necessary.transient: Mark the field as non-persistent, only used for views or calculations.Unless specified by user, do not add views!!
Table.views:
option (hope.persistence.table) = {
name: "PET";
description: "宠物";
views: [
{
name: "summary";
description: "列表视图";
includes: ["id", "name", "category"];
excludes: ["description"];
}
];
};
includes: Explicitly included field list, higher priority than excludes.excludes: Fields that need to be excluded from the default field set.AggregatedField:
aggregated_fields: [{
type: COUNT;
alias: "total";
}];
ReferenceView:
references: [{
entity: "Category"; // Target entity name
view: "summary"; // View name on target entity
join_type: INNER;
left_field: "category"; // Current entity field
right_field: "name"; // Target entity field
}];
wires represents whether to apply some built-in common domain features of the platform (e.g., auditing, soft delete, multi-tenancy, etc.). Usage example:
wires: [ALL];
wires: [AUDITABLE, DELETABLE];
wires: [NONE];
Specific available values are based on the Table.Wire enum.
(hope.persistence.table) on it.(hope.persistence.column) to each field that needs to be persisted, supplementing necessary constraint and type information.View/AggregatedField/ReferenceView instead of duplicating multiple entities.Liquibase entries for that table, rather than directly modifying existing version records.