diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9390189..02db804 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -115,10 +115,15 @@ jobs: cp .github/settings.xml ~/.m2/settings.xml - name: Build and push server image run: | + VERSION=$(cat VERSION | tr -d '[:space:]') + BUILD_VERSION="${VERSION}.${{ github.run_number }}" + FULL_VERSION="${BUILD_VERSION}-$(git rev-parse --short HEAD)" mvn -B -Dmaven.test.skip=true clean package -pl flexmodel-server -am \ + -Dflexmodel.version=${BUILD_VERSION} \ -Dquarkus.container-image.build=true \ -Dquarkus.container-image.push=true \ - -Dquarkus.container-image.image=cjbi/flexmodel-server:latest \ + -Dquarkus.container-image.image=cjbi/flexmodel-server:${BUILD_VERSION} \ + -Dquarkus.container-image.additional-tags=latest,${VERSION},${FULL_VERSION},sha-${{ github.sha }} \ -Dquarkus.container-image.username=${{ secrets.DOCKER_USERNAME }} \ -Dquarkus.container-image.password=${{ secrets.DOCKER_PASSWORD }} @@ -140,10 +145,15 @@ jobs: cache-dependency-path: '**/pom.xml' - name: Build and push server native image run: | + VERSION=$(cat VERSION | tr -d '[:space:]') + BUILD_VERSION="${VERSION}.${{ github.run_number }}" + FULL_VERSION="${BUILD_VERSION}-$(git rev-parse --short HEAD)" mvn -B -Dmaven.test.skip=true clean package -Pnative -pl flexmodel-server -am \ + -Dflexmodel.version=${BUILD_VERSION} \ -Dquarkus.container-image.build=true \ -Dquarkus.container-image.push=true \ - -Dquarkus.container-image.image=cjbi/flexmodel-server-native:latest \ + -Dquarkus.container-image.image=cjbi/flexmodel-server-native:${BUILD_VERSION} \ + -Dquarkus.container-image.additional-tags=latest,${VERSION},${FULL_VERSION},sha-${{ github.sha }} \ -Dquarkus.container-image.username=${{ secrets.DOCKER_USERNAME }} \ -Dquarkus.container-image.password=${{ secrets.DOCKER_PASSWORD }} @@ -153,6 +163,13 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v5 + - name: Read version + id: version + run: | + VERSION=$(cat VERSION | tr -d '[:space:]') + echo "tag=${VERSION}.${{ github.run_number }}" >> $GITHUB_OUTPUT + echo "ver=${VERSION}" >> $GITHUB_OUTPUT + echo "full=${VERSION}.${{ github.run_number }}-${{ github.sha }}" >> $GITHUB_OUTPUT - name: Set up Docker Buildx uses: docker/setup-buildx-action@v4 - name: Log in to Docker Hub @@ -165,23 +182,78 @@ jobs: with: context: flexmodel-functions-runtime push: true - tags: cjbi/flexmodel-functions-runtime:latest + tags: | + cjbi/flexmodel-functions-runtime:latest + cjbi/flexmodel-functions-runtime:${{ steps.version.outputs.ver }} + cjbi/flexmodel-functions-runtime:${{ steps.version.outputs.tag }} + cjbi/flexmodel-functions-runtime:${{ steps.version.outputs.full }} + cjbi/flexmodel-functions-runtime:sha-${{ github.sha }} + cache-from: type=gha + cache-to: type=gha,mode=max + + push-ui-image: + name: Push UI docker image + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + with: + submodules: 'recursive' + token: ${{ secrets.GITHUB_TOKEN }} + - name: Read version + id: version + run: | + VERSION=$(cat VERSION | tr -d '[:space:]') + echo "tag=${VERSION}.${{ github.run_number }}" >> $GITHUB_OUTPUT + echo "ver=${VERSION}" >> $GITHUB_OUTPUT + echo "full=${VERSION}.${{ github.run_number }}-${{ github.sha }}" >> $GITHUB_OUTPUT + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v4 + - name: Log in to Docker Hub + uses: docker/login-action@v4 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + - name: Build and push UI image + uses: docker/build-push-action@v7 + with: + context: flexmodel-ui + push: true + tags: | + cjbi/flexmodel-ui:latest + cjbi/flexmodel-ui:${{ steps.version.outputs.ver }} + cjbi/flexmodel-ui:${{ steps.version.outputs.tag }} + cjbi/flexmodel-ui:${{ steps.version.outputs.full }} + cjbi/flexmodel-ui:sha-${{ github.sha }} cache-from: type=gha cache-to: type=gha,mode=max # deploy: +# name: Deploy to production # runs-on: ubuntu-latest -# needs: [ push-server-image, push-ui-image, push-functions-runtime-image ] +# needs: [ push-server-image, push-functions-runtime-image, push-ui-image ] # steps: +# - uses: actions/checkout@v5 +# - name: Read version +# id: version +# run: echo "tag=$(cat VERSION | tr -d '[:space:]').${{ github.run_number }}" >> $GITHUB_OUTPUT # - name: Deploy Docker Image # uses: appleboy/ssh-action@master +# env: +# IMAGE_TAG: ${{ steps.version.outputs.tag }} # with: # host: ${{ secrets.HOST }} # username: ${{ secrets.SSH_USER }} # port: ${{ secrets.SSH_PORT }} # key: ${{ secrets.SSH_KEY }} +# envs: IMAGE_TAG # command_timeout: 10m # script: | # cd /opt/flexmodel-quickstarts/docker-compose -# docker-compose pull flexmodel-server flexmodel-ui flexmodel-functions-runtime +# docker pull cjbi/flexmodel-server:${IMAGE_TAG} +# docker pull cjbi/flexmodel-functions-runtime:${IMAGE_TAG} +# docker pull cjbi/flexmodel-ui:${IMAGE_TAG} +# docker tag cjbi/flexmodel-server:${IMAGE_TAG} cjbi/flexmodel-server:latest +# docker tag cjbi/flexmodel-functions-runtime:${IMAGE_TAG} cjbi/flexmodel-functions-runtime:latest +# docker tag cjbi/flexmodel-ui:${IMAGE_TAG} cjbi/flexmodel-ui:latest # docker-compose up -d +# echo "Deployed version ${IMAGE_TAG}" diff --git a/VERSION b/VERSION new file mode 100644 index 0000000..45c7a58 --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +v0.0.1 diff --git a/flexmodel-engine/README.md b/flexmodel-engine/README.md index 6d37aa5..66d157f 100644 --- a/flexmodel-engine/README.md +++ b/flexmodel-engine/README.md @@ -85,7 +85,7 @@ try (Session session = sessionFactory.createSession("mySchema")) { { "objects": [ { - "type": "entity", + "type": "Entity", "name": "User", "comment": "用户表", "fields": [ diff --git a/flexmodel-engine/docs/API.md b/flexmodel-engine/docs/API.md index 4cbe056..5d56bc8 100644 --- a/flexmodel-engine/docs/API.md +++ b/flexmodel-engine/docs/API.md @@ -339,31 +339,22 @@ EnumField statusField = new EnumField("status") .setDefaultValue("PENDING"); ``` -#### 关系字段 +#### 模型引用字段 ```java -// 一对一关系 -RelationField profileField = new RelationField("profile") - .setType(RelationField.Type.ONE_TO_ONE) - .setFrom("User") - .setTo("UserProfile") - .setForeignField("user_id"); - -// 一对多关系 -RelationField ordersField = new RelationField("orders") - .setType(RelationField.Type.ONE_TO_MANY) - .setFrom("User") - .setTo("Order") - .setForeignField("user_id"); - -// 多对多关系 -RelationField rolesField = new RelationField("roles") - .setType(RelationField.Type.MANY_TO_MANY) - .setFrom("User") - .setTo("Role") - .setJoinTable("user_roles") - .setJoinColumn("user_id") - .setInverseJoinColumn("role_id"); +// 单选引用(一对一) +ModelRefField profileField = new ModelRefField("profile") + .setFrom("UserProfile") + .setLocalField("profileId") + .setForeignField("id"); + +// 多选引用(一对多) +ModelRefField ordersField = new ModelRefField("orders") + .setMultiple(true) + .setFrom("Order") + .setLocalField("userId") + .setForeignField("id"); + ``` ### 异常处理 diff --git a/flexmodel-engine/docs/flexmodel-codegen.md b/flexmodel-engine/docs/flexmodel-codegen.md index 710596b..31bf099 100644 --- a/flexmodel-engine/docs/flexmodel-codegen.md +++ b/flexmodel-engine/docs/flexmodel-codegen.md @@ -27,7 +27,7 @@ class ListApiDefinitionGenerator extends ApiDefinitionGenerator { out.println "query MyListQuery( \$where: ${modelName}BoolExp) {" out.println " ${modelName}(where: \$where) {" context.getModelClass().getAllFields().each { - if (!it.isRelationField()) { + if (!it.isModelRefField()) { out.println " ${it.fieldName}" } } diff --git a/flexmodel-engine/docs/flexmodel-core.md b/flexmodel-engine/docs/flexmodel-core.md index 226a940..0d8c8b1 100644 --- a/flexmodel-engine/docs/flexmodel-core.md +++ b/flexmodel-engine/docs/flexmodel-core.md @@ -175,7 +175,9 @@ session.schema().createEntity("Student", entity -> entity .addField(new IntField("age")) .addField(new FloatField("score").setPrecision(5).setScale(2)) .addField(new EnumRefField("gender").setFrom("UserGender")) - .addField(new RelationField("studentClass") + . + +addField(new ModelRefField("studentClass") .setFrom("Classes") .setLocalField("classId") .setForeignField("id")) diff --git a/flexmodel-engine/flexmodel-codegen/src/main/java/dev/flexmodel/codegen/JavaType.java b/flexmodel-engine/flexmodel-codegen/src/main/java/dev/flexmodel/codegen/JavaType.java index 8ad9f36..730d279 100644 --- a/flexmodel-engine/flexmodel-codegen/src/main/java/dev/flexmodel/codegen/JavaType.java +++ b/flexmodel-engine/flexmodel-codegen/src/main/java/dev/flexmodel/codegen/JavaType.java @@ -9,7 +9,7 @@ */ public enum JavaType { - RELATION(ScalarType.RELATION_TYPE, null, null, null), + MODEL_REF(ScalarType.MODEL_REF_TYPE, null, null, null), STRING(STRING_TYPE, null, "String", "String"), FLOAT(FLOAT_TYPE, null, "Double", "Double"), INT(INT_TYPE, null, "Integer", "Integer"), diff --git a/flexmodel-engine/flexmodel-codegen/src/main/java/dev/flexmodel/codegen/ModelClass.java b/flexmodel-engine/flexmodel-codegen/src/main/java/dev/flexmodel/codegen/ModelClass.java index fe2cb45..7cc6343 100644 --- a/flexmodel-engine/flexmodel-codegen/src/main/java/dev/flexmodel/codegen/ModelClass.java +++ b/flexmodel-engine/flexmodel-codegen/src/main/java/dev/flexmodel/codegen/ModelClass.java @@ -4,7 +4,7 @@ import dev.flexmodel.model.EntityDefinition; import dev.flexmodel.model.ModelDefinition; import dev.flexmodel.model.field.EnumRefField; -import dev.flexmodel.model.field.RelationField; +import dev.flexmodel.model.field.ModelRefField; import dev.flexmodel.model.field.TypedField; import java.util.ArrayList; @@ -19,7 +19,7 @@ public class ModelClass extends AbstractClass { private ModelField idField; private final List basicFields = new ArrayList<>(); private final List enumFields = new ArrayList<>(); - private final List relationFields = new ArrayList<>(); + private final List modelRefFields = new ArrayList<>(); private final List allFields = new ArrayList<>(); private ModelDefinition original; @@ -56,7 +56,7 @@ public static ModelClass buildModelClass(String replaceString, String packageNam .setComment(field.getComment()); switch (field) { - case RelationField relationField -> { + case ModelRefField relationField -> { String ftName = StringUtils.capitalize( StringUtils.snakeToCamel( replaceString != null ? @@ -68,13 +68,13 @@ public static ModelClass buildModelClass(String replaceString, String packageNam modelField.setTypePackage("java.util") .setFullTypeName("java.util.List") .setShortTypeName("List<" + ftName + ">") - .setRelationField(true); + .setModelRefField(true); } else { modelField.setTypePackage(null) .setFullTypeName(modelField.getTypePackage() + "." + ftName) .setShortTypeName(ftName) - .setRelationField(true); - modelClass.getRelationFields().add(modelField); + .setModelRefField(true); + modelClass.getModelRefFields().add(modelField); } } @@ -150,8 +150,8 @@ public List getEnumFields() { return enumFields; } - public List getRelationFields() { - return relationFields; + public List getModelRefFields() { + return modelRefFields; } public List getAllFields() { diff --git a/flexmodel-engine/flexmodel-codegen/src/main/java/dev/flexmodel/codegen/ModelField.java b/flexmodel-engine/flexmodel-codegen/src/main/java/dev/flexmodel/codegen/ModelField.java index eb1ceb6..ea9f28f 100644 --- a/flexmodel-engine/flexmodel-codegen/src/main/java/dev/flexmodel/codegen/ModelField.java +++ b/flexmodel-engine/flexmodel-codegen/src/main/java/dev/flexmodel/codegen/ModelField.java @@ -18,7 +18,7 @@ public class ModelField { private String fullTypeName; private boolean identity; private boolean basicField; - private boolean relationField; + private boolean modelRefField; private boolean enumField; private Field original; @@ -103,8 +103,8 @@ public ModelField setBasicField(boolean basicField) { return this; } - public boolean isRelationField() { - return relationField; + public boolean isModelRefField() { + return modelRefField; } public boolean isEnumField() { @@ -116,8 +116,8 @@ public ModelField setEnumField(boolean enumField) { return this; } - public ModelField setRelationField(boolean relationField) { - this.relationField = relationField; + public ModelField setModelRefField(boolean relationField) { + this.modelRefField = relationField; return this; } diff --git a/flexmodel-engine/flexmodel-codegen/src/main/java/dev/flexmodel/codegen/PojoGenerator.java b/flexmodel-engine/flexmodel-codegen/src/main/java/dev/flexmodel/codegen/PojoGenerator.java index 44457e7..36f8290 100644 --- a/flexmodel-engine/flexmodel-codegen/src/main/java/dev/flexmodel/codegen/PojoGenerator.java +++ b/flexmodel-engine/flexmodel-codegen/src/main/java/dev/flexmodel/codegen/PojoGenerator.java @@ -56,9 +56,9 @@ public void writeModel(PrintWriter out, GenerationContext context) { out.println(" * " + field.getComment()); out.println(" */"); } - if (field.isRelationField()) { - out.println(" @ModelRelation"); - } + if (field.isModelRefField()) { + out.println(" @ModelRef"); + } out.println(" @ModelField(\"" + field.getOriginal().getName() + "\")"); out.println(" private " + field.getShortTypeName() + " " + field.getVariableName() + ";"); } diff --git a/flexmodel-engine/flexmodel-codegen/src/test/resources/import.json b/flexmodel-engine/flexmodel-codegen/src/test/resources/import.json index 87254f6..aec0a23 100644 --- a/flexmodel-engine/flexmodel-codegen/src/test/resources/import.json +++ b/flexmodel-engine/flexmodel-codegen/src/test/resources/import.json @@ -134,11 +134,11 @@ } ], "indexes": [], - "type": "entity" + "type": "Entity" }, { "name": "fs_datasource", - "type": "entity", + "type": "Entity", "fields": [ { "name": "name", @@ -198,7 +198,7 @@ }, { "name": "fs_api_log", - "type": "entity", + "type": "Entity", "fields": [ { "name": "id", @@ -258,7 +258,7 @@ ] }, { - "type": "entity", + "type": "Entity", "name": "Student", "fields": [ { @@ -315,7 +315,7 @@ }, { "name": "studentDetail", - "type": "Relation", + "type": "ModelRef", "modelName": "Student", "unique": false, "nullable": true, @@ -329,7 +329,7 @@ "indexes": [] }, { - "type": "entity", + "type": "Entity", "name": "StudentDetail", "fields": [ { @@ -363,7 +363,7 @@ }, { "name": "LogLevel", - "type": "enum", + "type": "Enum", "elements": [ "DEBUG", "INFO", @@ -374,7 +374,7 @@ }, { "name": "UserGender", - "type": "enum", + "type": "Enum", "elements": [ "UNKNOWN", "MALE", @@ -384,7 +384,7 @@ }, { "name": "User_interest", - "type": "enum", + "type": "Enum", "elements": [ "chang", "tiao", @@ -490,4 +490,4 @@ ] } ] -} +} \ No newline at end of file diff --git a/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/annotation/ModelRelation.java b/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/annotation/ModelRef.java similarity index 86% rename from flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/annotation/ModelRelation.java rename to flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/annotation/ModelRef.java index ac0669b..a77d105 100644 --- a/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/annotation/ModelRelation.java +++ b/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/annotation/ModelRef.java @@ -9,5 +9,5 @@ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE}) -public @interface ModelRelation { +public @interface ModelRef { } diff --git a/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/model/EntityDefinition.java b/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/model/EntityDefinition.java index 8ff587a..1577f15 100644 --- a/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/model/EntityDefinition.java +++ b/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/model/EntityDefinition.java @@ -1,6 +1,6 @@ package dev.flexmodel.model; -import dev.flexmodel.model.field.RelationField; +import dev.flexmodel.model.field.ModelRefField; import dev.flexmodel.model.field.TypedField; import java.util.*; @@ -21,7 +21,7 @@ public EntityDefinition(String name) { @Override public String getType() { - return "entity"; + return "Entity"; } public String getComment() { @@ -58,9 +58,9 @@ public IndexDefinition getIndex(String name) { .orElse(null); } - public Optional findRelationByModelName(String modelName) { + public Optional findRelationByModelName(String modelName) { for (TypedField field : fields) { - if (field instanceof RelationField relationField) { + if (field instanceof ModelRefField relationField) { if (relationField.getFrom().equals(modelName)) { return Optional.of(relationField); } diff --git a/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/model/EnumDefinition.java b/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/model/EnumDefinition.java index 5c7ded4..3410764 100644 --- a/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/model/EnumDefinition.java +++ b/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/model/EnumDefinition.java @@ -31,7 +31,7 @@ public String getName() { @Override public String getType() { - return "enum"; + return "Enum"; } public EnumDefinition setElements(List elements) { diff --git a/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/model/NativeQueryDefinition.java b/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/model/NativeQueryDefinition.java index d534be9..6fb0b40 100644 --- a/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/model/NativeQueryDefinition.java +++ b/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/model/NativeQueryDefinition.java @@ -32,7 +32,7 @@ public NativeQueryDefinition setStatement(String statement) { @Override public String getType() { - return "native_query"; + return "NativeQuery"; } /** diff --git a/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/model/field/EnumRefField.java b/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/model/field/EnumRefField.java index 05af3c1..7730d2f 100644 --- a/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/model/field/EnumRefField.java +++ b/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/model/field/EnumRefField.java @@ -18,7 +18,7 @@ public class EnumRefField extends TypedField { private String from; public EnumRefField(String name) { - super(name, ScalarType.ENUM.getType()); + super(name, ScalarType.ENUM_REF.getType()); } public boolean isMultiple() { diff --git a/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/model/field/RelationField.java b/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/model/field/ModelRefField.java similarity index 76% rename from flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/model/field/RelationField.java rename to flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/model/field/ModelRefField.java index a8f7e7f..4fac5ae 100644 --- a/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/model/field/RelationField.java +++ b/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/model/field/ModelRefField.java @@ -5,7 +5,7 @@ /** * @author cjbi */ -public class RelationField extends TypedField { +public class ModelRefField extends TypedField { /** * 多选 @@ -28,15 +28,15 @@ public class RelationField extends TypedField { */ private boolean cascadeDelete; - public RelationField(String name) { - super(name, ScalarType.RELATION.getType()); + public ModelRefField(String name) { + super(name, ScalarType.MODEL_REF.getType()); } public boolean isCascadeDelete() { return cascadeDelete; } - public RelationField setCascadeDelete(boolean cascadeDelete) { + public ModelRefField setCascadeDelete(boolean cascadeDelete) { this.cascadeDelete = cascadeDelete; return this; } @@ -45,7 +45,7 @@ public String getFrom() { return from; } - public RelationField setFrom(String from) { + public ModelRefField setFrom(String from) { this.from = from; return this; } @@ -54,7 +54,7 @@ public String getLocalField() { return localField; } - public RelationField setLocalField(String localField) { + public ModelRefField setLocalField(String localField) { this.localField = localField; return this; } @@ -63,7 +63,7 @@ public String getForeignField() { return foreignField; } - public RelationField setForeignField(String foreignField) { + public ModelRefField setForeignField(String foreignField) { this.foreignField = foreignField; return this; } @@ -72,14 +72,14 @@ public boolean isMultiple() { return multiple; } - public RelationField setMultiple(boolean multiple) { + public ModelRefField setMultiple(boolean multiple) { this.multiple = multiple; return this; } @Override public boolean equals(Object o) { - if (!(o instanceof RelationField that)) return false; + if (!(o instanceof ModelRefField that)) return false; if (!super.equals(o)) return false; return isMultiple() == that.isMultiple() && isCascadeDelete() == that.isCascadeDelete() && diff --git a/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/model/field/ScalarType.java b/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/model/field/ScalarType.java index 57e50be..b6084f3 100644 --- a/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/model/field/ScalarType.java +++ b/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/model/field/ScalarType.java @@ -13,8 +13,8 @@ public enum ScalarType { DATE(ScalarType.DATE_TYPE), TIME(ScalarType.TIME_TYPE), JSON(ScalarType.JSON_TYPE), - ENUM(ScalarType.ENUM_TYPE), - RELATION(ScalarType.RELATION_TYPE); + ENUM_REF(ScalarType.ENUM_REF_TYPE), + MODEL_REF(ScalarType.MODEL_REF_TYPE); private final String type; @@ -27,8 +27,8 @@ public enum ScalarType { public static final String DATE_TYPE = "Date"; public static final String TIME_TYPE = "Time"; public static final String JSON_TYPE = "JSON"; - public static final String ENUM_TYPE = "EnumRef"; - public static final String RELATION_TYPE = "Relation"; + public static final String ENUM_REF_TYPE = "EnumRef"; + public static final String MODEL_REF_TYPE = "ModelRef"; ScalarType(String type) { this.type = type; diff --git a/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/mongodb/MongoContext.java b/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/mongodb/MongoContext.java index a86abf0..28df1df 100644 --- a/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/mongodb/MongoContext.java +++ b/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/mongodb/MongoContext.java @@ -7,7 +7,6 @@ import dev.flexmodel.session.AbstractSessionContext; import dev.flexmodel.session.SessionFactory; import dev.flexmodel.type.*; -import dev.flexmodel.type.*; import java.util.HashMap; import java.util.Map; @@ -35,7 +34,7 @@ public MongoContext(String schemaName, MongoDatabase mongoDatabase, ModelRegistr this.typeHandlerMap.put(ScalarType.DATE.getType(), new DateTypeHandler()); this.typeHandlerMap.put(ScalarType.TIME.getType(), new TimeTypeHandler()); this.typeHandlerMap.put(ScalarType.JSON.getType(), new JsonTypeHandler()); - this.typeHandlerMap.put(ScalarType.ENUM.getType(), new EnumTypeHandler()); + this.typeHandlerMap.put(ScalarType.ENUM_REF.getType(), new EnumTypeHandler()); } public MongoDatabase getMongoDatabase() { diff --git a/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/mongodb/MongoStatementBuilder.java b/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/mongodb/MongoStatementBuilder.java index db10849..2dfd1b2 100644 --- a/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/mongodb/MongoStatementBuilder.java +++ b/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/mongodb/MongoStatementBuilder.java @@ -5,7 +5,7 @@ import dev.flexmodel.ExpressionCalculatorException; import dev.flexmodel.model.ModelDefinition; import dev.flexmodel.model.field.Field; -import dev.flexmodel.model.field.RelationField; +import dev.flexmodel.model.field.ModelRefField; import dev.flexmodel.query.Direction; import dev.flexmodel.query.Query; import dev.flexmodel.service.BaseService; @@ -82,7 +82,7 @@ private Document createLookupDocument(List pipeline, ModelDefinition m private void addProjectionStage(List pipeline, ModelDefinition model, Query query) { Document project = new Document("_id", false); - Map relationFields = findRelationFields(model, query); + Map relationFields = findRelationFields(model, query); boolean hasAggFunc = false; Query.Projection projection = query.getProjection(); diff --git a/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/parser/ASTNodeConverter.java b/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/parser/ASTNodeConverter.java index de42402..01d4a58 100644 --- a/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/parser/ASTNodeConverter.java +++ b/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/parser/ASTNodeConverter.java @@ -6,7 +6,6 @@ import dev.flexmodel.model.SchemaObject; import dev.flexmodel.model.field.*; import dev.flexmodel.ModelImportBundle; -import dev.flexmodel.model.field.*; import dev.flexmodel.parser.impl.ModelParser; import dev.flexmodel.parser.impl.ParseException; import dev.flexmodel.query.Direction; @@ -112,17 +111,17 @@ public static EntityDefinition toSchemaEntity(ModelParser.Model idlModel) { ModelParser.Annotation relationAnno = idlField.annotations.stream() .filter(f -> f.name.equals("relation")).findFirst() .orElse(null); - boolean isRelationField = relationAnno != null; + boolean isModelRefField = relationAnno != null; String from = idlField.type.replace("[]", ""); boolean multiple = idlField.type.endsWith("[]"); - if (isRelationField) { - RelationField relationField = new RelationField(idlField.name); - relationField.setMultiple(multiple); - relationField.setFrom(from); - relationField.setLocalField((String) relationAnno.parameters.get("localField")); - relationField.setForeignField((String) relationAnno.parameters.get("foreignField")); - relationField.setCascadeDelete(Boolean.parseBoolean(Objects.toString(relationAnno.parameters.get("cascadeDelete")))); - field = relationField; + if (isModelRefField) { + ModelRefField modelRefField = new ModelRefField(idlField.name); + modelRefField.setMultiple(multiple); + modelRefField.setFrom(from); + modelRefField.setLocalField((String) relationAnno.parameters.get("localField")); + modelRefField.setForeignField((String) relationAnno.parameters.get("foreignField")); + modelRefField.setCascadeDelete(Boolean.parseBoolean(Objects.toString(relationAnno.parameters.get("cascadeDelete")))); + field = modelRefField; } else { field = new EnumRefField(idlField.name); ((EnumRefField) field).setFrom(from); @@ -273,7 +272,7 @@ public static ModelParser.Field fromSchemaField(TypedField field) { case DateField dateField -> addDefaultAnnotation(idlField, dateField.getDefaultValue()); case TimeField timeField -> addDefaultAnnotation(idlField, timeField.getDefaultValue()); case JSONField jsonField -> addDefaultAnnotation(idlField, jsonField.getDefaultValue()); - case RelationField relationField -> { + case ModelRefField relationField -> { ModelParser.Annotation relationAnno = new ModelParser.Annotation("relation"); relationAnno.parameters.put("localField", relationField.getLocalField()); relationAnno.parameters.put("foreignField", relationField.getForeignField()); @@ -319,7 +318,7 @@ public static ModelParser.Enumeration fromSchemaEnum(EnumDefinition schemaEnum) // 辅助方法 private static String getCorrespondingType(TypedField field) { - if (field instanceof RelationField relationField) { + if (field instanceof ModelRefField relationField) { return relationField.isMultiple() ? relationField.getFrom() + "[]" : relationField.getFrom(); } else if (field instanceof EnumRefField enumField) { return enumField.isMultiple() ? enumField.getFrom() + "[]" : enumField.getFrom(); diff --git a/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/reflect/LazyLoadInterceptor.java b/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/reflect/LazyLoadInterceptor.java index 8208fae..47faa6d 100644 --- a/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/reflect/LazyLoadInterceptor.java +++ b/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/reflect/LazyLoadInterceptor.java @@ -8,7 +8,7 @@ import org.slf4j.LoggerFactory; import dev.flexmodel.JsonUtils; import dev.flexmodel.model.EntityDefinition; -import dev.flexmodel.model.field.RelationField; +import dev.flexmodel.model.field.ModelRefField; import dev.flexmodel.model.field.TypedField; import dev.flexmodel.query.Expressions; import dev.flexmodel.session.AbstractSession; @@ -101,7 +101,7 @@ public Object intercept(@This Object proxy, @Origin Class clazz, @Origin Meth EntityDefinition entity = (EntityDefinition) session.schema().getModel(modelName); String fieldName = ReflectionUtils.getFieldNameFromGetter(method); TypedField field = entity.getField(fieldName); - if (field instanceof RelationField relationField) { + if (field instanceof ModelRefField relationField) { return handleRelationField(proxy, clazz, method, superCall, fieldName, relationField); } return superCall.call(); @@ -112,7 +112,7 @@ private Object handleRelationField(Object proxy, Method method, Callable superCall, String fieldName, - RelationField relationField) throws Exception { + ModelRefField relationField) throws Exception { Object id = resolveRelationIdentifier(relationField); if (id == null) { return superCall.call(); @@ -135,7 +135,7 @@ private Object handleRelationField(Object proxy, return loadedValue; } - private RelationLoadResult loadRelationValue(RelationField relationField, Method method, Object identifier) { + private RelationLoadResult loadRelationValue(ModelRefField relationField, Method method, Object identifier) { Object convertedIdentifier = castValueType(relationField.getFrom(), relationField.getForeignField(), identifier); if (relationField.isMultiple()) { Class elementType = resolveCollectionElementType(method); @@ -156,7 +156,7 @@ private RelationLoadResult loadRelationValue(RelationField relationField, Method return RelationLoadResult.loaded(proxyValue); } - private Object resolveRelationIdentifier(RelationField relationField) { + private Object resolveRelationIdentifier(ModelRefField relationField) { Object id = dataMap.get(relationField.getLocalField()); if (id == null) { id = dataMap.get(underscoreToCamelCase(relationField.getLocalField())); diff --git a/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/reflect/LazyObjProxy.java b/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/reflect/LazyObjProxy.java index 5935a1d..8880e84 100644 --- a/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/reflect/LazyObjProxy.java +++ b/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/reflect/LazyObjProxy.java @@ -8,7 +8,7 @@ import org.slf4j.LoggerFactory; import dev.flexmodel.JsonUtils; import dev.flexmodel.model.EntityDefinition; -import dev.flexmodel.model.field.RelationField; +import dev.flexmodel.model.field.ModelRefField; import dev.flexmodel.session.Session; import java.lang.reflect.Modifier; @@ -79,7 +79,7 @@ public static List createProxyList(List list, String modelName, Sessio private static String[] getLazyMethods(EntityDefinition entity) { List methodNames = new ArrayList<>(); entity.getFields().forEach(field -> { - if (field instanceof RelationField) { + if (field instanceof ModelRefField) { methodNames.add("get" + ReflectionUtils.toUpperCamelCase(field.getName())); } }); diff --git a/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/service/BaseService.java b/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/service/BaseService.java index 612b403..0f1f556 100644 --- a/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/service/BaseService.java +++ b/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/service/BaseService.java @@ -191,7 +191,7 @@ private void validateJoinConfiguration(Query.Join joinConfig, ModelDefinition ma */ private void autoFillRelationFields(Query.Join joinConfig, EntityDefinition entity) { try { - RelationField relationField = entity.findRelationByModelName(joinConfig.getFrom()) + ModelRefField relationField = entity.findRelationByModelName(joinConfig.getFrom()) .orElseThrow(() -> new SqlExecutionException("Relation field not found for model: " + joinConfig.getFrom())); String localFieldName = relationField.getLocalField() != null ? @@ -230,11 +230,11 @@ private void validateManualJoinFields(Query.Join joinConfig) { * @param query 查询对象 * @return 关联字段映射,key为字段别名,value为关联字段定义 */ - public Map findRelationFields(ModelDefinition model, Query query) { + public Map findRelationFields(ModelDefinition model, Query query) { log.debug("Finding relation fields for model: {}, hasProjection: {}, hasExpand: {}", model.getName(), hasProjectionFields(query), query != null && query.hasExpand()); - Map relationFieldMap = new HashMap<>(); + Map relationFieldMap = new HashMap<>(); if (!(model instanceof EntityDefinition entity)) { log.debug("Model is not EntityDefinition, returning empty relation field map"); @@ -261,15 +261,15 @@ public Map findRelationFields(ModelDefinition model, Quer * @param expand expand 字段列表 * @param relationFieldMap 关联字段映射 */ - private void findRelationFieldsFromExpand(EntityDefinition entity, List expand, Map relationFieldMap) { + private void findRelationFieldsFromExpand(EntityDefinition entity, List expand, Map relationFieldMap) { log.debug("Finding relation fields from expand list: {}", expand); for (String expandPath : expand) { // 取顶层字段名(classId.teacher -> classId) String topField = expandPath.contains(".") ? expandPath.split("\\.")[0] : expandPath; entity.getFields().stream() - .filter(f -> f.getName().equals(topField) && f instanceof RelationField) - .map(f -> (RelationField) f) + .filter(f -> f.getName().equals(topField) && f instanceof ModelRefField) + .map(f -> (ModelRefField) f) .findFirst() .ifPresent(relationField -> { relationFieldMap.put(topField, relationField); @@ -319,7 +319,7 @@ private boolean hasProjectionFields(Query query) { * @param query 查询对象 * @param relationFieldMap 关联字段映射 */ - private void findRelationFieldsFromProjection(EntityDefinition entity, Query query, Map relationFieldMap) { + private void findRelationFieldsFromProjection(EntityDefinition entity, Query query, Map relationFieldMap) { log.debug("Finding relation fields from projection, projection fields count: {}", query.getProjection().getFields().size()); @@ -331,8 +331,8 @@ private void findRelationFieldsFromProjection(EntityDefinition entity, Query que log.debug("Checking field: {} (alias: {})", queryField.getName(), fieldAlias); entity.getFields().stream() - .filter(field -> field.getName().equals(queryField.getName()) && field instanceof RelationField) - .map(field -> (RelationField) field) + .filter(field -> field.getName().equals(queryField.getName()) && field instanceof ModelRefField) + .map(field -> (ModelRefField) field) .findFirst() .ifPresent(relationField -> { relationFieldMap.put(fieldAlias, relationField); @@ -348,11 +348,11 @@ private void findRelationFieldsFromProjection(EntityDefinition entity, Query que * @param entity 实体定义 * @param relationFieldMap 关联字段映射 */ - private void findAllRelationFields(EntityDefinition entity, Map relationFieldMap) { + private void findAllRelationFields(EntityDefinition entity, Map relationFieldMap) { log.debug("Finding all relation fields for entity: {}", entity.getName()); for (Field field : entity.getFields()) { - if (field instanceof RelationField relationField) { + if (field instanceof ModelRefField relationField) { relationFieldMap.put(relationField.getName(), relationField); log.debug("Found relation field: {}", relationField.getName()); } @@ -369,7 +369,7 @@ private void findAllRelationFields(EntityDefinition entity, Map> findRelationDataList( BiFunction>> relationQueryFunction, - RelationField relationField, + ModelRefField relationField, Set foreignKeyValues) { log.debug("Finding relation data for field: {}, foreign key values count: {}", @@ -431,11 +431,11 @@ private void nestedQuery(List> parentDataList, log.debug("Processing nested query for model: {}, remaining depth: {}", model.getName(), remainingDepth.get()); - Map relationFieldMap = findRelationFields(model, query); + Map relationFieldMap = findRelationFields(model, query); relationFieldMap.entrySet().stream().forEach(entry -> { String relationFieldAlias = entry.getKey(); - RelationField relationField = entry.getValue(); + ModelRefField relationField = entry.getValue(); log.debug("Processing relation field: {} (alias: {})", relationField.getName(), relationFieldAlias); processRelationField(parentDataList, relationQueryFunction, model, query, @@ -460,7 +460,7 @@ private void processRelationField(List> parentDataList, Query query, AtomicInteger remainingDepth, String relationFieldAlias, - RelationField relationField) { + ModelRefField relationField) { // 收集所有外键值 Set foreignKeyValues = parentDataList.stream() .map(dataItem -> dataItem.get(relationField.getLocalField())) @@ -508,7 +508,7 @@ private void processRelationField(List> parentDataList, * @param relationModel 关联模型定义 */ private void fillRelationDataToParent(Map parentDataItem, - RelationField relationField, + ModelRefField relationField, String relationFieldAlias, Map>> relationDataGroup, BiFunction>> relationQueryFunction, @@ -590,7 +590,7 @@ private void processInputData(Map inputData, EntityDefinition en inputData.forEach((fieldName, fieldValue) -> { TypedField field = entity.getField(fieldName); - if (field != null && !(field instanceof RelationField)) { + if (field != null && !(field instanceof ModelRefField)) { Object convertedValue = convertParameter(field, fieldValue); processedData.put(field.getName(), convertedValue); log.debug("Converted field: {} = {} -> {}", fieldName, fieldValue, convertedValue); @@ -613,7 +613,7 @@ private void processDefaultAndGeneratedValues(List> entityField log.debug("Processing default and generated values for {} fields", entityFields.size()); for (TypedField field : entityFields) { - if (field instanceof RelationField) { + if (field instanceof ModelRefField) { continue; } @@ -726,7 +726,7 @@ protected void insertRelatedRecords(String modelName, Map relati try { EntityDefinition entity = (EntityDefinition) sessionContext.getModelDefinition(modelName); relationObject.forEach((fieldName, fieldValue) -> { - if (fieldValue != null && entity.getField(fieldName) instanceof RelationField relationField) { + if (fieldValue != null && entity.getField(fieldName) instanceof ModelRefField relationField) { processRelationFieldInsertion(entity, fieldName, fieldValue, relationObject.get(relationField.getLocalField())); } }); @@ -748,7 +748,7 @@ protected void insertRelatedRecords(String modelName, Map relati */ @SuppressWarnings({"rawtypes", "unchecked"}) private void processRelationFieldInsertion(EntityDefinition entity, String fieldName, Object fieldValue, Object parentId) { - if (!(entity.getField(fieldName) instanceof RelationField relationField)) { + if (!(entity.getField(fieldName) instanceof ModelRefField relationField)) { return; } log.debug("Processing relation field insertion: field={}, relationField={}, parentId={}", fieldName, relationField.getName(), parentId); diff --git a/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/sql/SqlContext.java b/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/sql/SqlContext.java index eb2a796..65c7931 100644 --- a/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/sql/SqlContext.java +++ b/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/sql/SqlContext.java @@ -6,7 +6,6 @@ import dev.flexmodel.session.SessionFactory; import dev.flexmodel.sql.dialect.SqlDialect; import dev.flexmodel.sql.type.*; -import dev.flexmodel.sql.type.*; import java.sql.Connection; import java.sql.DatabaseMetaData; @@ -60,7 +59,7 @@ public SqlContext(String schemaName, this.typeHandlerMap.put(ScalarType.TIME.getType(), new LegacyTimeSqlTypeHandler()); } this.typeHandlerMap.put(ScalarType.JSON.getType(), new JsonSqlTypeHandler()); - this.typeHandlerMap.put(ScalarType.ENUM.getType(), new EnumSqlTypeHandler()); + this.typeHandlerMap.put(ScalarType.ENUM_REF.getType(), new EnumSqlTypeHandler()); } @Override diff --git a/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/sql/SqlDataService.java b/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/sql/SqlDataService.java index 57a2726..7b9d550 100644 --- a/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/sql/SqlDataService.java +++ b/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/sql/SqlDataService.java @@ -6,7 +6,7 @@ import dev.flexmodel.model.ModelDefinition; import dev.flexmodel.model.NativeQueryDefinition; import dev.flexmodel.model.field.Field; -import dev.flexmodel.model.field.RelationField; +import dev.flexmodel.model.field.ModelRefField; import dev.flexmodel.model.field.TypedField; import dev.flexmodel.query.Query; import dev.flexmodel.service.BaseService; @@ -298,7 +298,7 @@ public Optional> findById(String modelName, Object id, List< EntityDefinition entity = (EntityDefinition) sessionContext.getModelDefinition(modelName); TypedField idField = entity.findIdField().orElseThrow(); String columnsString = entity.getFields().stream() - .filter(f -> !(f instanceof RelationField)) + .filter(f -> !(f instanceof ModelRefField)) .map(field -> sqlDialect.quoteIdentifier(field.getName())) .collect(Collectors.joining(", ")); diff --git a/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/sql/SqlSchemaService.java b/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/sql/SqlSchemaService.java index be04fa7..8be778c 100644 --- a/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/sql/SqlSchemaService.java +++ b/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/sql/SqlSchemaService.java @@ -6,8 +6,6 @@ import org.slf4j.LoggerFactory; import dev.flexmodel.JsonUtils; import dev.flexmodel.ModelRegistry; -import dev.flexmodel.model.*; -import dev.flexmodel.model.field.*; import dev.flexmodel.service.BaseService; import dev.flexmodel.service.SchemaService; @@ -120,7 +118,7 @@ private void dropTable(SqlTable sqlTable) { entity.addField(field); modelRegistry.register(sessionContext.getSchemaName(), entity); } - if (!(field instanceof RelationField)) { + if (!(field instanceof ModelRefField)) { createColumn(toSqlColumn(field)); } return field; @@ -136,7 +134,7 @@ private void dropTable(SqlTable sqlTable) { modelRegistry.register(sessionContext.getSchemaName(), entity); } try { - if (!(field instanceof RelationField)) { + if (!(field instanceof ModelRefField)) { modifyColumn(toSqlColumn(field)); } } catch (Exception e) { @@ -310,7 +308,7 @@ private SqlTable toSqlTable(EntityDefinition entity) { SqlPrimaryKey primaryKey = new SqlPrimaryKey(sqlTable); for (TypedField field : entity.getFields()) { field.setModelName(entity.getName()); - if (field instanceof RelationField) { + if (field instanceof ModelRefField) { continue; } if (sqlTable.getColumn(field.getName()) != null) { @@ -333,7 +331,7 @@ private SqlTable toSqlTable(EntityDefinition entity) { } private SqlColumn toSqlColumn(TypedField field) { - if (field instanceof RelationField relationField) { + if (field instanceof ModelRefField relationField) { SqlColumn associationColumn = new SqlColumn(); associationColumn.setName(relationField.getForeignField()); associationColumn.setTableName( diff --git a/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/sql/SqlStatementBuilder.java b/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/sql/SqlStatementBuilder.java index 975a11f..7e1629c 100644 --- a/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/sql/SqlStatementBuilder.java +++ b/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/sql/SqlStatementBuilder.java @@ -3,7 +3,7 @@ import dev.flexmodel.ExpressionCalculatorException; import dev.flexmodel.model.EntityDefinition; import dev.flexmodel.model.ModelDefinition; -import dev.flexmodel.model.field.RelationField; +import dev.flexmodel.model.field.ModelRefField; import dev.flexmodel.model.field.ScalarType; import dev.flexmodel.model.field.TypedField; import dev.flexmodel.query.Query; @@ -123,7 +123,7 @@ private void appendJoins(String modelName, Query query, ModelDefinition model, S } String localField = joiner.getLocalField(); String foreignField = joiner.getForeignField(); - RelationField relationField; + ModelRefField relationField; if (model instanceof EntityDefinition entity && (relationField = entity.findRelationByModelName(joiner.getFrom()).orElse(null)) != null) { foreignField = relationField.getForeignField(); joinCause.append(joinTableName).append(" \n on \n").append(toFullColumnQuoteString(modelName, localField)).append("=").append(toFullColumnQuoteString(joiner.getAs(), foreignField)); @@ -157,7 +157,7 @@ private void appendFromClause(String modelName, StringBuilder sqlBuilder) { private void appendProjection(String modelName, Query query, ModelDefinition model, Map projectionMap, StringBuilder sqlBuilder) { SqlDialect sqlDialect = sqlContext.getSqlDialect(); Query.Projection projection = query.getProjection(); - Map relationFields = findRelationFields(model, query); + Map relationFields = findRelationFields(model, query); StringJoiner columns = new StringJoiner(", "); if (projection != null && !projection.getFields().isEmpty()) { projection.getFields().forEach((key, value) -> { diff --git a/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/supports/jackson/FlexmodelCoreModule.java b/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/supports/jackson/FlexmodelCoreModule.java index 10e9a56..107bb08 100644 --- a/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/supports/jackson/FlexmodelCoreModule.java +++ b/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/supports/jackson/FlexmodelCoreModule.java @@ -6,8 +6,6 @@ import com.fasterxml.jackson.databind.module.SimpleModule; import dev.flexmodel.model.*; import dev.flexmodel.model.field.*; -import dev.flexmodel.model.*; -import dev.flexmodel.model.field.*; import java.io.IOException; import java.text.SimpleDateFormat; @@ -36,7 +34,7 @@ public FlexmodelCoreModule() { setMixInAnnotation(DateField.class, TypedFieldMixIn.class); setMixInAnnotation(TimeField.class, TypedFieldMixIn.class); setMixInAnnotation(JSONField.class, TypedFieldMixIn.class); - setMixInAnnotation(RelationField.class, TypedFieldMixIn.class); + setMixInAnnotation(ModelRefField.class, TypedFieldMixIn.class); setMixInAnnotation(EnumRefField.class, TypedFieldMixIn.class); // Index setMixInAnnotation(IndexDefinition.class, IndexMixIn.class); diff --git a/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/supports/jackson/LazyObjectSerializer.java b/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/supports/jackson/LazyObjectSerializer.java index 8013788..5d352d2 100644 --- a/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/supports/jackson/LazyObjectSerializer.java +++ b/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/supports/jackson/LazyObjectSerializer.java @@ -4,7 +4,7 @@ import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.ser.std.StdSerializer; import dev.flexmodel.model.EntityDefinition; -import dev.flexmodel.model.field.RelationField; +import dev.flexmodel.model.field.ModelRefField; import dev.flexmodel.reflect.ProxyInterface; import dev.flexmodel.reflect.ReflectionUtils; @@ -39,7 +39,7 @@ private Map invokeGetter(ProxyInterface value) { Field[] declaredFields = aClass.getDeclaredFields(); Map data = new HashMap<>(); for (Field field : declaredFields) { - if (entity.getField(field.getName()) instanceof RelationField) { + if (entity.getField(field.getName()) instanceof ModelRefField) { continue; } try { diff --git a/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/supports/jackson/ModelMixIn.java b/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/supports/jackson/ModelMixIn.java index 93e586b..dabe3d0 100644 --- a/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/supports/jackson/ModelMixIn.java +++ b/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/supports/jackson/ModelMixIn.java @@ -13,9 +13,9 @@ */ @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type") @JsonSubTypes({ - @JsonSubTypes.Type(value = EntityDefinition.class, name = "entity"), - @JsonSubTypes.Type(value = NativeQueryDefinition.class, name = "native_query"), - @JsonSubTypes.Type(value = EnumDefinition.class, name = "enum"), + @JsonSubTypes.Type(value = EntityDefinition.class, name = "Entity"), + @JsonSubTypes.Type(value = NativeQueryDefinition.class, name = "NativeQuery"), + @JsonSubTypes.Type(value = EnumDefinition.class, name = "Enum"), }) public class ModelMixIn { diff --git a/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/supports/jackson/TypedFieldMixIn.java b/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/supports/jackson/TypedFieldMixIn.java index 753dd57..1e91eaa 100644 --- a/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/supports/jackson/TypedFieldMixIn.java +++ b/flexmodel-engine/flexmodel-core/src/main/java/dev/flexmodel/supports/jackson/TypedFieldMixIn.java @@ -5,7 +5,6 @@ import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonTypeInfo; import dev.flexmodel.model.field.*; -import dev.flexmodel.model.field.*; /** * @author cjbi @@ -21,8 +20,8 @@ @JsonSubTypes.Type(value = TimeField.class, name = ScalarType.TIME_TYPE), @JsonSubTypes.Type(value = BooleanField.class, name = ScalarType.BOOLEAN_TYPE), @JsonSubTypes.Type(value = JSONField.class, name = ScalarType.JSON_TYPE), - @JsonSubTypes.Type(value = RelationField.class, name = ScalarType.RELATION_TYPE), - @JsonSubTypes.Type(value = EnumRefField.class, name = ScalarType.ENUM_TYPE), + @JsonSubTypes.Type(value = ModelRefField.class, name = ScalarType.MODEL_REF_TYPE), + @JsonSubTypes.Type(value = EnumRefField.class, name = ScalarType.ENUM_REF_TYPE), }) public abstract class TypedFieldMixIn { diff --git a/flexmodel-engine/flexmodel-core/src/test/resources/sample_input.json b/flexmodel-engine/flexmodel-core/src/test/resources/sample_input.json index d1f2232..b6905e8 100644 --- a/flexmodel-engine/flexmodel-core/src/test/resources/sample_input.json +++ b/flexmodel-engine/flexmodel-core/src/test/resources/sample_input.json @@ -1,7 +1,7 @@ [ { "name": "fs_datasource", - "type": "entity", + "type": "Entity", "fields": [ { "name": "name", @@ -66,7 +66,7 @@ }, { "name": "fs_api_definition", - "type": "entity", + "type": "Entity", "fields": [ { "name": "id", @@ -171,7 +171,7 @@ }, { "name": "fs_api_log", - "type": "entity", + "type": "Entity", "fields": [ { "name": "id", @@ -237,7 +237,7 @@ }, { "name": "fs_identity_provider", - "type": "entity", + "type": "Entity", "fields": [ { "name": "name", @@ -282,7 +282,7 @@ { "name": "fs_config", "comment": "配置", - "type": "entity", + "type": "Entity", "fields": [ { "name": "id", @@ -350,7 +350,7 @@ ] }, { - "type": "entity", + "type": "Entity", "name": "Teacher", "fields": [ { @@ -381,7 +381,7 @@ "indexes": [] }, { - "type": "entity", + "type": "Entity", "name": "Student", "fields": [ { @@ -433,7 +433,7 @@ "nullable": true }, { - "type": "Relation", + "type": "ModelRef", "name": "studentClass", "comment": "班级", "modelName": "Student", @@ -445,7 +445,7 @@ }, { "name": "studentDetail", - "type": "Relation", + "type": "ModelRef", "modelName": "Student", "unique": false, "nullable": true, @@ -482,7 +482,7 @@ ] }, { - "type": "entity", + "type": "Entity", "name": "StudentDetail", "fields": [ { @@ -505,7 +505,7 @@ "nullable": true }, { - "type": "Relation", + "type": "ModelRef", "name": "student", "comment": "学生", "modelName": "StudentDetail", @@ -527,7 +527,7 @@ "indexes": [] }, { - "type": "entity", + "type": "Entity", "name": "Classes", "fields": [ { @@ -555,7 +555,7 @@ "length": 255 }, { - "type": "Relation", + "type": "ModelRef", "name": "students", "modelName": "Classes", "unique": false, @@ -569,7 +569,7 @@ ] }, { - "type": "entity", + "type": "Entity", "name": "Course", "fields": [ { @@ -605,7 +605,7 @@ }, { "name": "ApiType", - "type": "enum", + "type": "Enum", "elements": [ "FOLDER", "API" @@ -614,7 +614,7 @@ }, { "name": "DatasourceType", - "type": "enum", + "type": "Enum", "elements": [ "SYSTEM", "USER" @@ -623,7 +623,7 @@ }, { "name": "UserGender", - "type": "enum", + "type": "Enum", "elements": [ "UNKNOWN", "MALE", @@ -633,7 +633,7 @@ }, { "name": "user_interest", - "type": "enum", + "type": "Enum", "elements": [ "chang", "tiao", @@ -644,7 +644,7 @@ }, { "name": "LogLevel", - "type": "enum", + "type": "Enum", "elements": [ "DEBUG", "INFO", @@ -656,6 +656,6 @@ { "name": "select_log_count", "statement": "select count(*) as total from fs_api_log", - "type": "native_query" + "type": "NativeQuery" } ] diff --git a/flexmodel-engine/flexmodel-graphql/src/main/java/dev/flexmodel/graphql/FlexmodelAbstractDataFetcher.java b/flexmodel-engine/flexmodel-graphql/src/main/java/dev/flexmodel/graphql/FlexmodelAbstractDataFetcher.java index fae1eeb..2e745fd 100644 --- a/flexmodel-engine/flexmodel-graphql/src/main/java/dev/flexmodel/graphql/FlexmodelAbstractDataFetcher.java +++ b/flexmodel-engine/flexmodel-graphql/src/main/java/dev/flexmodel/graphql/FlexmodelAbstractDataFetcher.java @@ -7,7 +7,7 @@ import graphql.schema.SelectedField; import dev.flexmodel.JsonUtils; import dev.flexmodel.model.EntityDefinition; -import dev.flexmodel.model.field.RelationField; +import dev.flexmodel.model.field.ModelRefField; import dev.flexmodel.model.field.TypedField; import dev.flexmodel.query.Direction; import dev.flexmodel.query.Query; @@ -51,12 +51,12 @@ public FlexmodelAbstractDataFetcher(String schemaName, String modelName, Session this.sessionFactory = sessionFactory; } - protected List> findRelationDataList(Session session, DataFetchingEnvironment env, String path, String modelName, RelationField relationField, Object id) { + protected List> findRelationDataList(Session session, DataFetchingEnvironment env, String path, String modelName, ModelRefField relationField, Object id) { EntityDefinition entity = (EntityDefinition) session.schema().getModel(relationField.getModelName()); EntityDefinition targetEntity = (EntityDefinition) session.schema().getModel(relationField.getFrom()); path = path == null ? relationField.getName() : path + "/" + relationField.getName(); List selectedFields = env.getSelectionSet().getFields(path + "/*"); - List relationFields = new ArrayList<>(); + List relationFields = new ArrayList<>(); List> list = session.dsl() .select(selector -> { @@ -67,7 +67,7 @@ protected List> findRelationDataList(Session session, DataFe if (flexModelField == null) { continue; } - if (flexModelField instanceof RelationField secondaryRelationField) { + if (flexModelField instanceof ModelRefField secondaryRelationField) { relationFields.add(secondaryRelationField); continue; } @@ -84,7 +84,7 @@ protected List> findRelationDataList(Session session, DataFe for (Map map : list) { Map resultData = new HashMap<>(map); result.add(resultData); - for (RelationField sencondaryRelationField : relationFields) { + for (ModelRefField sencondaryRelationField : relationFields) { Object secondaryId = map.get(entity.findIdField().map(TypedField::getName).orElseThrow()); List> associationDataList = findRelationDataList(session, env, path, sencondaryRelationField.getFrom(), sencondaryRelationField, secondaryId); resultData.put(sencondaryRelationField.getName(), sencondaryRelationField.isMultiple() ? diff --git a/flexmodel-engine/flexmodel-graphql/src/main/java/dev/flexmodel/graphql/FlexmodelByIdDataFetcher.java b/flexmodel-engine/flexmodel-graphql/src/main/java/dev/flexmodel/graphql/FlexmodelByIdDataFetcher.java index 40b83aa..2f23a6c 100644 --- a/flexmodel-engine/flexmodel-graphql/src/main/java/dev/flexmodel/graphql/FlexmodelByIdDataFetcher.java +++ b/flexmodel-engine/flexmodel-graphql/src/main/java/dev/flexmodel/graphql/FlexmodelByIdDataFetcher.java @@ -3,7 +3,7 @@ import graphql.schema.DataFetchingEnvironment; import graphql.schema.SelectedField; import dev.flexmodel.model.EntityDefinition; -import dev.flexmodel.model.field.RelationField; +import dev.flexmodel.model.field.ModelRefField; import dev.flexmodel.model.field.TypedField; import dev.flexmodel.session.Session; import dev.flexmodel.session.SessionFactory; @@ -13,8 +13,6 @@ import java.util.List; import java.util.Map; -import static dev.flexmodel.query.Expressions.field; - import dev.flexmodel.query.Expressions; import dev.flexmodel.query.Query; @@ -35,7 +33,7 @@ public Map get(DataFetchingEnvironment env) { EntityDefinition entity = (EntityDefinition) session.schema().getModel(modelName); TypedField idField = entity.findIdField().orElseThrow(); - List relationFields = new ArrayList<>(); + List relationFields = new ArrayList<>(); List> list = session.dsl() .select(projection -> { @@ -45,7 +43,7 @@ public Map get(DataFetchingEnvironment env) { if (flexModelField == null) { continue; } - if (flexModelField instanceof RelationField secondaryRelationField) { + if (flexModelField instanceof ModelRefField secondaryRelationField) { relationFields.add(secondaryRelationField); continue; } @@ -62,7 +60,7 @@ public Map get(DataFetchingEnvironment env) { return null; } Map resultData = new HashMap<>(list.stream().findFirst().orElseThrow()); - for (RelationField secondaryRelationField : relationFields) { + for (ModelRefField secondaryRelationField : relationFields) { Object secondaryId = resultData.get(idField.getName()); List> relationDataList = findRelationDataList(session, env, null, secondaryRelationField.getFrom(), secondaryRelationField, secondaryId); resultData.put(secondaryRelationField.getName(), secondaryRelationField.isMultiple() ? relationDataList : relationDataList.stream().findFirst().orElse(null)); diff --git a/flexmodel-engine/flexmodel-graphql/src/main/java/dev/flexmodel/graphql/FlexmodelListDataFetcher.java b/flexmodel-engine/flexmodel-graphql/src/main/java/dev/flexmodel/graphql/FlexmodelListDataFetcher.java index d464188..8f836c8 100644 --- a/flexmodel-engine/flexmodel-graphql/src/main/java/dev/flexmodel/graphql/FlexmodelListDataFetcher.java +++ b/flexmodel-engine/flexmodel-graphql/src/main/java/dev/flexmodel/graphql/FlexmodelListDataFetcher.java @@ -4,7 +4,7 @@ import graphql.schema.SelectedField; import dev.flexmodel.JsonUtils; import dev.flexmodel.model.EntityDefinition; -import dev.flexmodel.model.field.RelationField; +import dev.flexmodel.model.field.ModelRefField; import dev.flexmodel.model.field.TypedField; import dev.flexmodel.query.Direction; import dev.flexmodel.query.Query; @@ -41,7 +41,7 @@ public List> findRootData(DataFetchingEnvironment env) { List selectedFields = env.getSelectionSet().getImmediateFields(); try (Session session = sessionFactory.createSession(schemaName)) { EntityDefinition entity = (EntityDefinition) session.schema().getModel(modelName); - List relationFields = new ArrayList<>(); + List relationFields = new ArrayList<>(); String whereString = null; if (where != null) { @@ -70,7 +70,7 @@ public List> findRootData(DataFetchingEnvironment env) { if (flexModelField == null) { continue; } - if (flexModelField instanceof RelationField secondaryRelationField) { + if (flexModelField instanceof ModelRefField secondaryRelationField) { relationFields.add(secondaryRelationField); continue; } @@ -88,7 +88,7 @@ public List> findRootData(DataFetchingEnvironment env) { for (Map map : list) { Map resultData = new HashMap<>(map); result.add(resultData); - for (RelationField sencondaryRelationField : relationFields) { + for (ModelRefField sencondaryRelationField : relationFields) { Object secondaryId = map.get(entity.findIdField().map(TypedField::getName).orElseThrow()); List> relationDataList = findRelationDataList(session, env, null, sencondaryRelationField.getFrom(), sencondaryRelationField, secondaryId); resultData.put(sencondaryRelationField.getName(), diff --git a/flexmodel-engine/flexmodel-graphql/src/main/java/dev/flexmodel/graphql/GraphQLSchemaGenerator.java b/flexmodel-engine/flexmodel-graphql/src/main/java/dev/flexmodel/graphql/GraphQLSchemaGenerator.java index 300b634..99a0b9a 100644 --- a/flexmodel-engine/flexmodel-graphql/src/main/java/dev/flexmodel/graphql/GraphQLSchemaGenerator.java +++ b/flexmodel-engine/flexmodel-graphql/src/main/java/dev/flexmodel/graphql/GraphQLSchemaGenerator.java @@ -2,11 +2,10 @@ import dev.flexmodel.codegen.AbstractGenerator; import dev.flexmodel.codegen.GenerationContext; -import dev.flexmodel.codegen.ModelClass; import dev.flexmodel.codegen.ModelField; import dev.flexmodel.codegen.StringUtils; import dev.flexmodel.model.field.EnumRefField; -import dev.flexmodel.model.field.RelationField; +import dev.flexmodel.model.field.ModelRefField; import dev.flexmodel.model.field.ScalarType; import dev.flexmodel.model.field.TypedField; @@ -47,8 +46,8 @@ public class GraphQLSchemaGenerator extends AbstractGenerator { private final I18nUtil i18n = new I18nUtil(); private String toGraphQLType(ModelField itt, GenerationContext context) { - if (itt.isRelationField()) { - RelationField rf = (RelationField) itt.getOriginal(); + if (itt.isModelRefField()) { + ModelRefField rf = (ModelRefField) itt.getOriginal(); String typeName = StringUtils.capitalize(StringUtils.snakeToCamel(rf.getFrom())); if (rf.isMultiple()) { return "[" + typeName + "]"; @@ -203,7 +202,7 @@ public void write(PrintWriter out, GenerationContext context) { out.println(); out.println("type " + key + "AvgFields {"); for (var f : it.getAllFields()) { - if (!f.isRelationField()) { + if (!f.isModelRefField()) { out.println(" " + f.getName() + ": Float"); } } @@ -220,7 +219,7 @@ public void write(PrintWriter out, GenerationContext context) { out.println(" and: [" + key + "BoolExp!]"); out.println(" or: [" + key + "BoolExp!]"); for (var f : it.getAllFields()) { - if (!f.isRelationField() && !f.isEnumField()) { + if (!f.isModelRefField() && !f.isEnumField()) { TypedField tf = (TypedField) f.getOriginal(); out.println(" " + f.getName() + ": " + comparisonMapping.getOrDefault(tf.getType(), "StringComparisonExp")); } else if (f.isEnumField() && context.containsEnumClass(((EnumRefField) f.getOriginal()).getFrom())) { @@ -235,7 +234,7 @@ public void write(PrintWriter out, GenerationContext context) { out.println("\"" + i18n.getString("gql.order_by.comment", key) + "\""); out.println("input " + key + "OrderBy {"); for (var f : it.getAllFields()) { - if (!f.isRelationField()) { + if (!f.isModelRefField()) { out.println(" " + f.getName() + ": OrderBy"); } } @@ -243,7 +242,7 @@ public void write(PrintWriter out, GenerationContext context) { out.println(); out.println("input " + key + "InsertInput {"); for (var f : it.getAllFields()) { - if (!f.isRelationField()) { + if (!f.isModelRefField()) { out.println(" " + f.getName() + ": " + toGraphQLType(f, context)); } } @@ -251,7 +250,7 @@ public void write(PrintWriter out, GenerationContext context) { out.println(); out.println("input " + key + "SetInput {"); for (var f : it.getAllFields()) { - if (!f.isRelationField()) { + if (!f.isModelRefField()) { out.println(" " + f.getName() + ": " + toGraphQLType(f, context)); } } @@ -264,7 +263,7 @@ public void write(PrintWriter out, GenerationContext context) { out.println(); out.println("enum " + key + "SelectField {"); for (var f : it.getAllFields()) { - if (!f.isRelationField()) { + if (!f.isModelRefField()) { out.println(" " + f.getName()); } } diff --git a/flexmodel-engine/flexmodel-graphql/src/test/java/dev/flexmodel/graphql/Models.java b/flexmodel-engine/flexmodel-graphql/src/test/java/dev/flexmodel/graphql/Models.java index 5567d2b..29c3fbf 100644 --- a/flexmodel-engine/flexmodel-graphql/src/test/java/dev/flexmodel/graphql/Models.java +++ b/flexmodel-engine/flexmodel-graphql/src/test/java/dev/flexmodel/graphql/Models.java @@ -74,7 +74,7 @@ public static EntityDefinition createTeacherEntity(Session session, String entit public static void createAssociations(Session session, String classRoomEntityName, String studentEntityName, String studentDetailEntityName, String courseEntityName, String teacherEntityName) { // 班级:学生 - session.schema().createField(new RelationField("students") + session.schema().createField(new ModelRefField("students") .setModelName(classRoomEntityName) .setFrom(studentEntityName) .setForeignField("classId") @@ -82,7 +82,7 @@ public static void createAssociations(Session session, String classRoomEntityNam .setCascadeDelete(true) ); // 学生:学生明细 -> 1:1 - session.schema().createField(new RelationField("studentDetail") + session.schema().createField(new ModelRefField("studentDetail") .setModelName(studentEntityName) .setFrom(studentDetailEntityName) .setForeignField("studentId") diff --git a/flexmodel-engine/flexmodel-graphql/src/test/resources/import.json b/flexmodel-engine/flexmodel-graphql/src/test/resources/import.json index 850f0bf..a08f290 100644 --- a/flexmodel-engine/flexmodel-graphql/src/test/resources/import.json +++ b/flexmodel-engine/flexmodel-graphql/src/test/resources/import.json @@ -2,7 +2,7 @@ "objects": [ { "name": "Datasource", - "type": "entity", + "type": "Entity", "fields": [ { "name": "name", @@ -59,7 +59,7 @@ { "name": "ApiInfo", "comment": "接口信息", - "type": "entity", + "type": "Entity", "fields": [ { "name": "id", @@ -144,7 +144,7 @@ }, { "name": "ApiLog", - "type": "entity", + "type": "Entity", "fields": [ { "name": "id", @@ -204,7 +204,7 @@ }, { "name": "IdentityProvider", - "type": "entity", + "type": "Entity", "fields": [ { "name": "name", @@ -241,7 +241,7 @@ { "name": "Config", "comment": "配置", - "type": "entity", + "type": "Entity", "fields": [ { "name": "id", @@ -302,7 +302,7 @@ ] }, { - "type": "entity", + "type": "Entity", "name": "Teacher", "fields": [ { @@ -337,7 +337,7 @@ "indexes": [] }, { - "type": "entity", + "type": "Entity", "name": "Student", "fields": [ { @@ -394,7 +394,7 @@ }, { "name": "studentDetail", - "type": "Relation", + "type": "ModelRef", "modelName": "Student", "unique": false, "nullable": true, @@ -407,7 +407,7 @@ "indexes": [] }, { - "type": "entity", + "type": "Entity", "name": "StudentDetail", "fields": [ { @@ -440,7 +440,7 @@ "indexes": [] }, { - "type": "entity", + "type": "Entity", "name": "Classes", "fields": [ { @@ -468,7 +468,7 @@ "length": 255 }, { - "type": "Relation", + "type": "ModelRef", "name": "students", "modelName": "Classes", "unique": false, @@ -482,7 +482,7 @@ "indexes": [] }, { - "type": "entity", + "type": "Entity", "name": "Course", "fields": [ { @@ -502,7 +502,7 @@ }, { "name": "students", - "type": "Relation", + "type": "ModelRef", "modelName": "Course", "unique": false, "nullable": true, @@ -528,7 +528,7 @@ }, { "name": "UserGender", - "type": "enum", + "type": "Enum", "elements": [ "UNKNOWN", "MALE", @@ -538,7 +538,7 @@ }, { "name": "User_interest", - "type": "enum", + "type": "Enum", "elements": [ "Chang", "Tiao", @@ -788,4 +788,4 @@ ] } ] -} +} \ No newline at end of file diff --git a/flexmodel-engine/integration-tests/flexmodel-common-it/src/main/java/dev/flexmodel/AbstractSessionTests.java b/flexmodel-engine/integration-tests/flexmodel-common-it/src/main/java/dev/flexmodel/AbstractSessionTests.java index 8751e0c..637a792 100644 --- a/flexmodel-engine/integration-tests/flexmodel-common-it/src/main/java/dev/flexmodel/AbstractSessionTests.java +++ b/flexmodel-engine/integration-tests/flexmodel-common-it/src/main/java/dev/flexmodel/AbstractSessionTests.java @@ -203,7 +203,7 @@ void createAssociations(String classRoomEntityName, String studentEntityName, String studentDetailEntityName, String courseEntityName, String teacherEntityName) { // 班级:学生 session.schema().createField( - new RelationField("students") + new ModelRefField("students") .setModelName(classRoomEntityName) .setFrom(studentEntityName) .setLocalField("id") @@ -213,7 +213,7 @@ void createAssociations(String classRoomEntityName, String studentEntityName, ); // 学生:学生明细 -> 1:1 session.schema().createField( - new RelationField("studentDetail") + new ModelRefField("studentDetail") .setModelName(studentEntityName) .setFrom(studentDetailEntityName) .setLocalField("id") @@ -222,7 +222,7 @@ void createAssociations(String classRoomEntityName, String studentEntityName, ); // 明细:学生 -> 1:1 session.schema().createField( - new RelationField("student") + new ModelRefField("student") .setModelName(studentDetailEntityName) .setFrom(studentEntityName) .setLocalField("studentId") @@ -626,7 +626,7 @@ void createTeacherCourseEntity(String teacherEntityName, String teacherCourseEnt .setComment("教师成绩表") ); session.schema().createField( - new RelationField("courses") + new ModelRefField("courses") .setModelName(teacherEntityName) .setMultiple(true) .setCascadeDelete(true) diff --git a/flexmodel-engine/integration-tests/flexmodel-common-it/src/main/java/dev/flexmodel/entity/Classes.java b/flexmodel-engine/integration-tests/flexmodel-common-it/src/main/java/dev/flexmodel/entity/Classes.java index 89fd101..a5693e0 100644 --- a/flexmodel-engine/integration-tests/flexmodel-common-it/src/main/java/dev/flexmodel/entity/Classes.java +++ b/flexmodel-engine/integration-tests/flexmodel-common-it/src/main/java/dev/flexmodel/entity/Classes.java @@ -2,7 +2,7 @@ import dev.flexmodel.annotation.ModelClass; import dev.flexmodel.annotation.ModelField; -import dev.flexmodel.annotation.ModelRelation; +import dev.flexmodel.annotation.ModelRef; import java.util.List; @@ -12,7 +12,7 @@ @ModelClass("Classes") public class Classes { - @ModelRelation + @ModelRef @ModelField("students") private List students; diff --git a/flexmodel-engine/integration-tests/flexmodel-common-it/src/main/java/dev/flexmodel/entity/Student.java b/flexmodel-engine/integration-tests/flexmodel-common-it/src/main/java/dev/flexmodel/entity/Student.java index 79e0f31..0db226a 100644 --- a/flexmodel-engine/integration-tests/flexmodel-common-it/src/main/java/dev/flexmodel/entity/Student.java +++ b/flexmodel-engine/integration-tests/flexmodel-common-it/src/main/java/dev/flexmodel/entity/Student.java @@ -2,7 +2,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonRootName; -import dev.flexmodel.annotation.ModelRelation; +import dev.flexmodel.annotation.ModelRef; import dev.flexmodel.enumeration.UserGender; import dev.flexmodel.enumeration.UserInterest; @@ -14,7 +14,7 @@ @JsonRootName("Student") public class Student { - @ModelRelation + @ModelRef @JsonProperty("studentDetail") private StudentDetail studentDetail; diff --git a/flexmodel-engine/integration-tests/flexmodel-common-it/src/main/resources/import.json b/flexmodel-engine/integration-tests/flexmodel-common-it/src/main/resources/import.json index b13fa87..77e7ab6 100644 --- a/flexmodel-engine/integration-tests/flexmodel-common-it/src/main/resources/import.json +++ b/flexmodel-engine/integration-tests/flexmodel-common-it/src/main/resources/import.json @@ -2,7 +2,7 @@ "objects": [ { "name": "Datasource", - "type": "entity", + "type": "Entity", "fields": [ { "name": "name", @@ -46,7 +46,7 @@ }, { "name": "ApiInfo", - "type": "entity", + "type": "Entity", "fields": [ { "name": "id", @@ -142,7 +142,7 @@ }, { "name": "ApiLog", - "type": "entity", + "type": "Entity", "fields": [ { "name": "id", @@ -214,7 +214,7 @@ }, { "name": "IdentityProvider", - "type": "entity", + "type": "Entity", "fields": [ { "name": "createdAt", diff --git a/flexmodel-sdks b/flexmodel-sdks index cd01e13..cb79787 160000 --- a/flexmodel-sdks +++ b/flexmodel-sdks @@ -1 +1 @@ -Subproject commit cd01e135a16de50c0926d2f1d1685b874b9297c4 +Subproject commit cb79787bd5b8a861bb18e8f3ed78e65d976e102e diff --git a/flexmodel-server/pom.xml b/flexmodel-server/pom.xml index d406ed6..e872c06 100644 --- a/flexmodel-server/pom.xml +++ b/flexmodel-server/pom.xml @@ -11,6 +11,7 @@ flexmodel-server true + dev @@ -137,6 +138,20 @@ + + maven-resources-plugin + + + @ + + + + src/main/resources + true + + + + dev.flexmodel flexmodel-maven-plugin diff --git a/flexmodel-server/src/main/java/dev/flexmodel/common/FlexmodelConfig.java b/flexmodel-server/src/main/java/dev/flexmodel/common/FlexmodelConfig.java index 99b0c83..e8e19d1 100644 --- a/flexmodel-server/src/main/java/dev/flexmodel/common/FlexmodelConfig.java +++ b/flexmodel-server/src/main/java/dev/flexmodel/common/FlexmodelConfig.java @@ -71,6 +71,14 @@ default String pagesUrlTemplate() { @WithDefault("${quarkus.http.root-path}") String apiRootPath(); + /** + * 构建版本号,由 CI 在构建时通过 Maven 资源过滤注入(-Dflexmodel.version=...)。 + * 本地开发未指定时为 "dev"。 + */ + @WithName("version") + @WithDefault("dev") + String version(); + @WithName("jwt") JwtConfig jwt(); diff --git a/flexmodel-server/src/main/java/dev/flexmodel/mcp/ModelingTools.java b/flexmodel-server/src/main/java/dev/flexmodel/mcp/ModelingTools.java index c524c94..50d63ba 100644 --- a/flexmodel-server/src/main/java/dev/flexmodel/mcp/ModelingTools.java +++ b/flexmodel-server/src/main/java/dev/flexmodel/mcp/ModelingTools.java @@ -23,7 +23,7 @@ public class ModelingTools { @Tool(description = """ List all models (entities, enums, native queries) in a project. \ - Returns a JSON array of model definitions. Each model has: type (entity/enum/native_query), name, \ + Returns a JSON array of model definitions. Each model has: type (entity/enum/NativeQuery), name, \ and type-specific fields. Entities include fields array and indexes array. \ Enums include elements array. Native queries include statement string.\ """) @@ -61,14 +61,14 @@ public String get_model( @Tool(description = """ Create a new entity model (maps to a database table) in a project. \ - The entityJson must be a JSON object with type='entity', name, and fields array. \ + The entityJson must be a JSON object with type='Entity', name, and fields array. \ Supported field types: String (with length, default 255), Int, Long, Float (with precision/scale), \ Boolean, DateTime, Date, Time, JSON, Enum (EnumRef, with 'from' pointing to an enum name, 'multiple' for array), \ Relation (with 'from', 'localField', 'foreignField', 'cascadeDelete'). \ Common field properties: name, type, modelName (must match entity name), nullable (default true), \ unique (default false), identity (for primary key), comment, defaultValue. \ Optional indexes array at entity level. \ - Example: {"type":"entity","name":"Student","fields":[\ + Example: {"type":"Entity","name":"Student","fields":[\ {"name":"id","type":"Long","identity":true,"modelName":"Student"},\ {"name":"studentName","type":"String","modelName":"Student","length":255},\ {"name":"age","type":"Int","modelName":"Student"},\ @@ -80,7 +80,7 @@ Boolean, DateTime, Date, Time, JSON, Enum (EnumRef, with 'from' pointing to an e public String create_entity_model( @ToolArg(description = "The project ID, e.g. 'dev_test', 'default'") String projectId, @ToolArg(description = """ - Entity definition as JSON string: must contain type='entity', name, and fields array. \ + Entity definition as JSON string: must contain type='Entity', name, and fields array. \ Each field must have name, type, and modelName. See tool description for supported types and properties.\ """) String entityJson ) { @@ -98,14 +98,14 @@ public String create_entity_model( @Tool(description = """ Create a new enum definition in a project. Enums define a fixed set of string values \ that can be referenced by entity fields via the EnumRef field type (using 'from' property). \ - The enumJson must be a JSON object with name, type='enum', and elements (string array). \ + The enumJson must be a JSON object with name, type='Enum', and elements (string array). \ Elements should be uppercase or UPPER_SNAKE_CASE by convention. \ Optional: comment for description, additionalProperties for i18n or extensions. \ - Example: {"name":"UserGender","type":"enum","elements":["UNKNOWN","MALE","FEMALE"],"comment":"User gender options"}\ + Example: {"name":"UserGender","type":"Enum","elements":["UNKNOWN","MALE","FEMALE"],"comment":"User gender options"}\ """) public String create_enum_model( @ToolArg(description = "The project ID, e.g. 'dev_test', 'default'") String projectId, - @ToolArg(description = "Enum definition as JSON string: must contain name, type='enum', and elements (string array)") String enumJson + @ToolArg(description = "Enum definition as JSON string: must contain name, type='Enum', and elements (string array)") String enumJson ) { log.info("create_enum_model called, projectId={}, enumJson={}", projectId, enumJson); try { diff --git a/flexmodel-server/src/main/java/dev/flexmodel/modeling/ModelingResource.java b/flexmodel-server/src/main/java/dev/flexmodel/modeling/ModelingResource.java index 4a17b4c..2fce04f 100644 --- a/flexmodel-server/src/main/java/dev/flexmodel/modeling/ModelingResource.java +++ b/flexmodel-server/src/main/java/dev/flexmodel/modeling/ModelingResource.java @@ -71,19 +71,19 @@ private void requirePermission(String permission) { @ExampleObject( name = "实体", value = """ - [{ "type": "entity", "name": "Student", "fields": [ { "name": "id", "type": "Long", "identity": true, "modelName": "Student", "unique": false, "nullable": true }, { "name": "studentName", "type": "String", "modelName": "Student", "unique": false, "nullable": true, "length": 255 }, { "name": "gender", "type": "EnumRef", "from": "UserGender", "multiple": false, "modelName": "Student", "unique": false, "nullable": true }, { "name": "interest", "type": "EnumRef", "from": "user_interest", "multiple": true, "modelName": "Student", "unique": false, "nullable": true }, { "name": "age", "type": "Int", "modelName": "Student", "unique": false, "nullable": true }, { "name": "classId", "type": "Long", "modelName": "Student", "unique": false, "nullable": true }, { "name": "studentDetail", "type": "Relation", "modelName": "Student", "unique": false, "nullable": true, "multiple": false, "from": "StudentDetail", "localField": "id", "foreignField": "studentId", "cascadeDelete": true } ], "indexes": [ { "modelName": "Student", "name": "IDX_studentName", "fields": [ { "fieldName": "studentName", "direction": "ASC" } ], "unique": false } ] }] + [{ "type": "Entity", "name": "Student", "fields": [ { "name": "id", "type": "Long", "identity": true, "modelName": "Student", "unique": false, "nullable": true }, { "name": "studentName", "type": "String", "modelName": "Student", "unique": false, "nullable": true, "length": 255 }, { "name": "gender", "type": "EnumRef", "from": "UserGender", "multiple": false, "modelName": "Student", "unique": false, "nullable": true }, { "name": "interest", "type": "EnumRef", "from": "user_interest", "multiple": true, "modelName": "Student", "unique": false, "nullable": true }, { "name": "age", "type": "Int", "modelName": "Student", "unique": false, "nullable": true }, { "name": "classId", "type": "Long", "modelName": "Student", "unique": false, "nullable": true }, { "name": "studentDetail", "type": "ModelRef", "modelName": "Student", "unique": false, "nullable": true, "multiple": false, "from": "StudentDetail", "localField": "id", "foreignField": "studentId", "cascadeDelete": true } ], "indexes": [ { "modelName": "Student", "name": "IDX_studentName", "fields": [ { "fieldName": "studentName", "direction": "ASC" } ], "unique": false } ] }] """ ), @ExampleObject( name = "枚举", value = """ - [{ "name": "UserGender", "type": "enum", "elements": [ "UNKNOWN", "MALE", "FEMALE" ], "comment": "性别" }] + [{ "name": "UserGender", "type": "Enum", "elements": [ "UNKNOWN", "MALE", "FEMALE" ], "comment": "性别" }] """ ), @ExampleObject( name = "本地查询", value = """ - [{ "name": "分组查询", "type": "native_query", "statement": "select count(id) as total, gender, max(age) as ageSum from Student group by gender" }] + [{ "name": "分组查询", "type": "NativeQuery", "statement": "select count(id) as total, gender, max(age) as ageSum from Student group by gender" }] """ ), } @@ -114,19 +114,19 @@ public List findModels(@PathParam("projectId") String projectId) { @ExampleObject( name = "实体", value = """ - { "type": "entity", "name": "Student", "fields": [ { "name": "id", "type": "Long", "identity": true, "modelName": "Student", "unique": false, "nullable": true }, { "name": "studentName", "type": "String", "modelName": "Student", "unique": false, "nullable": true, "length": 255 }, { "name": "gender", "type": "EnumRef", "from": "UserGender", "multiple": false, "modelName": "Student", "unique": false, "nullable": true }, { "name": "interest", "type": "EnumRef", "from": "user_interest", "multiple": true, "modelName": "Student", "unique": false, "nullable": true }, { "name": "age", "type": "Int", "modelName": "Student", "unique": false, "nullable": true }, { "name": "classId", "type": "Long", "modelName": "Student", "unique": false, "nullable": true }, { "name": "studentDetail", "type": "Relation", "modelName": "Student", "unique": false, "nullable": true, "multiple": false, "from": "StudentDetail", "localField": "id", "foreignField": "studentId", "cascadeDelete": true } ], "indexes": [ { "modelName": "Student", "name": "IDX_studentName", "fields": [ { "fieldName": "studentName", "direction": "ASC" } ], "unique": false } ] } + { "type": "Entity", "name": "Student", "fields": [ { "name": "id", "type": "Long", "identity": true, "modelName": "Student", "unique": false, "nullable": true }, { "name": "studentName", "type": "String", "modelName": "Student", "unique": false, "nullable": true, "length": 255 }, { "name": "gender", "type": "EnumRef", "from": "UserGender", "multiple": false, "modelName": "Student", "unique": false, "nullable": true }, { "name": "interest", "type": "EnumRef", "from": "user_interest", "multiple": true, "modelName": "Student", "unique": false, "nullable": true }, { "name": "age", "type": "Int", "modelName": "Student", "unique": false, "nullable": true }, { "name": "classId", "type": "Long", "modelName": "Student", "unique": false, "nullable": true }, { "name": "studentDetail", "type": "ModelRef", "modelName": "Student", "unique": false, "nullable": true, "multiple": false, "from": "StudentDetail", "localField": "id", "foreignField": "studentId", "cascadeDelete": true } ], "indexes": [ { "modelName": "Student", "name": "IDX_studentName", "fields": [ { "fieldName": "studentName", "direction": "ASC" } ], "unique": false } ] } """ ), @ExampleObject( name = "枚举", value = """ - { "name": "UserGender", "type": "enum", "elements": [ "UNKNOWN", "MALE", "FEMALE" ], "comment": "性别" } + { "name": "UserGender", "type": "Enum", "elements": [ "UNKNOWN", "MALE", "FEMALE" ], "comment": "性别" } """ ), @ExampleObject( name = "本地查询", value = """ - { "name": "分组查询", "type": "native_query", "statement": "select count(id) as total, gender, max(age) as ageSum from Student group by gender" } + { "name": "分组查询", "type": "NativeQuery", "statement": "select count(id) as total, gender, max(age) as ageSum from Student group by gender" } """ ), } @@ -154,19 +154,19 @@ public SchemaObject findModel(@PathParam("projectId") String projectId, @PathPar @ExampleObject( name = "实体", value = """ - { "type": "entity", "name": "Student", "fields": [ { "name": "id", "type": "Long", "identity": true, "modelName": "Student", "unique": false, "nullable": true }, { "name": "studentName", "type": "String", "modelName": "Student", "unique": false, "nullable": true, "length": 255 }, { "name": "gender", "type": "EnumRef", "from": "UserGender", "multiple": false, "modelName": "Student", "unique": false, "nullable": true }, { "name": "interest", "type": "EnumRef", "from": "user_interest", "multiple": true, "modelName": "Student", "unique": false, "nullable": true }, { "name": "age", "type": "Int", "modelName": "Student", "unique": false, "nullable": true }, { "name": "classId", "type": "Long", "modelName": "Student", "unique": false, "nullable": true }, { "name": "studentDetail", "type": "Relation", "modelName": "Student", "unique": false, "nullable": true, "multiple": false, "from": "StudentDetail", "localField": "id", "foreignField": "studentId", "cascadeDelete": true } ], "indexes": [ { "modelName": "Student", "name": "IDX_studentName", "fields": [ { "fieldName": "studentName", "direction": "ASC" } ], "unique": false } ] } + { "type": "Entity", "name": "Student", "fields": [ { "name": "id", "type": "Long", "identity": true, "modelName": "Student", "unique": false, "nullable": true }, { "name": "studentName", "type": "String", "modelName": "Student", "unique": false, "nullable": true, "length": 255 }, { "name": "gender", "type": "EnumRef", "from": "UserGender", "multiple": false, "modelName": "Student", "unique": false, "nullable": true }, { "name": "interest", "type": "EnumRef", "from": "user_interest", "multiple": true, "modelName": "Student", "unique": false, "nullable": true }, { "name": "age", "type": "Int", "modelName": "Student", "unique": false, "nullable": true }, { "name": "classId", "type": "Long", "modelName": "Student", "unique": false, "nullable": true }, { "name": "studentDetail", "type": "ModelRef", "modelName": "Student", "unique": false, "nullable": true, "multiple": false, "from": "StudentDetail", "localField": "id", "foreignField": "studentId", "cascadeDelete": true } ], "indexes": [ { "modelName": "Student", "name": "IDX_studentName", "fields": [ { "fieldName": "studentName", "direction": "ASC" } ], "unique": false } ] } """ ), @ExampleObject( name = "枚举", value = """ - { "name": "UserGender", "type": "enum", "elements": [ "UNKNOWN", "MALE", "FEMALE" ], "comment": "性别" } + { "name": "UserGender", "type": "Enum", "elements": [ "UNKNOWN", "MALE", "FEMALE" ], "comment": "性别" } """ ), @ExampleObject( name = "本地查询", value = """ - { "name": "分组查询", "type": "native_query", "statement": "select count(id) as total, gender, max(age) as ageSum from Student group by gender" } + { "name": "分组查询", "type": "NativeQuery", "statement": "select count(id) as total, gender, max(age) as ageSum from Student group by gender" } """ ), } @@ -190,19 +190,19 @@ public SchemaObject findModel(@PathParam("projectId") String projectId, @PathPar @ExampleObject( name = "实体", value = """ - { "type": "entity", "name": "Student", "fields": [ { "name": "id", "type": "Long", "identity": true, "modelName": "Student", "unique": false, "nullable": true }, { "name": "studentName", "type": "String", "modelName": "Student", "unique": false, "nullable": true, "length": 255 }, { "name": "gender", "type": "EnumRef", "from": "UserGender", "multiple": false, "modelName": "Student", "unique": false, "nullable": true }, { "name": "interest", "type": "EnumRef", "from": "user_interest", "multiple": true, "modelName": "Student", "unique": false, "nullable": true }, { "name": "age", "type": "Int", "modelName": "Student", "unique": false, "nullable": true }, { "name": "classId", "type": "Long", "modelName": "Student", "unique": false, "nullable": true }, { "name": "studentDetail", "type": "Relation", "modelName": "Student", "unique": false, "nullable": true, "multiple": false, "from": "StudentDetail", "localField": "id", "foreignField": "studentId", "cascadeDelete": true } ], "indexes": [ { "modelName": "Student", "name": "IDX_studentName", "fields": [ { "fieldName": "studentName", "direction": "ASC" } ], "unique": false } ] } + { "type": "Entity", "name": "Student", "fields": [ { "name": "id", "type": "Long", "identity": true, "modelName": "Student", "unique": false, "nullable": true }, { "name": "studentName", "type": "String", "modelName": "Student", "unique": false, "nullable": true, "length": 255 }, { "name": "gender", "type": "EnumRef", "from": "UserGender", "multiple": false, "modelName": "Student", "unique": false, "nullable": true }, { "name": "interest", "type": "EnumRef", "from": "user_interest", "multiple": true, "modelName": "Student", "unique": false, "nullable": true }, { "name": "age", "type": "Int", "modelName": "Student", "unique": false, "nullable": true }, { "name": "classId", "type": "Long", "modelName": "Student", "unique": false, "nullable": true }, { "name": "studentDetail", "type": "ModelRef", "modelName": "Student", "unique": false, "nullable": true, "multiple": false, "from": "StudentDetail", "localField": "id", "foreignField": "studentId", "cascadeDelete": true } ], "indexes": [ { "modelName": "Student", "name": "IDX_studentName", "fields": [ { "fieldName": "studentName", "direction": "ASC" } ], "unique": false } ] } """ ), @ExampleObject( name = "枚举", value = """ - { "name": "UserGender", "type": "enum", "elements": [ "UNKNOWN", "MALE", "FEMALE" ], "comment": "性别" } + { "name": "UserGender", "type": "Enum", "elements": [ "UNKNOWN", "MALE", "FEMALE" ], "comment": "性别" } """ ), @ExampleObject( name = "本地查询", value = """ - { "name": "分组查询", "type": "native_query", "statement": "select count(id) as total, gender, max(age) as ageSum from Student group by gender" } + { "name": "分组查询", "type": "NativeQuery", "statement": "select count(id) as total, gender, max(age) as ageSum from Student group by gender" } """ ), } @@ -241,19 +241,19 @@ public Boolean executeFml(@PathParam("projectId") String projectId, FmlRequest r @ExampleObject( name = "实体", value = """ - { "type": "entity", "name": "Student", "fields": [ { "name": "id", "type": "Long", "identity": true, "modelName": "Student", "unique": false, "nullable": true }, { "name": "studentName", "type": "String", "modelName": "Student", "unique": false, "nullable": true, "length": 255 }, { "name": "gender", "type": "EnumRef", "from": "UserGender", "multiple": false, "modelName": "Student", "unique": false, "nullable": true }, { "name": "interest", "type": "EnumRef", "from": "user_interest", "multiple": true, "modelName": "Student", "unique": false, "nullable": true }, { "name": "age", "type": "Int", "modelName": "Student", "unique": false, "nullable": true }, { "name": "classId", "type": "Long", "modelName": "Student", "unique": false, "nullable": true }, { "name": "studentDetail", "type": "Relation", "modelName": "Student", "unique": false, "nullable": true, "multiple": false, "from": "StudentDetail", "localField": "id", "foreignField": "studentId", "cascadeDelete": true } ], "indexes": [ { "modelName": "Student", "name": "IDX_studentName", "fields": [ { "fieldName": "studentName", "direction": "ASC" } ], "unique": false } ] } + { "type": "Entity", "name": "Student", "fields": [ { "name": "id", "type": "Long", "identity": true, "modelName": "Student", "unique": false, "nullable": true }, { "name": "studentName", "type": "String", "modelName": "Student", "unique": false, "nullable": true, "length": 255 }, { "name": "gender", "type": "EnumRef", "from": "UserGender", "multiple": false, "modelName": "Student", "unique": false, "nullable": true }, { "name": "interest", "type": "EnumRef", "from": "user_interest", "multiple": true, "modelName": "Student", "unique": false, "nullable": true }, { "name": "age", "type": "Int", "modelName": "Student", "unique": false, "nullable": true }, { "name": "classId", "type": "Long", "modelName": "Student", "unique": false, "nullable": true }, { "name": "studentDetail", "type": "ModelRef", "modelName": "Student", "unique": false, "nullable": true, "multiple": false, "from": "StudentDetail", "localField": "id", "foreignField": "studentId", "cascadeDelete": true } ], "indexes": [ { "modelName": "Student", "name": "IDX_studentName", "fields": [ { "fieldName": "studentName", "direction": "ASC" } ], "unique": false } ] } """ ), @ExampleObject( name = "枚举", value = """ - { "name": "UserGender", "type": "enum", "elements": [ "UNKNOWN", "MALE", "FEMALE" ], "comment": "性别" } + { "name": "UserGender", "type": "Enum", "elements": [ "UNKNOWN", "MALE", "FEMALE" ], "comment": "性别" } """ ), @ExampleObject( name = "本地查询", value = """ - { "name": "分组查询", "type": "native_query", "statement": "select count(id) as total, gender, max(age) as ageSum from Student group by gender" } + { "name": "分组查询", "type": "NativeQuery", "statement": "select count(id) as total, gender, max(age) as ageSum from Student group by gender" } """ ), } @@ -277,19 +277,19 @@ public Boolean executeFml(@PathParam("projectId") String projectId, FmlRequest r @ExampleObject( name = "实体", value = """ - { "type": "entity", "name": "Student", "fields": [ { "name": "id", "type": "Long", "identity": true, "modelName": "Student", "unique": false, "nullable": true }, { "name": "studentName", "type": "String", "modelName": "Student", "unique": false, "nullable": true, "length": 255 }, { "name": "gender", "type": "EnumRef", "from": "UserGender", "multiple": false, "modelName": "Student", "unique": false, "nullable": true }, { "name": "interest", "type": "EnumRef", "from": "user_interest", "multiple": true, "modelName": "Student", "unique": false, "nullable": true }, { "name": "age", "type": "Int", "modelName": "Student", "unique": false, "nullable": true }, { "name": "classId", "type": "Long", "modelName": "Student", "unique": false, "nullable": true }, { "name": "studentDetail", "type": "Relation", "modelName": "Student", "unique": false, "nullable": true, "multiple": false, "from": "StudentDetail", "localField": "id", "foreignField": "studentId", "cascadeDelete": true } ], "indexes": [ { "modelName": "Student", "name": "IDX_studentName", "fields": [ { "fieldName": "studentName", "direction": "ASC" } ], "unique": false } ] } + { "type": "Entity", "name": "Student", "fields": [ { "name": "id", "type": "Long", "identity": true, "modelName": "Student", "unique": false, "nullable": true }, { "name": "studentName", "type": "String", "modelName": "Student", "unique": false, "nullable": true, "length": 255 }, { "name": "gender", "type": "EnumRef", "from": "UserGender", "multiple": false, "modelName": "Student", "unique": false, "nullable": true }, { "name": "interest", "type": "EnumRef", "from": "user_interest", "multiple": true, "modelName": "Student", "unique": false, "nullable": true }, { "name": "age", "type": "Int", "modelName": "Student", "unique": false, "nullable": true }, { "name": "classId", "type": "Long", "modelName": "Student", "unique": false, "nullable": true }, { "name": "studentDetail", "type": "ModelRef", "modelName": "Student", "unique": false, "nullable": true, "multiple": false, "from": "StudentDetail", "localField": "id", "foreignField": "studentId", "cascadeDelete": true } ], "indexes": [ { "modelName": "Student", "name": "IDX_studentName", "fields": [ { "fieldName": "studentName", "direction": "ASC" } ], "unique": false } ] } """ ), @ExampleObject( name = "枚举", value = """ - { "name": "UserGender", "type": "enum", "elements": [ "UNKNOWN", "MALE", "FEMALE" ], "comment": "性别" } + { "name": "UserGender", "type": "Enum", "elements": [ "UNKNOWN", "MALE", "FEMALE" ], "comment": "性别" } """ ), @ExampleObject( name = "本地查询", value = """ - { "name": "分组查询", "type": "native_query", "statement": "select count(id) as total, gender, max(age) as ageSum from Student group by gender" } + { "name": "分组查询", "type": "NativeQuery", "statement": "select count(id) as total, gender, max(age) as ageSum from Student group by gender" } """ ), } @@ -526,7 +526,7 @@ public EnumSchema(String name) { description = "本地查询", properties = { @SchemaProperty(name = "name", description = "名称"), - @SchemaProperty(name = "type", description = "类型, entity: 实体;native_query: 本地查询;enum: 枚举"), + @SchemaProperty(name = "type", description = "类型, Entity: 实体;NativeQuery: 本地查询;Enum: 枚举"), @SchemaProperty(name = "statement", description = "语句"), @SchemaProperty(name = "comment", description = "注释"), @SchemaProperty(name = "additionalProperties", description = "用户自定义扩展属性"), @@ -543,7 +543,7 @@ public NativeQuerySchema(String name) { description = "实体", properties = { @SchemaProperty(name = "name", description = "名称"), - @SchemaProperty(name = "type", description = "类型, entity: 实体;native_query: 本地查询;enum: 枚举"), + @SchemaProperty(name = "type", description = "类型, Entity: 实体;NativeQuery: 本地查询;Enum: 枚举"), @SchemaProperty(name = "fields", description = "字段列表"), @SchemaProperty(name = "indexes", description = "索引列表"), @SchemaProperty(name = "comment", description = "注释"), diff --git a/flexmodel-server/src/main/java/dev/flexmodel/settings/GlobalResource.java b/flexmodel-server/src/main/java/dev/flexmodel/settings/GlobalResource.java index 0e7c2ce..904f832 100644 --- a/flexmodel-server/src/main/java/dev/flexmodel/settings/GlobalResource.java +++ b/flexmodel-server/src/main/java/dev/flexmodel/settings/GlobalResource.java @@ -53,6 +53,7 @@ public class GlobalResource { @SchemaProperty(name = "routingMode", description = "路由模式:path 为路径模式,subdomain 为子域名模式"), @SchemaProperty(name = "edgeUrlTemplate", description = "边缘函数调用 URL,由 routingMode + projectBaseDomain 自动推导"), @SchemaProperty(name = "pagesUrlTemplate", description = "Pages 站点 URL,由 routingMode + projectBaseDomain 自动推导"), + @SchemaProperty(name = "version", description = "构建版本号"), } ) ) @@ -69,7 +70,8 @@ public Map getProfile() { "projectBaseDomain", config.projectBaseDomain().orElse(""), "routingMode", config.isSubdomainRouting() ? "subdomain" : "path", "edgeUrlTemplate", config.edgeUrlTemplate(), - "pagesUrlTemplate", config.pagesUrlTemplate() + "pagesUrlTemplate", config.pagesUrlTemplate(), + "version", config.version() ); } diff --git a/flexmodel-server/src/main/resources/META-INF/native-image/dev.flexmodel/flexmodel-server/reachability-metadata.json b/flexmodel-server/src/main/resources/META-INF/native-image/dev.flexmodel/flexmodel-server/reachability-metadata.json index 33d9ef6..04a05b1 100644 --- a/flexmodel-server/src/main/resources/META-INF/native-image/dev.flexmodel/flexmodel-server/reachability-metadata.json +++ b/flexmodel-server/src/main/resources/META-INF/native-image/dev.flexmodel/flexmodel-server/reachability-metadata.json @@ -5366,7 +5366,7 @@ ] }, { - "type": "dev.flexmodel.model.field.RelationField", + "type": "dev.flexmodel.model.field.ModelRefField", "serializable": true, "methods": [ { diff --git a/flexmodel-server/src/main/resources/META-INF/native-image/dev.flexmodel/flexmodel-server/serialization-config.json b/flexmodel-server/src/main/resources/META-INF/native-image/dev.flexmodel/flexmodel-server/serialization-config.json index 53f48df..6a66695 100644 --- a/flexmodel-server/src/main/resources/META-INF/native-image/dev.flexmodel/flexmodel-server/serialization-config.json +++ b/flexmodel-server/src/main/resources/META-INF/native-image/dev.flexmodel/flexmodel-server/serialization-config.json @@ -45,7 +45,7 @@ "name": "dev.flexmodel.model.field.EnumRefField" }, { - "name": "dev.flexmodel.model.field.RelationField" + "name": "dev.flexmodel.model.field.ModelRefField" }, { "name": "dev.flexmodel.model.field.TypedField" diff --git a/flexmodel-server/src/main/resources/application.properties b/flexmodel-server/src/main/resources/application.properties index 1aa85dd..3624944 100644 --- a/flexmodel-server/src/main/resources/application.properties +++ b/flexmodel-server/src/main/resources/application.properties @@ -3,6 +3,7 @@ quarkus.virtual-threads.enabled=true quarkus.swagger-ui.always-include=true quarkus.http.root-path=/api quarkus.http.limits.max-body-size=100M +flexmodel.version=@flexmodel.version@ quarkus.log.category."dev.flexmodel".level=INFO # File logging — daily rotation, retain 7 days quarkus.log.file.enable=true diff --git a/flexmodel-server/src/test/java/dev/flexmodel/pages/PageAliasManagerTest.java b/flexmodel-server/src/test/java/dev/flexmodel/pages/PageAliasManagerTest.java index da5dc0b..41283e5 100644 --- a/flexmodel-server/src/test/java/dev/flexmodel/pages/PageAliasManagerTest.java +++ b/flexmodel-server/src/test/java/dev/flexmodel/pages/PageAliasManagerTest.java @@ -220,6 +220,11 @@ public java.util.Optional projectBaseDomain() { @Override public String apiRootPath() { return "/api"; } + @Override + public String version() { + return "dev"; + } + @Override public JwtConfig jwt() { return null; } } diff --git a/flexmodel-server/src/test/java/dev/flexmodel/pages/PageDeployerTest.java b/flexmodel-server/src/test/java/dev/flexmodel/pages/PageDeployerTest.java index 3a57622..3bb52c4 100644 --- a/flexmodel-server/src/test/java/dev/flexmodel/pages/PageDeployerTest.java +++ b/flexmodel-server/src/test/java/dev/flexmodel/pages/PageDeployerTest.java @@ -249,6 +249,11 @@ public java.util.Optional projectBaseDomain() { @Override public String apiRootPath() { return "/api"; } + @Override + public String version() { + return "dev"; + } + @Override public JwtConfig jwt() { return null; } } diff --git a/flexmodel-server/src/test/java/dev/flexmodel/rest/ModelResourceTest.java b/flexmodel-server/src/test/java/dev/flexmodel/rest/ModelResourceTest.java index eadcf0e..6abe09f 100644 --- a/flexmodel-server/src/test/java/dev/flexmodel/rest/ModelResourceTest.java +++ b/flexmodel-server/src/test/java/dev/flexmodel/rest/ModelResourceTest.java @@ -60,7 +60,7 @@ void testCreateModel() { .contentType(ContentType.JSON) .body(""" { - "type": "entity", + "type": "Entity", "name": "testCreateModelStudent", "fields": [ { @@ -112,7 +112,7 @@ void testDropModel() { .contentType(ContentType.JSON) .body(""" { - "type": "entity", + "type": "Entity", "name": "testDropModelStudent", "fields": [ { @@ -181,7 +181,7 @@ void testCreateField() { .contentType(ContentType.JSON) .body(""" { - "type": "entity", + "type": "Entity", "name": "testCreateFieldStudent", "fields": [ { @@ -260,7 +260,7 @@ void testModifyField() { .contentType(ContentType.JSON) .body(""" { - "type": "entity", + "type": "Entity", "name": "testModifyFieldStudent", "fields": [ { @@ -340,7 +340,7 @@ void testDropField() { .contentType(ContentType.JSON) .body(""" { - "type": "entity", + "type": "Entity", "name": "testDropFieldStudent", "fields": [ { @@ -411,7 +411,7 @@ void testCreateIndex() { .contentType(ContentType.JSON) .body(""" { - "type": "entity", + "type": "Entity", "name": "testCreateIndexStudent", "fields": [ { @@ -494,7 +494,7 @@ void testModifyIndex() { .contentType(ContentType.JSON) .body(""" { - "type": "entity", + "type": "Entity", "name": "testModifyIndexStudent", "fields": [ { @@ -589,7 +589,7 @@ void testDropIndex() { .contentType(ContentType.JSON) .body(""" { - "type": "entity", + "type": "Entity", "name": "testDropIndexStudent", "fields": [ { diff --git a/flexmodel-server/src/test/java/dev/flexmodel/rest/PermissionFilterTest.java b/flexmodel-server/src/test/java/dev/flexmodel/rest/PermissionFilterTest.java index 3d6faa3..b910f0c 100644 --- a/flexmodel-server/src/test/java/dev/flexmodel/rest/PermissionFilterTest.java +++ b/flexmodel-server/src/test/java/dev/flexmodel/rest/PermissionFilterTest.java @@ -205,7 +205,7 @@ void viewOnlyDenyWrite() { .header("Authorization", testTokenHelper.getAuthorizationHeader()) .header("X-Test-Permissions", "modeling:Student:view") .contentType(ContentType.JSON) - .body("{\"type\":\"entity\",\"name\":\"Student\"}") + .body("{\"type\":\"Entity\",\"name\":\"Student\"}") .when() .put(Resources.ROOT_PATH + "/projects/dev_test/models/Student") .then() diff --git a/flexmodel-ui b/flexmodel-ui index 8d0b601..85a36d3 160000 --- a/flexmodel-ui +++ b/flexmodel-ui @@ -1 +1 @@ -Subproject commit 8d0b6013dd2b421e2ab6eb4de7ab9a2e024afc0e +Subproject commit 85a36d39d82ac58ddd2b156cb4a3f2ab4aa9f389 diff --git a/flexmodel-website b/flexmodel-website index 501c05e..c6a5fad 160000 --- a/flexmodel-website +++ b/flexmodel-website @@ -1 +1 @@ -Subproject commit 501c05ec3151cc36ddd9bdb657c52be0d549bd13 +Subproject commit c6a5fadbf9be52ea2a5cc32f4aff6f00470a8fba diff --git a/progress.md b/progress.md index 3049593..6cd2030 100644 --- a/progress.md +++ b/progress.md @@ -1,4 +1,23 @@ -# Session Progress Log +# Session Progress Log + +## Doc Fix: 补全模型引用字段重命名的文档更新(2026-08-15) + +**背景:** `feature/model-ref` 分支此前将 `RelationField` 重命名为 `ModelRefField`、`ScalarType.RELATION` → `MODEL_REF`、 +`ScalarType.ENUM` → `ENUM_REF`(commit d3be8f0、d8bb3cb)。源码与测试资源已全部更新且编译通过,但 `flexmodel-engine/docs/` 下 +3 个文档仍残留旧 API 名称。 + +**修复:** + +- `flexmodel-engine/docs/API.md`:将「关系字段」章节标题改为「模型引用字段」;将 `RelationField` 示例重写为 `ModelRefField` 新 + API(`setFrom`/`setLocalField`/`setForeignField`/`setMultiple`);删除新 API 已不支持的多对多示例(`setJoinTable` 等方法已移除)。 +- `flexmodel-engine/docs/flexmodel-core.md`:`new RelationField("studentClass")` → `new ModelRefField("studentClass")`。 +- `flexmodel-engine/docs/flexmodel-codegen.md`:`it.isRelationField()` → `it.isModelRefField()`。 + +**验证:** + +- `mvn test -pl flexmodel-engine/flexmodel-core -o` → BUILD SUCCESS,Tests run: 49, Failures: 0, Errors: 0(含 + `JsonSerializeTest`)。 +- 全仓搜索 `RelationField` / `isRelationField`(docs 目录)→ 0 残留。 ## Bug Fix: Storage 复制访问链接不能访问(2026-08-06)