You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@submarine.apache.org by pi...@apache.org on 2021/10/24 18:49:41 UTC

[submarine] branch master updated: SUBMARINE-1052. Create submarine model management service in server

This is an automated email from the ASF dual-hosted git repository.

pingsutw pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/submarine.git


The following commit(s) were added to refs/heads/master by this push:
     new 9ba44b9  SUBMARINE-1052. Create submarine model management service in server
9ba44b9 is described below

commit 9ba44b975d3971664c9bd3daa9945d845a335251
Author: KUAN-HSUN-LI <b0...@ntu.edu.tw>
AuthorDate: Sun Oct 17 10:11:24 2021 +0800

    SUBMARINE-1052. Create submarine model management service in server
    
    ### What is this PR for?
    Create the model management service in the server for later use in model serving and model management workbench.
    
    ### What type of PR is it?
    [Feature]
    
    ### Todos
    
    ### What is the Jira issue?
    https://issues.apache.org/jira/browse/SUBMARINE-1052
    
    ### How should this be tested?
    CI pass.
    All of the tests for new functions are provided under the `submarine-server/server-core/src/test/java/org/apache/submarine/server/model/database` directory.
    
    ### Screenshots (if appropriate)
    
    ### Questions:
    * Do the license files need updating? No
    * Are there breaking changes for older versions? No
    * Does this need new documentation? No
    
    Author: KUAN-HSUN-LI <b0...@ntu.edu.tw>
    
    Signed-off-by: Kevin <pi...@apache.org>
    
    Closes #770 from KUAN-HSUN-LI/SUBMARINE-1052 and squashes the following commits:
    
    a01fd85e [KUAN-HSUN-LI] SUBMARINE-1052. Create submarine model management service in server
    f9432abc [KUAN-HSUN-LI] SUBMARINE-1052. Add exception
    42348927 [KUAN-HSUN-LI] Remove useless code
    e5bc7c25 [KUAN-HSUN-LI] SUBMARINE-1052. Create submarine model management service in server
    090f6664 [KUAN-HSUN-LI] SUBMARINE-1052. Create submarine model management service in server
---
 .../submarine/commons/utils/SubmarineConfVars.java |   4 +-
 .../server/database/utils/MyBatisUtil.java         |   2 +-
 .../database/entities/ModelVersionEntity.java      | 120 +++++++-------
 ...lNameEntity.java => ModelVersionTagEntity.java} |  45 ++---
 ...lNameEntity.java => RegisteredModelEntity.java} |  38 +++--
 .../RegisteredModelTagEntity.java}                 |  36 +++-
 .../model/database/mappers/ModelVersionMapper.java |  14 +-
 ...rsionMapper.java => ModelVersionTagMapper.java} |  12 +-
 ...lNameMapper.java => RegisteredModelMapper.java} |  19 ++-
 ...meMapper.java => RegisteredModelTagMapper.java} |  14 +-
 .../model/database/service/ModelService.java       | 181 ---------------------
 .../database/service/ModelVersionService.java      | 112 +++++++++++++
 .../database/service/ModelVersionTagService.java   |  61 +++++++
 .../database/service/RegisteredModelService.java   | 137 ++++++++++++++++
 .../service/RegisteredModelTagService.java         |  61 +++++++
 .../src/main/resources/mybatis-config.xml          |   4 +
 .../database/mappers/ModelVersionMapper.xml        |  99 +++++++----
 .../database/mappers/ModelVersionTagMapper.xml     |  41 +++++
 .../database/mappers/RegisteredModelMapper.xml     | 106 ++++++++++++
 .../database/mappers/RegisteredModelNameMapper.xml |  68 --------
 .../database/mappers/RegisteredModelTagMapper.xml  |  41 +++++
 .../server/model/database/ModelVersionTagTest.java |  75 +++++++++
 .../server/model/database/ModelVersionTest.java    | 174 ++++++++++++++++++++
 .../model/database/RegisteredModelServiceTest.java | 148 +++++++++++++++++
 .../database/RegisteredModelTagServiceTest.java    |  61 +++++++
 25 files changed, 1246 insertions(+), 427 deletions(-)

diff --git a/submarine-commons/commons-utils/src/main/java/org/apache/submarine/commons/utils/SubmarineConfVars.java b/submarine-commons/commons-utils/src/main/java/org/apache/submarine/commons/utils/SubmarineConfVars.java
index bb3d1cd..38945c9 100644
--- a/submarine-commons/commons-utils/src/main/java/org/apache/submarine/commons/utils/SubmarineConfVars.java
+++ b/submarine-commons/commons-utils/src/main/java/org/apache/submarine/commons/utils/SubmarineConfVars.java
@@ -53,8 +53,8 @@ public class SubmarineConfVars {
 
     JDBC_DRIVERCLASSNAME("jdbc.driverClassName", "com.mysql.jdbc.Driver"),
     JDBC_URL("jdbc.url", "jdbc:mysql://127.0.0.1:3306/submarine" +
-        "?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&" +
-        "failOverReadOnly=false&zeroDateTimeBehavior=convertToNull&useSSL=false"),
+        "?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&allowMultiQueries=true" +
+        "failOverReadOnly=false&zeroDateTimeBehavior=convertToNull&useSSL=false&"),
     JDBC_USERNAME("jdbc.username", "submarine"),
     JDBC_PASSWORD("jdbc.password", "password"),
     METASTORE_JDBC_URL("metastore.jdbc.url", "jdbc:mysql://127.0.0.1:3306/metastore" +
diff --git a/submarine-server/server-core/src/main/java/org/apache/submarine/server/database/utils/MyBatisUtil.java b/submarine-server/server-core/src/main/java/org/apache/submarine/server/database/utils/MyBatisUtil.java
index 9a638ef..cfd0192 100755
--- a/submarine-server/server-core/src/main/java/org/apache/submarine/server/database/utils/MyBatisUtil.java
+++ b/submarine-server/server-core/src/main/java/org/apache/submarine/server/database/utils/MyBatisUtil.java
@@ -97,7 +97,7 @@ public class MyBatisUtil {
     // Run the test unit using the test database
     SubmarineConfiguration conf = SubmarineConfiguration.getInstance();
     conf.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/submarine_test?" +
-            "useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&" +
+            "useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&allowMultiQueries=true&" +
             "failOverReadOnly=false&zeroDateTimeBehavior=convertToNull&useSSL=false");
     conf.setJdbcUserName("submarine_test");
     conf.setJdbcPassword("password_test");
diff --git a/submarine-server/server-core/src/main/java/org/apache/submarine/server/model/database/entities/ModelVersionEntity.java b/submarine-server/server-core/src/main/java/org/apache/submarine/server/model/database/entities/ModelVersionEntity.java
index 7c7cb3b..ade2cb7 100644
--- a/submarine-server/server-core/src/main/java/org/apache/submarine/server/model/database/entities/ModelVersionEntity.java
+++ b/submarine-server/server-core/src/main/java/org/apache/submarine/server/model/database/entities/ModelVersionEntity.java
@@ -19,30 +19,31 @@
 
 package org.apache.submarine.server.model.database.entities;
 
+import java.sql.Timestamp;
+import java.util.List;
+
 public class ModelVersionEntity {
   private String name;
 
   private Integer version;
 
-  private Long createTime;
-
-  private Long lastUpdatedTime;
-
-  private String description;
+  private String source;
 
   private String userId;
 
+  private String experimentId;
+
   private String currentStage;
 
-  private String source;
+  private Timestamp creationTime;
 
-  private String runId;
+  private Timestamp lastUpdatedTime;
 
-  private String status;
+  private String dataset;
 
-  private String statusMessage;
+  private String description;
 
-  private String runLink;
+  private List<String> tags;
 
   public String getName() {
     return name;
@@ -60,28 +61,12 @@ public class ModelVersionEntity {
     this.version = version;
   }
 
-  public Long getCreateTime() {
-    return createTime;
-  }
-
-  public void setCreateTime(Long createTime) {
-    this.createTime = createTime;
-  }
-
-  public Long getLastUpdatedTime() {
-    return lastUpdatedTime;
-  }
-
-  public void setLastUpdatedTime(Long lastUpdatedTime) {
-    this.lastUpdatedTime = lastUpdatedTime;
-  }
-
-  public String getDescription() {
-    return description;
+  public String getSource() {
+    return source;
   }
 
-  public void setDescription(String description) {
-    this.description = description;
+  public void setSource(String source) {
+    this.source = source;
   }
 
   public String getUserId() {
@@ -92,6 +77,14 @@ public class ModelVersionEntity {
     this.userId = userId;
   }
 
+  public String getExperimentId() {
+    return experimentId;
+  }
+
+  public void setExperimentId(String experimentId) {
+    this.experimentId = experimentId;
+  }
+
   public String getCurrentStage() {
     return currentStage;
   }
@@ -100,60 +93,61 @@ public class ModelVersionEntity {
     this.currentStage = currentStage;
   }
 
-  public String getSource() {
-    return source;
+  public Timestamp getCreationTime() {
+    return creationTime;
   }
 
-  public void setSource(String source) {
-    this.source = source;
+  public void setCreationTime(Timestamp creationTime) {
+    this.creationTime = creationTime;
   }
 
-  public String getRunId() {
-    return runId;
+  public Timestamp getLastUpdatedTime() {
+    return lastUpdatedTime;
   }
 
-  public void setRunId(String runId) {
-    this.runId = runId;
+  public void setLastUpdatedTime(Timestamp lastUpdatedTime) {
+    this.lastUpdatedTime = lastUpdatedTime;
   }
 
-  public String getStatus() {
-    return status;
+  public String getDataset() {
+    return dataset;
   }
 
-  public void setStatus(String status) {
-    this.status = status;
+  public void setDataset(String dataset) {
+    this.dataset = dataset;
   }
 
-  public String getStatusMessage() {
-    return statusMessage;
+  public String getDescription() {
+    return description;
   }
 
-  public void setStatusMessage(String statusMessage) {
-    this.statusMessage = statusMessage;
+  public void setDescription(String description) {
+    this.description = description;
   }
 
-  public String getRunLink() {
-    return runLink;
+  public List<String> getTags() {
+    return tags;
   }
 
-  public void setRunLink(String runLink) {
-    this.runLink = runLink;
+  public void setTags(List<String> tags) {
+    this.tags = tags;
   }
 
+  public ModelVersionEntity() {}
+
   public String toString() {
     return "ModelVersionEntity{" +
-        "name='" + name + '\'' +
-        ",version='" + version + '\'' +
-        ", createTime='" + createTime + '\'' +
-        ", lastUpdatedTime=" + lastUpdatedTime + '\'' +
-        ", description='" + description + '\'' +
-        ", userId='" + userId + '\'' +
-        ", currentStage='" + currentStage + '\'' +
-        ", source='" + source + '\'' +
-        ", runLink='" + runLink + '\'' +
-        ", runId='" + runId + '\'' +
-        ", status='" + status + '\'' +
-        ", statusMessage='" + statusMessage + '\'' +
-        '}';
+      "name='" + name + '\'' +
+      ",version='" + version + '\'' +
+      ", source='" + source + '\'' +
+      ", userId='" + userId + '\'' +
+      ", experimentId='" + experimentId + '\'' +
+      ", currentStage='" + currentStage + '\'' +
+      ", creationTime='" + creationTime + '\'' +
+      ", lastUpdatedTime=" + lastUpdatedTime + '\'' +
+      ", dataset=" + dataset + '\'' +
+      ", description='" + description + '\'' +
+      ", tags='" + tags + '\'' +
+      '}';
   }
 }
diff --git a/submarine-server/server-core/src/main/java/org/apache/submarine/server/model/database/entities/RegisteredModelNameEntity.java b/submarine-server/server-core/src/main/java/org/apache/submarine/server/model/database/entities/ModelVersionTagEntity.java
similarity index 55%
copy from submarine-server/server-core/src/main/java/org/apache/submarine/server/model/database/entities/RegisteredModelNameEntity.java
copy to submarine-server/server-core/src/main/java/org/apache/submarine/server/model/database/entities/ModelVersionTagEntity.java
index b92045b..b7b85f3 100644
--- a/submarine-server/server-core/src/main/java/org/apache/submarine/server/model/database/entities/RegisteredModelNameEntity.java
+++ b/submarine-server/server-core/src/main/java/org/apache/submarine/server/model/database/entities/ModelVersionTagEntity.java
@@ -19,15 +19,13 @@
 
 package org.apache.submarine.server.model.database.entities;
 
-public class RegisteredModelNameEntity {
+public class ModelVersionTagEntity {
 
   private String name;
 
-  private Long createTime;
+  private Integer version;
 
-  private Long lastUpdatedTime;
-
-  private String description;
+  private String tag;
 
   public String getName() {
     return name;
@@ -37,38 +35,29 @@ public class RegisteredModelNameEntity {
     this.name = name;
   }
 
-  public Long getCreateTime() {
-    return createTime;
-  }
-
-  public void setCreateTime(Long createTime) {
-    this.createTime = createTime;
-  }
-
-  public Long getLastUpdatedTime() {
-    return lastUpdatedTime;
+  public Integer getVersion() {
+    return version;
   }
 
-  public void setLastUpdatedTime(Long lastUpdatedTime) {
-    this.lastUpdatedTime = lastUpdatedTime;
+  public void setVersion(Integer version) {
+    this.version = version;
   }
 
-  public String getDescription() {
-    return description;
+  public String getTag() {
+    return tag;
   }
 
-  public void setDescription(String description) {
-    this.description = description;
+  public void setTag(String tag) {
+    this.tag = tag;
   }
 
-  public RegisteredModelNameEntity() {}
+  public ModelVersionTagEntity() {};
 
   public String toString() {
-    return "RegisteredModelNameEntity{" +
-        "name='" + name + '\'' +
-        ", createTime='" + createTime + '\'' +
-        ", lastUpdatedTime=" + lastUpdatedTime + '\'' +
-        ", description='" + description + '\'' +
-        '}';
+    return "ModelVersionEntity{" +
+      "name='" + name + '\'' +
+      ",version='" + version + '\'' +
+      ", tag='" + tag + '\'' +
+      '}';
   }
 }
diff --git a/submarine-server/server-core/src/main/java/org/apache/submarine/server/model/database/entities/RegisteredModelNameEntity.java b/submarine-server/server-core/src/main/java/org/apache/submarine/server/model/database/entities/RegisteredModelEntity.java
similarity index 66%
rename from submarine-server/server-core/src/main/java/org/apache/submarine/server/model/database/entities/RegisteredModelNameEntity.java
rename to submarine-server/server-core/src/main/java/org/apache/submarine/server/model/database/entities/RegisteredModelEntity.java
index b92045b..9bfa016 100644
--- a/submarine-server/server-core/src/main/java/org/apache/submarine/server/model/database/entities/RegisteredModelNameEntity.java
+++ b/submarine-server/server-core/src/main/java/org/apache/submarine/server/model/database/entities/RegisteredModelEntity.java
@@ -19,16 +19,21 @@
 
 package org.apache.submarine.server.model.database.entities;
 
-public class RegisteredModelNameEntity {
+import java.sql.Timestamp;
+import java.util.List;
+
+public class RegisteredModelEntity {
 
   private String name;
 
-  private Long createTime;
+  private Timestamp creationTime;
 
-  private Long lastUpdatedTime;
+  private Timestamp lastUpdatedTime;
 
   private String description;
 
+  private List<String> tags;
+
   public String getName() {
     return name;
   }
@@ -37,19 +42,19 @@ public class RegisteredModelNameEntity {
     this.name = name;
   }
 
-  public Long getCreateTime() {
-    return createTime;
+  public Timestamp getCreationTime() {
+    return creationTime;
   }
 
-  public void setCreateTime(Long createTime) {
-    this.createTime = createTime;
+  public void setCreationTime(Timestamp creationTime) {
+    this.creationTime = creationTime;
   }
 
-  public Long getLastUpdatedTime() {
+  public Timestamp getLastUpdatedTime() {
     return lastUpdatedTime;
   }
 
-  public void setLastUpdatedTime(Long lastUpdatedTime) {
+  public void setLastUpdatedTime(Timestamp lastUpdatedTime) {
     this.lastUpdatedTime = lastUpdatedTime;
   }
 
@@ -61,14 +66,23 @@ public class RegisteredModelNameEntity {
     this.description = description;
   }
 
-  public RegisteredModelNameEntity() {}
+  public List<String> getTags() {
+    return tags;
+  }
+
+  public void setTags(List<String> tags) {
+    this.tags = tags;
+  }
+
+  public RegisteredModelEntity() {}
 
   public String toString() {
-    return "RegisteredModelNameEntity{" +
+    return "RegisteredModelEntity{" +
         "name='" + name + '\'' +
-        ", createTime='" + createTime + '\'' +
+        ", createTime='" + creationTime + '\'' +
         ", lastUpdatedTime=" + lastUpdatedTime + '\'' +
         ", description='" + description + '\'' +
+        ", tags='" + tags + '\'' +
         '}';
   }
 }
diff --git a/submarine-server/server-core/src/main/java/org/apache/submarine/server/model/database/mappers/RegisteredModelNameMapper.java b/submarine-server/server-core/src/main/java/org/apache/submarine/server/model/database/entities/RegisteredModelTagEntity.java
similarity index 59%
copy from submarine-server/server-core/src/main/java/org/apache/submarine/server/model/database/mappers/RegisteredModelNameMapper.java
copy to submarine-server/server-core/src/main/java/org/apache/submarine/server/model/database/entities/RegisteredModelTagEntity.java
index 2ebc53d..c827724 100644
--- a/submarine-server/server-core/src/main/java/org/apache/submarine/server/model/database/mappers/RegisteredModelNameMapper.java
+++ b/submarine-server/server-core/src/main/java/org/apache/submarine/server/model/database/entities/RegisteredModelTagEntity.java
@@ -17,18 +17,36 @@
  * under the License.
  */
 
-package org.apache.submarine.server.model.database.mappers;
+package org.apache.submarine.server.model.database.entities;
 
-import java.util.List;
-import org.apache.submarine.server.model.database.entities.RegisteredModelNameEntity;
+public class RegisteredModelTagEntity {
 
-public interface RegisteredModelNameMapper {
-  List<RegisteredModelNameEntity> selectAll();
-  RegisteredModelNameEntity select(String name);
+  private String name;
 
-  int insert(RegisteredModelNameEntity registeredmodelNameEntity);
-  int update(RegisteredModelNameEntity registeredmodelNameEntity);
-  int delete(String name);
+  private String tag;
 
+  public String getName() {
+    return name;
+  }
 
+  public void setName(String name) {
+    this.name = name;
+  }
+
+  public String getTag() {
+    return tag;
+  }
+
+  public void setTag(String tag) {
+    this.tag = tag;
+  }
+
+  public RegisteredModelTagEntity() {};
+
+  public String toString() {
+    return "ModelVersionEntity{" +
+            "name='" + name + '\'' +
+            ", tag='" + tag + '\'' +
+            '}';
+  }
 }
diff --git a/submarine-server/server-core/src/main/java/org/apache/submarine/server/model/database/mappers/ModelVersionMapper.java b/submarine-server/server-core/src/main/java/org/apache/submarine/server/model/database/mappers/ModelVersionMapper.java
index d39fba8..af7339c 100644
--- a/submarine-server/server-core/src/main/java/org/apache/submarine/server/model/database/mappers/ModelVersionMapper.java
+++ b/submarine-server/server-core/src/main/java/org/apache/submarine/server/model/database/mappers/ModelVersionMapper.java
@@ -20,13 +20,15 @@
 package org.apache.submarine.server.model.database.mappers;
 
 import java.util.List;
+
+import org.apache.ibatis.annotations.Param;
 import org.apache.submarine.server.model.database.entities.ModelVersionEntity;
 
 public interface ModelVersionMapper {
-  List<ModelVersionEntity> list(String name);
-  ModelVersionEntity select(ModelVersionEntity modelVersionEntity);
-
-  int insert(ModelVersionEntity modelVersionEntity);
-  int delete(ModelVersionEntity modelVersionEntity);
-  int deleteAll(String name);
+  List<ModelVersionEntity> selectAllVersions(String name);
+  ModelVersionEntity select(@Param("name") String name, @Param("version") Integer version);
+  ModelVersionEntity selectWithTag(@Param("name") String name, @Param("version") Integer version);
+  void insert(ModelVersionEntity modelVersion);
+  void update(ModelVersionEntity modelVersion);
+  void delete(@Param("name") String name, @Param("version") Integer version);
 }
diff --git a/submarine-server/server-core/src/main/java/org/apache/submarine/server/model/database/mappers/ModelVersionMapper.java b/submarine-server/server-core/src/main/java/org/apache/submarine/server/model/database/mappers/ModelVersionTagMapper.java
similarity index 74%
copy from submarine-server/server-core/src/main/java/org/apache/submarine/server/model/database/mappers/ModelVersionMapper.java
copy to submarine-server/server-core/src/main/java/org/apache/submarine/server/model/database/mappers/ModelVersionTagMapper.java
index d39fba8..7611153 100644
--- a/submarine-server/server-core/src/main/java/org/apache/submarine/server/model/database/mappers/ModelVersionMapper.java
+++ b/submarine-server/server-core/src/main/java/org/apache/submarine/server/model/database/mappers/ModelVersionTagMapper.java
@@ -19,14 +19,10 @@
 
 package org.apache.submarine.server.model.database.mappers;
 
-import java.util.List;
-import org.apache.submarine.server.model.database.entities.ModelVersionEntity;
+import org.apache.submarine.server.model.database.entities.ModelVersionTagEntity;
 
-public interface ModelVersionMapper {
-  List<ModelVersionEntity> list(String name);
-  ModelVersionEntity select(ModelVersionEntity modelVersionEntity);
 
-  int insert(ModelVersionEntity modelVersionEntity);
-  int delete(ModelVersionEntity modelVersionEntity);
-  int deleteAll(String name);
+public interface ModelVersionTagMapper {
+  void insert(ModelVersionTagEntity registeredModelTag);
+  void delete(ModelVersionTagEntity registeredModelTag);
 }
diff --git a/submarine-server/server-core/src/main/java/org/apache/submarine/server/model/database/mappers/RegisteredModelNameMapper.java b/submarine-server/server-core/src/main/java/org/apache/submarine/server/model/database/mappers/RegisteredModelMapper.java
similarity index 66%
copy from submarine-server/server-core/src/main/java/org/apache/submarine/server/model/database/mappers/RegisteredModelNameMapper.java
copy to submarine-server/server-core/src/main/java/org/apache/submarine/server/model/database/mappers/RegisteredModelMapper.java
index 2ebc53d..df107ed 100644
--- a/submarine-server/server-core/src/main/java/org/apache/submarine/server/model/database/mappers/RegisteredModelNameMapper.java
+++ b/submarine-server/server-core/src/main/java/org/apache/submarine/server/model/database/mappers/RegisteredModelMapper.java
@@ -20,15 +20,18 @@
 package org.apache.submarine.server.model.database.mappers;
 
 import java.util.List;
-import org.apache.submarine.server.model.database.entities.RegisteredModelNameEntity;
 
-public interface RegisteredModelNameMapper {
-  List<RegisteredModelNameEntity> selectAll();
-  RegisteredModelNameEntity select(String name);
-
-  int insert(RegisteredModelNameEntity registeredmodelNameEntity);
-  int update(RegisteredModelNameEntity registeredmodelNameEntity);
-  int delete(String name);
+import org.apache.ibatis.annotations.Param;
+import org.apache.submarine.server.model.database.entities.RegisteredModelEntity;
 
+public interface RegisteredModelMapper {
+  List<RegisteredModelEntity> selectAll();
+  RegisteredModelEntity select(String name);
+  RegisteredModelEntity selectWithTag(String name);
 
+  void insert(RegisteredModelEntity registeredModel);
+  void update(RegisteredModelEntity registeredModel);
+  void rename(@Param("name")String name, @Param("newName")String newName);
+  void delete(String name);
+  void deleteAll();
 }
diff --git a/submarine-server/server-core/src/main/java/org/apache/submarine/server/model/database/mappers/RegisteredModelNameMapper.java b/submarine-server/server-core/src/main/java/org/apache/submarine/server/model/database/mappers/RegisteredModelTagMapper.java
similarity index 72%
rename from submarine-server/server-core/src/main/java/org/apache/submarine/server/model/database/mappers/RegisteredModelNameMapper.java
rename to submarine-server/server-core/src/main/java/org/apache/submarine/server/model/database/mappers/RegisteredModelTagMapper.java
index 2ebc53d..0ba67d5 100644
--- a/submarine-server/server-core/src/main/java/org/apache/submarine/server/model/database/mappers/RegisteredModelNameMapper.java
+++ b/submarine-server/server-core/src/main/java/org/apache/submarine/server/model/database/mappers/RegisteredModelTagMapper.java
@@ -19,16 +19,10 @@
 
 package org.apache.submarine.server.model.database.mappers;
 
-import java.util.List;
-import org.apache.submarine.server.model.database.entities.RegisteredModelNameEntity;
-
-public interface RegisteredModelNameMapper {
-  List<RegisteredModelNameEntity> selectAll();
-  RegisteredModelNameEntity select(String name);
-
-  int insert(RegisteredModelNameEntity registeredmodelNameEntity);
-  int update(RegisteredModelNameEntity registeredmodelNameEntity);
-  int delete(String name);
+import org.apache.submarine.server.model.database.entities.RegisteredModelTagEntity;
 
 
+public interface RegisteredModelTagMapper {
+  void insert(RegisteredModelTagEntity registeredModelTag);
+  void delete(RegisteredModelTagEntity registeredModelTag);
 }
diff --git a/submarine-server/server-core/src/main/java/org/apache/submarine/server/model/database/service/ModelService.java b/submarine-server/server-core/src/main/java/org/apache/submarine/server/model/database/service/ModelService.java
deleted file mode 100644
index b0bb750..0000000
--- a/submarine-server/server-core/src/main/java/org/apache/submarine/server/model/database/service/ModelService.java
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.submarine.server.model.database.service;
-
-import org.apache.ibatis.session.SqlSession;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import java.util.List;
-import org.apache.submarine.commons.utils.exception.SubmarineRuntimeException;
-import org.apache.submarine.server.database.utils.ModelBatisUtil;
-import org.apache.submarine.server.model.database.entities.RegisteredModelNameEntity;
-import org.apache.submarine.server.model.database.entities.ModelVersionEntity;
-import org.apache.submarine.server.model.database.mappers.RegisteredModelNameMapper;
-import org.apache.submarine.server.model.database.mappers.ModelVersionMapper;
-
-public class ModelService {
-
-  private static final Logger
-      LOG = LoggerFactory.getLogger(ModelService.class);
-
-  public List<RegisteredModelNameEntity> selectAllRegisteredModelName() throws SubmarineRuntimeException {
-    LOG.info("Registered Model Name selectAll");
-    List<RegisteredModelNameEntity> entities;
-    try (SqlSession sqlSession = ModelBatisUtil.getSqlSession()) {
-      RegisteredModelNameMapper mapper = sqlSession.getMapper(RegisteredModelNameMapper.class);
-      entities = mapper.selectAll();
-      sqlSession.commit();
-    } catch (Exception e) {
-      LOG.error(e.getMessage(), e);
-      throw new SubmarineRuntimeException("Unable to get registered model name entities from database");
-    }
-    return entities;
-  }
-
-  public RegisteredModelNameEntity selectRegisteredModelName(String name) throws SubmarineRuntimeException {
-    LOG.info("Registered Model Name select " + name);
-    RegisteredModelNameEntity entity;
-    try (SqlSession sqlSession = ModelBatisUtil.getSqlSession()) {
-      RegisteredModelNameMapper mapper = sqlSession.getMapper(RegisteredModelNameMapper.class);
-      entity = mapper.select(name);
-      sqlSession.commit();
-    } catch (Exception e) {
-      LOG.error(e.getMessage(), e);
-      throw new SubmarineRuntimeException("Unable to get registered model name entity from database");
-    }
-    return entity;
-  }
-
-  public boolean insertRegisteredModelName(RegisteredModelNameEntity entity)
-      throws SubmarineRuntimeException {
-    LOG.info("Registered Model Name insert " + entity.getName());
-    try (SqlSession sqlSession = ModelBatisUtil.getSqlSession()) {
-      RegisteredModelNameMapper mapper = sqlSession.getMapper(RegisteredModelNameMapper.class);
-      mapper.insert(entity);
-      sqlSession.commit();
-    } catch (Exception e) {
-      LOG.error(e.getMessage(), e);
-      throw new SubmarineRuntimeException("Unable to insert registered model name entity from database");
-    }
-    return true;
-  }
-
-  public boolean updateRegisteredModelName(RegisteredModelNameEntity entity)
-      throws SubmarineRuntimeException {
-    LOG.info("Registered Model Name update " + entity.getName());
-    try (SqlSession sqlSession = ModelBatisUtil.getSqlSession()) {
-      RegisteredModelNameMapper mapper = sqlSession.getMapper(RegisteredModelNameMapper.class);
-      mapper.update(entity);
-      sqlSession.commit();
-    } catch (Exception e) {
-      LOG.error(e.getMessage(), e);
-      throw new SubmarineRuntimeException("Unable to update registered model name entity from database");
-    }
-    return true;
-  }
-
-  public boolean deleteRegisteredModelName(String name) throws SubmarineRuntimeException {
-    LOG.info("Registered Model Name delete " + name);
-    try (SqlSession sqlSession = ModelBatisUtil.getSqlSession()) {
-      RegisteredModelNameMapper mapper = sqlSession.getMapper(RegisteredModelNameMapper.class);
-      mapper.delete(name);
-      sqlSession.commit();
-    } catch (Exception e) {
-      LOG.error(e.getMessage(), e);
-      throw new SubmarineRuntimeException("Unable to delete registered model name entity from database");
-    }
-    return true;
-  }
-
-  public List<ModelVersionEntity> listModelVersion(String name) throws SubmarineRuntimeException {
-    LOG.info("Model Version list " + name);
-    List<ModelVersionEntity> entities;
-    try (SqlSession sqlSession = ModelBatisUtil.getSqlSession()) {
-      ModelVersionMapper mapper = sqlSession.getMapper(ModelVersionMapper.class);
-      entities = mapper.list(name);
-      sqlSession.commit();
-    } catch (Exception e) {
-      LOG.error(e.getMessage(), e);
-      throw new SubmarineRuntimeException("Unable to get model version entities from database");
-    }
-    return entities;
-  }
-
-  public ModelVersionEntity selectModelVersion(String name, Integer version)
-      throws SubmarineRuntimeException {
-    LOG.info("Model Version select " + name + " " + version.toString());
-    ModelVersionEntity entity = new ModelVersionEntity();
-    entity.setName(name);
-    entity.setVersion(version);
-    try (SqlSession sqlSession = ModelBatisUtil.getSqlSession()) {
-      ModelVersionMapper mapper = sqlSession.getMapper(ModelVersionMapper.class);
-      entity = mapper.select(entity);
-      sqlSession.commit();
-    } catch (Exception e) {
-      LOG.error(e.getMessage(), e);
-      throw new SubmarineRuntimeException("Unable to get model version entity from database");
-    }
-    return entity;
-  }
-
-  public boolean insertModelVersion(ModelVersionEntity entity) throws SubmarineRuntimeException {
-    LOG.info("Model Version insert " + entity.getName());
-    try (SqlSession sqlSession = ModelBatisUtil.getSqlSession()) {
-      ModelVersionMapper mapper = sqlSession.getMapper(ModelVersionMapper.class);
-      mapper.insert(entity);
-      sqlSession.commit();
-    } catch (Exception e) {
-      LOG.error(e.getMessage(), e);
-      throw new SubmarineRuntimeException("Unable to insert model version entity from database");
-    }
-    return true;
-  }
-
-
-  public boolean deleteModelVersion(String name, Integer version) throws SubmarineRuntimeException {
-    LOG.info("Model Version delete " + name + " " + version.toString());
-    ModelVersionEntity entity = new ModelVersionEntity();
-    entity.setName(name);
-    entity.setVersion(version);
-    try (SqlSession sqlSession = ModelBatisUtil.getSqlSession()) {
-      ModelVersionMapper mapper = sqlSession.getMapper(ModelVersionMapper.class);
-      mapper.delete(entity);
-      sqlSession.commit();
-    } catch (Exception e) {
-      LOG.error(e.getMessage(), e);
-      throw new SubmarineRuntimeException("Unable to delete model version entity from database");
-    }
-    return true;
-  }
-
-  public boolean deleteAllModelVersion(String name) throws SubmarineRuntimeException {
-    LOG.info("Model Version delete all " + name);
-    try (SqlSession sqlSession = ModelBatisUtil.getSqlSession()) {
-      ModelVersionMapper mapper = sqlSession.getMapper(ModelVersionMapper.class);
-      mapper.deleteAll(name);
-      sqlSession.commit();
-    } catch (Exception e) {
-      LOG.error(e.getMessage(), e);
-      throw new SubmarineRuntimeException("Unable to delete model version entity from database");
-    }
-    return true;
-  }
-
-}
diff --git a/submarine-server/server-core/src/main/java/org/apache/submarine/server/model/database/service/ModelVersionService.java b/submarine-server/server-core/src/main/java/org/apache/submarine/server/model/database/service/ModelVersionService.java
new file mode 100644
index 0000000..8588a2e
--- /dev/null
+++ b/submarine-server/server-core/src/main/java/org/apache/submarine/server/model/database/service/ModelVersionService.java
@@ -0,0 +1,112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.submarine.server.model.database.service;
+
+import org.apache.ibatis.session.SqlSession;
+import org.apache.submarine.commons.utils.exception.SubmarineRuntimeException;
+import org.apache.submarine.server.database.utils.MyBatisUtil;
+import org.apache.submarine.server.model.database.entities.ModelVersionEntity;
+import org.apache.submarine.server.model.database.mappers.ModelVersionMapper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+
+public class ModelVersionService {
+
+  private static final Logger LOG = LoggerFactory.getLogger(ModelVersionService.class);
+
+  public List<ModelVersionEntity> selectAllVersions(String name) throws SubmarineRuntimeException {
+    LOG.info("Model Version select all versions:" + name);
+    List<ModelVersionEntity> modelVersionEntities;
+    try (SqlSession sqlSession = MyBatisUtil.getSqlSession()) {
+      ModelVersionMapper mapper = sqlSession.getMapper(ModelVersionMapper.class);
+      modelVersionEntities = mapper.selectAllVersions(name);
+      sqlSession.commit();
+    } catch (Exception e) {
+      LOG.error(e.getMessage(), e);
+      throw new SubmarineRuntimeException("Unable to get model version from database");
+    }
+    return modelVersionEntities;
+  }
+
+  public ModelVersionEntity select(String name, Integer version) throws SubmarineRuntimeException {
+    LOG.info("Model Version select:" + name + " " + version.toString());
+    ModelVersionEntity modelVersionEntity;
+    try (SqlSession sqlSession = MyBatisUtil.getSqlSession()) {
+      ModelVersionMapper mapper = sqlSession.getMapper(ModelVersionMapper.class);
+      modelVersionEntity = mapper.select(name, version);
+      sqlSession.commit();
+    } catch (Exception e) {
+      LOG.error(e.getMessage(), e);
+      throw new SubmarineRuntimeException("Unable to get model version from database");
+    }
+    return modelVersionEntity;
+  }
+  public ModelVersionEntity selectWithTag(String name, Integer version) throws SubmarineRuntimeException {
+    LOG.info("Model Version select with tag:" + name + " " + version.toString());
+    ModelVersionEntity modelVersionEntity;
+    try (SqlSession sqlSession = MyBatisUtil.getSqlSession()) {
+      ModelVersionMapper mapper = sqlSession.getMapper(ModelVersionMapper.class);
+      modelVersionEntity = mapper.selectWithTag(name, version);
+      sqlSession.commit();
+    } catch (Exception e) {
+      LOG.error(e.getMessage(), e);
+      throw new SubmarineRuntimeException("Unable to get model version from database");
+    }
+    return modelVersionEntity;
+  }
+
+  public void insert(ModelVersionEntity modelVersion) throws SubmarineRuntimeException {
+    LOG.info("Model Version insert " + modelVersion.getName());
+    try (SqlSession sqlSession = MyBatisUtil.getSqlSession()) {
+      ModelVersionMapper mapper = sqlSession.getMapper(ModelVersionMapper.class);
+      mapper.insert(modelVersion);
+      sqlSession.commit();
+    } catch (Exception e) {
+      LOG.error(e.getMessage(), e);
+      throw new SubmarineRuntimeException("Unable to insert model version from database");
+    }
+  }
+
+  public void update(ModelVersionEntity modelVersion) throws SubmarineRuntimeException {
+    LOG.info("Model Version update " + modelVersion.getName());
+    try (SqlSession sqlSession = MyBatisUtil.getSqlSession()) {
+      ModelVersionMapper mapper = sqlSession.getMapper(ModelVersionMapper.class);
+      mapper.update(modelVersion);
+      sqlSession.commit();
+    } catch (Exception e) {
+      LOG.error(e.getMessage(), e);
+      throw new SubmarineRuntimeException("Unable to update model version from database");
+    }
+  }
+
+  public void delete(String name, Integer version) throws SubmarineRuntimeException {
+    LOG.info("Model Version delete name:" + name + ", version:" + version.toString());
+    try (SqlSession sqlSession = MyBatisUtil.getSqlSession()) {
+      ModelVersionMapper mapper = sqlSession.getMapper(ModelVersionMapper.class);
+      mapper.delete(name, version);
+      sqlSession.commit();
+    } catch (Exception e) {
+      LOG.error(e.getMessage(), e);
+      throw new SubmarineRuntimeException("Unable to delete model version from database");
+    }
+  }
+}
diff --git a/submarine-server/server-core/src/main/java/org/apache/submarine/server/model/database/service/ModelVersionTagService.java b/submarine-server/server-core/src/main/java/org/apache/submarine/server/model/database/service/ModelVersionTagService.java
new file mode 100644
index 0000000..937fcf8
--- /dev/null
+++ b/submarine-server/server-core/src/main/java/org/apache/submarine/server/model/database/service/ModelVersionTagService.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.submarine.server.model.database.service;
+
+import org.apache.ibatis.session.SqlSession;
+import org.apache.submarine.commons.utils.exception.SubmarineRuntimeException;
+import org.apache.submarine.server.database.utils.MyBatisUtil;
+import org.apache.submarine.server.model.database.entities.ModelVersionTagEntity;
+import org.apache.submarine.server.model.database.mappers.ModelVersionTagMapper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ModelVersionTagService {
+
+  private static final Logger LOG = LoggerFactory.getLogger(ModelVersionTagService.class);
+
+  public void insert(ModelVersionTagEntity modelVersionTag)
+          throws SubmarineRuntimeException {
+    LOG.info("Model Version Tag insert name:" + modelVersionTag.getName() + ", tag:" +
+            modelVersionTag.getTag());
+    try (SqlSession sqlSession = MyBatisUtil.getSqlSession()) {
+      ModelVersionTagMapper mapper = sqlSession.getMapper(ModelVersionTagMapper.class);
+      mapper.insert(modelVersionTag);
+      sqlSession.commit();
+    } catch (Exception e) {
+      LOG.error(e.getMessage(), e);
+      throw new SubmarineRuntimeException("Unable to insert model version tag entity to database");
+    }
+  }
+
+  public void delete(ModelVersionTagEntity modelVersionTag)
+          throws SubmarineRuntimeException {
+    LOG.info("Model Version Tag delete name:" + modelVersionTag.getName() + ", tag:" +
+            modelVersionTag.getTag());
+    try (SqlSession sqlSession = MyBatisUtil.getSqlSession()) {
+      ModelVersionTagMapper mapper = sqlSession.getMapper(ModelVersionTagMapper.class);
+      mapper.delete(modelVersionTag);
+      sqlSession.commit();
+    } catch (Exception e) {
+      LOG.error(e.getMessage(), e);
+      throw new SubmarineRuntimeException("Unable to delete model version tag entity to database");
+    }
+  }
+}
diff --git a/submarine-server/server-core/src/main/java/org/apache/submarine/server/model/database/service/RegisteredModelService.java b/submarine-server/server-core/src/main/java/org/apache/submarine/server/model/database/service/RegisteredModelService.java
new file mode 100644
index 0000000..02dae36
--- /dev/null
+++ b/submarine-server/server-core/src/main/java/org/apache/submarine/server/model/database/service/RegisteredModelService.java
@@ -0,0 +1,137 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.submarine.server.model.database.service;
+
+import org.apache.ibatis.session.SqlSession;
+import org.apache.submarine.commons.runtime.exception.SubmarineRuntimeException;
+import org.apache.submarine.server.database.utils.MyBatisUtil;
+import org.apache.submarine.server.model.database.entities.RegisteredModelEntity;
+import org.apache.submarine.server.model.database.mappers.RegisteredModelMapper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+
+public class RegisteredModelService {
+
+  private static final Logger LOG = LoggerFactory.getLogger(RegisteredModelService.class);
+
+  public List<RegisteredModelEntity> selectAll() throws SubmarineRuntimeException {
+    LOG.info("Registered model selectAll");
+    List<RegisteredModelEntity> registeredModels;
+    try (SqlSession sqlSession = MyBatisUtil.getSqlSession()) {
+      RegisteredModelMapper mapper = sqlSession.getMapper(RegisteredModelMapper.class);
+      registeredModels = mapper.selectAll();
+      sqlSession.commit();
+    } catch (Exception e) {
+      LOG.error(e.getMessage(), e);
+      throw new SubmarineRuntimeException("Unable to get registered models from database");
+    }
+    return registeredModels;
+  }
+
+  public RegisteredModelEntity select(String name) throws SubmarineRuntimeException {
+    LOG.info("Registered Model select:" + name);
+    RegisteredModelEntity registeredModel;
+    try (SqlSession sqlSession = MyBatisUtil.getSqlSession()) {
+      RegisteredModelMapper mapper = sqlSession.getMapper(RegisteredModelMapper.class);
+      registeredModel = mapper.select(name);
+      sqlSession.commit();
+    } catch (Exception e) {
+      LOG.error(e.getMessage(), e);
+      throw new SubmarineRuntimeException("Unable to get registered model name entity from database");
+    }
+    return registeredModel;
+  }
+
+  public RegisteredModelEntity selectWithTag(String name) throws SubmarineRuntimeException {
+    LOG.info("Registered Model select with tag:" + name);
+    RegisteredModelEntity registeredModel;
+    try (SqlSession sqlSession = MyBatisUtil.getSqlSession()) {
+      RegisteredModelMapper mapper = sqlSession.getMapper(RegisteredModelMapper.class);
+      registeredModel = mapper.selectWithTag(name);
+      sqlSession.commit();
+    } catch (Exception e) {
+      LOG.error(e.getMessage(), e);
+      throw new SubmarineRuntimeException("Unable to get registered model name entity from database");
+    }
+    return registeredModel;
+  }
+
+  public void insert(RegisteredModelEntity registeredModel) throws SubmarineRuntimeException {
+    LOG.info("Registered Model insert " + registeredModel.getName());
+    try (SqlSession sqlSession = MyBatisUtil.getSqlSession()) {
+      RegisteredModelMapper mapper = sqlSession.getMapper(RegisteredModelMapper.class);
+      mapper.insert(registeredModel);
+      sqlSession.commit();
+    } catch (Exception e) {
+      LOG.error(e.getMessage(), e);
+      throw new SubmarineRuntimeException("Unable to insert registered model name entity to database");
+    }
+  }
+
+  public void update(RegisteredModelEntity registeredModel) throws SubmarineRuntimeException {
+    LOG.info("Registered Model update " + registeredModel.getName());
+    try (SqlSession sqlSession = MyBatisUtil.getSqlSession()) {
+      RegisteredModelMapper mapper = sqlSession.getMapper(RegisteredModelMapper.class);
+      mapper.update(registeredModel);
+      sqlSession.commit();
+    } catch (Exception e) {
+      LOG.error(e.getMessage(), e);
+      throw new SubmarineRuntimeException("Unable to update registered model name entity from database");
+    }
+  }
+
+  public void rename(String name, String newName) throws SubmarineRuntimeException {
+    LOG.info("Registered Model rename");
+    try (SqlSession sqlSession = MyBatisUtil.getSqlSession()) {
+      RegisteredModelMapper mapper = sqlSession.getMapper(RegisteredModelMapper.class);
+      mapper.rename(name, newName);
+      sqlSession.commit();
+    } catch (Exception e) {
+      LOG.error(e.getMessage(), e);
+      throw new SubmarineRuntimeException("Unable to rename registered model name from database");
+    }
+  }
+
+  public void delete(String name) throws SubmarineRuntimeException {
+    LOG.info("Registered Model delete " + name);
+    try (SqlSession sqlSession = MyBatisUtil.getSqlSession()) {
+      RegisteredModelMapper mapper = sqlSession.getMapper(RegisteredModelMapper.class);
+      mapper.delete(name);
+      sqlSession.commit();
+    } catch (Exception e) {
+      LOG.error(e.getMessage(), e);
+      throw new SubmarineRuntimeException("Unable to delete registered model entity from database");
+    }
+  }
+
+  public void deleteAll() throws SubmarineRuntimeException {
+    LOG.info("Registered Model delete all");
+    try (SqlSession sqlSession = MyBatisUtil.getSqlSession()) {
+      RegisteredModelMapper mapper = sqlSession.getMapper(RegisteredModelMapper.class);
+      mapper.deleteAll();
+      sqlSession.commit();
+    } catch (Exception e) {
+      LOG.error(e.getMessage(), e);
+      throw new SubmarineRuntimeException("Unable to delete all registered model entities from database");
+    }
+  }
+}
diff --git a/submarine-server/server-core/src/main/java/org/apache/submarine/server/model/database/service/RegisteredModelTagService.java b/submarine-server/server-core/src/main/java/org/apache/submarine/server/model/database/service/RegisteredModelTagService.java
new file mode 100644
index 0000000..400f764
--- /dev/null
+++ b/submarine-server/server-core/src/main/java/org/apache/submarine/server/model/database/service/RegisteredModelTagService.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.submarine.server.model.database.service;
+
+import org.apache.ibatis.session.SqlSession;
+import org.apache.submarine.commons.utils.exception.SubmarineRuntimeException;
+import org.apache.submarine.server.database.utils.MyBatisUtil;
+import org.apache.submarine.server.model.database.entities.RegisteredModelTagEntity;
+import org.apache.submarine.server.model.database.mappers.RegisteredModelTagMapper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class RegisteredModelTagService {
+
+  private static final Logger LOG = LoggerFactory.getLogger(RegisteredModelTagService.class);
+
+  public void insert(RegisteredModelTagEntity registeredModelTag)
+          throws SubmarineRuntimeException {
+    LOG.info("Registered Model Tag insert name:" + registeredModelTag.getName() + ", tag:" +
+            registeredModelTag.getTag());
+    try (SqlSession sqlSession = MyBatisUtil.getSqlSession()) {
+      RegisteredModelTagMapper mapper = sqlSession.getMapper(RegisteredModelTagMapper.class);
+      mapper.insert(registeredModelTag);
+      sqlSession.commit();
+    } catch (Exception e) {
+      LOG.error(e.getMessage(), e);
+      throw new SubmarineRuntimeException("Unable to insert registered model tag entity to database");
+    }
+  }
+
+  public void delete(RegisteredModelTagEntity registeredModelTag)
+          throws SubmarineRuntimeException {
+    LOG.info("Registered Model Tag delete name:" + registeredModelTag.getName() + ", tag:" +
+            registeredModelTag.getTag());
+    try (SqlSession sqlSession = MyBatisUtil.getSqlSession()) {
+      RegisteredModelTagMapper mapper = sqlSession.getMapper(RegisteredModelTagMapper.class);
+      mapper.delete(registeredModelTag);
+      sqlSession.commit();
+    } catch (Exception e) {
+      LOG.error(e.getMessage(), e);
+      throw new SubmarineRuntimeException("Unable to delete registered model tag from database");
+    }
+  }
+}
diff --git a/submarine-server/server-core/src/main/resources/mybatis-config.xml b/submarine-server/server-core/src/main/resources/mybatis-config.xml
index e251084..ecdc40b 100755
--- a/submarine-server/server-core/src/main/resources/mybatis-config.xml
+++ b/submarine-server/server-core/src/main/resources/mybatis-config.xml
@@ -70,5 +70,9 @@
     <mapper resource='org/apache/submarine/database/mappers/ExperimentTemplateMapper.xml'/>
     <mapper resource='org/apache/submarine/database/mappers/ExperimentMapper.xml'/>
     <mapper resource='org/apache/submarine/database/mappers/NotebookMapper.xml'/>
+    <mapper resource='org/apache/submarine/database/mappers/RegisteredModelMapper.xml'/>
+    <mapper resource='org/apache/submarine/database/mappers/RegisteredModelTagMapper.xml'/>
+    <mapper resource="org/apache/submarine/database/mappers/ModelVersionMapper.xml" />
+    <mapper resource="org/apache/submarine/database/mappers/ModelVersionTagMapper.xml" />
   </mappers>
 </configuration>
diff --git a/submarine-server/server-core/src/main/resources/org/apache/submarine/database/mappers/ModelVersionMapper.xml b/submarine-server/server-core/src/main/resources/org/apache/submarine/database/mappers/ModelVersionMapper.xml
index 9344f71..eda962e 100644
--- a/submarine-server/server-core/src/main/resources/org/apache/submarine/database/mappers/ModelVersionMapper.xml
+++ b/submarine-server/server-core/src/main/resources/org/apache/submarine/database/mappers/ModelVersionMapper.xml
@@ -22,54 +22,91 @@
   <resultMap id="resultMap" type="org.apache.submarine.server.model.database.entities.ModelVersionEntity">
     <result column="name" property="name" />
     <result column="version" property="version" />
-    <result column="creation_time" property="createTime" />
+    <result column="source" property="source" />
+    <result column="user_id" property="userId" />
+    <result column="experiment_id" property="experimentId" />
+    <result column="current_stage" property="currentStage" />
+    <result column="creation_time" property="creationTime" />
     <result column="last_updated_time" property="lastUpdatedTime" />
+    <result column="dataset" property="dataset" />
     <result column="description" property="description" />
+  </resultMap>
+
+  <resultMap id="resultMapWithTag" type="org.apache.submarine.server.model.database.entities.ModelVersionEntity">
+    <result column="name" property="name" />
+    <result column="version" property="version" />
+    <result column="source" property="source" />
     <result column="user_id" property="userId" />
+    <result column="experiment_id" property="experimentId" />
     <result column="current_stage" property="currentStage" />
-    <result column="source" property="source" />
-    <result column="run_id" property="runId" />
-    <result column="status" property="status" />
-    <result column="status_message" property="statusMessage" />
-    <result column="run_link" property="runLink" />
+    <result column="creation_time" property="creationTime" />
+    <result column="last_updated_time" property="lastUpdatedTime" />
+    <result column="dataset" property="dataset" />
+    <result column="description" property="description" />
+    <collection property="tags" column="name" ofType="java.lang.String">
+      <result column="tag" property="tag" />
+    </collection>
   </resultMap>
 
   <sql id="Base_Column_List">
-    name, version, creation_time, last_updated_time, description, user_id, current_stage,
-    source, run_id, status, status_message, run_link
+    name, version, source, user_id, experiment_id, current_stage, creation_time,
+    last_updated_time, dataset, description
   </sql>
 
-  <select id="list" parameterType="java.lang.String" resultMap="resultMap">
+  <select id="select" resultMap="resultMap">
     select
     <include refid="Base_Column_List" />
-    from model_versions
-    where name = #{name,jdbcType=VARCHAR}
+    from model_version
+    where name = #{name} and version = #{version}
   </select>
 
-  <select id="select" parameterType="org.apache.submarine.server.model.database.entities.ModelVersionEntity" resultMap="resultMap">
-    select
-    <include refid="Base_Column_List" />
-    from model_versions
-    where name = #{name,jdbcType=VARCHAR} and version = #{version,jdbcType=INTEGER}
+  <select id="selectWithTag" resultMap="resultMapWithTag">
+    select *
+    from model_version mv
+    left join model_version_tag tag on tag.name = mv.name and tag.version = mv.version
+    where mv.name = #{name,jdbcType=VARCHAR} and mv.version = #{version}
   </select>
 
-  <delete id="delete" parameterType="org.apache.submarine.server.model.database.entities.ModelVersionEntity">
-    delete from model_versions
-    where name = #{name,jdbcType=VARCHAR} and version = #{version,jdbcType=INTEGER}
-  </delete>
-
-  <delete id="deleteAll" parameterType="java.lang.String">
-    delete from model_versions
-    where name = #{name,jdbcType=VARCHAR}
-  </delete>
+  <select id="selectAllVersions" resultMap="resultMapWithTag">
+    select *
+    from model_version mv
+           left join model_version_tag tag on tag.name = mv.name and tag.version = mv.version
+    where mv.name = #{name,jdbcType=VARCHAR}
+  </select>
 
   <insert id="insert" parameterType="org.apache.submarine.server.model.database.entities.ModelVersionEntity">
-    insert into model_versions (name, version, creation_time, last_updated_time, description, user_id,
-                                current_stage, source, run_id, status, status_message, run_link)
-    values (#{name,jdbcType=VARCHAR}, #{version,jdbcType=INTEGER}, now(), now(),
-            #{description,jdbcType=VARCHAR}, #{userId,jdbcType=VARCHAR}, #{currentStage,jdbcType=VARCHAR},
-            #{source,jdbcType=VARCHAR}, #{runId,jdbcType=VARCHAR}, #{status,jdbcType=VARCHAR},
-            #{statusMessage,jdbcType=VARCHAR}, #{runLink,jdbcType=VARCHAR})
+    insert into model_version (name, version, source, user_id, experiment_id, current_stage, creation_time, last_updated_time, dataset, description)
+    values (#{name,jdbcType=VARCHAR}, #{version,jdbcType=INTEGER}, #{source,jdbcType=VARCHAR},
+    #{userId,jdbcType=VARCHAR}, #{experimentId,jdbcType=VARCHAR}, #{currentStage,jdbcType=VARCHAR},
+    NOW(3), NOW(3), #{dataset,jdbcType=VARCHAR}, #{description,jdbcType=VARCHAR});
+    <if test="tags != null and !tags.isEmpty()">
+      insert INTO model_version_tag (name, version, tag) values
+      <foreach collection="tags" item="tag" index="index" separator=",">
+        (#{name},#{version},#{tag})
+      </foreach>
+    </if>
   </insert>
 
+  <update id="update" parameterType="org.apache.submarine.server.model.database.entities.ModelVersionEntity">
+    update model_version
+    <set>
+      <if test="currentStage != null">
+        current_stage = #{currentStage,jdbcType=VARCHAR},
+      </if>
+      <if test="dataset != null">
+        dataset = #{dataset,jdbcType=VARCHAR},
+      </if>
+      <if test="description != null">
+        description = #{description,jdbcType=VARCHAR},
+      </if>
+      last_updated_time = NOW(3)
+    </set>
+    where name = #{name, jdbcType=VARCHAR} and version = #{version, jdbcType=INTEGER}
+  </update>
+
+  <delete id="delete">
+    delete from model_version
+    where name = #{name,jdbcType=VARCHAR} and version = #{version,jdbcType=INTEGER}
+  </delete>
+
 </mapper>
diff --git a/submarine-server/server-core/src/main/resources/org/apache/submarine/database/mappers/ModelVersionTagMapper.xml b/submarine-server/server-core/src/main/resources/org/apache/submarine/database/mappers/ModelVersionTagMapper.xml
new file mode 100644
index 0000000..a76f4ee
--- /dev/null
+++ b/submarine-server/server-core/src/main/resources/org/apache/submarine/database/mappers/ModelVersionTagMapper.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="org.apache.submarine.server.model.database.mappers.ModelVersionTagMapper">
+  <resultMap id="resultMap" type="org.apache.submarine.server.model.database.entities.ModelVersionTagEntity">
+    <result column="name" property="name" />
+    <result column="tag" property="tag" />
+  </resultMap>
+
+  <sql id="Base_Column_List">
+    name, tag
+  </sql>
+
+  <delete id="delete" parameterType="java.lang.String">
+    delete from model_version_tag
+    where name = #{name,jdbcType=VARCHAR} AND tag = #{tag,jdbcType=VARCHAR}
+  </delete>
+
+  <insert id="insert" parameterType="org.apache.submarine.server.model.database.entities.ModelVersionTagEntity">
+    insert into model_version_tag (name, version, tag)
+    values (#{name,jdbcType=VARCHAR}, #{version,jdbcType=INTEGER}, #{tag,jdbcType=VARCHAR})
+  </insert>
+
+</mapper>
diff --git a/submarine-server/server-core/src/main/resources/org/apache/submarine/database/mappers/RegisteredModelMapper.xml b/submarine-server/server-core/src/main/resources/org/apache/submarine/database/mappers/RegisteredModelMapper.xml
new file mode 100644
index 0000000..6c5ecb4
--- /dev/null
+++ b/submarine-server/server-core/src/main/resources/org/apache/submarine/database/mappers/RegisteredModelMapper.xml
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="org.apache.submarine.server.model.database.mappers.RegisteredModelMapper">
+  <resultMap id="RegisteredModelTagMap" type="org.apache.submarine.server.model.database.entities.RegisteredModelTagEntity">
+    <result column="name" property="name" />
+    <result column="tag" property="tag" />
+  </resultMap>
+
+  <resultMap id="resultMap" type="org.apache.submarine.server.model.database.entities.RegisteredModelEntity">
+    <result column="name" property="name" />
+    <result column="creation_time" property="creationTime" />
+    <result column="last_updated_time" property="lastUpdatedTime" />
+    <result column="description" property="description" />
+  </resultMap>
+
+  <resultMap id="resultMapWithTag" type="org.apache.submarine.server.model.database.entities.RegisteredModelEntity">
+    <result column="name" property="name" />
+    <result column="creation_time" property="creationTime" />
+    <result column="last_updated_time" property="lastUpdatedTime" />
+    <result column="description" property="description" />
+    <collection property="tags" column="name" ofType="java.lang.String">
+      <result column="tag" property="tag" />
+    </collection>
+  </resultMap>
+
+  <sql id="Base_Column_List">
+    name, creation_time, last_updated_time, description
+  </sql>
+
+  <select id="select" parameterType="java.lang.String" resultMap="resultMap">
+    select
+    <include refid="Base_Column_List" />
+    from registered_model
+    where name = #{name,jdbcType=VARCHAR}
+  </select>
+
+  <select id="selectWithTag" parameterType="java.lang.String" resultMap="resultMapWithTag">
+    select *
+    from registered_model rm left join registered_model_tag tag on tag.name = #{name}
+    where rm.name = #{name,jdbcType=VARCHAR}
+  </select>
+
+  <select id="selectAll" resultMap="resultMapWithTag">
+    select *
+    from registered_model rm left join registered_model_tag tag on tag.name = rm.name
+  </select>
+
+  <insert id="insert" parameterType="org.apache.submarine.server.model.database.entities.RegisteredModelEntity">
+    insert into registered_model (name, creation_time, last_updated_time, description)
+    values (#{name,jdbcType=VARCHAR}, NOW(3), NOW(3), #{description,jdbcType=VARCHAR});
+    <if test="tags != null and !tags.isEmpty()">
+      insert INTO registered_model_tag (name, tag) values
+      <foreach collection="tags" item="tag" index="index" separator=",">
+        (#{name},#{tag})
+      </foreach>
+    </if>
+  </insert>
+
+  <update id="update" parameterType="org.apache.submarine.server.model.database.entities.RegisteredModelEntity">
+    update registered_model
+    <set>
+      <if test="description != null">
+        description = #{description,jdbcType=VARCHAR},
+      </if>
+      last_updated_time = NOW(3)
+    </set>
+    where name = #{name,jdbcType=VARCHAR}
+  </update>
+
+  <update id="rename">
+    update registered_model
+    <set>
+      last_updated_time = NOW(3),
+      name = #{newName,jdbcType=VARCHAR}
+    </set>
+    where name = #{name,jdbcType=VARCHAR}
+  </update>
+
+  <delete id="delete" parameterType="java.lang.String">
+    delete from registered_model
+    where name = #{name,jdbcType=VARCHAR};
+  </delete>
+
+  <delete id="deleteAll" parameterType="java.lang.String">
+    delete from registered_model;
+  </delete>
+
+</mapper>
diff --git a/submarine-server/server-core/src/main/resources/org/apache/submarine/database/mappers/RegisteredModelNameMapper.xml b/submarine-server/server-core/src/main/resources/org/apache/submarine/database/mappers/RegisteredModelNameMapper.xml
deleted file mode 100644
index 1ea332a..0000000
--- a/submarine-server/server-core/src/main/resources/org/apache/submarine/database/mappers/RegisteredModelNameMapper.xml
+++ /dev/null
@@ -1,68 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  Licensed to the Apache Software Foundation (ASF) under one
-  or more contributor license agreements.  See the NOTICE file
-  distributed with this work for additional information
-  regarding copyright ownership.  The ASF licenses this file
-  to you under the Apache License, Version 2.0 (the
-  "License"); you may not use this file except in compliance
-  with the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-  Unless required by applicable law or agreed to in writing,
-  software distributed under the License is distributed on an
-  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-  KIND, either express or implied.  See the License for the
-  specific language governing permissions and limitations
-  under the License.
--->
-<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="org.apache.submarine.server.model.database.mappers.RegisteredModelNameMapper">
-  <resultMap id="resultMap" type="org.apache.submarine.server.model.database.entities.RegisteredModelNameEntity">
-    <result column="name" property="name" />
-    <result column="creation_time" property="createTime" />
-    <result column="last_updated_time" property="lastUpdatedTime" />
-    <result column="description" property="description" />
-  </resultMap>
-
-  <sql id="Base_Column_List">
-    name, creation_time, last_updated_time, description
-  </sql>
-
-  <select id="selectAll" resultMap="resultMap">
-    select
-    <include refid="Base_Column_List" />
-    from registered_models
-  </select>
-
-  <select id="select" parameterType="java.lang.String" resultMap="resultMap">
-    select
-    <include refid="Base_Column_List" />
-    from registered_models
-    where name = #{name,jdbcType=VARCHAR}
-  </select>
-
-  <delete id="delete" parameterType="java.lang.String">
-    delete from registered_models
-    where name = #{name,jdbcType=VARCHAR}
-  </delete>
-
-  <insert id="insert" parameterType="org.apache.submarine.server.model.database.entities.RegisteredModelNameEntity">
-    insert into registered_models (name, creation_time, last_updated_time, description)
-    values (#{name,jdbcType=VARCHAR}, now(), now(), #{description,jdbcType=VARCHAR})
-  </insert>
-
-  <update id="update" parameterType="org.apache.submarine.server.model.database.entities.RegisteredModelNameEntity">
-    update registered_models
-    <set>
-      <if test="description != null">
-        description = #{description,jdbcType=VARCHAR},
-      </if>
-      last_updated_time = now()
-    </set>
-    where name = #{name,jdbcType=VARCHAR}
-  </update>
-
-
-</mapper>
diff --git a/submarine-server/server-core/src/main/resources/org/apache/submarine/database/mappers/RegisteredModelTagMapper.xml b/submarine-server/server-core/src/main/resources/org/apache/submarine/database/mappers/RegisteredModelTagMapper.xml
new file mode 100644
index 0000000..b9993c3
--- /dev/null
+++ b/submarine-server/server-core/src/main/resources/org/apache/submarine/database/mappers/RegisteredModelTagMapper.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="org.apache.submarine.server.model.database.mappers.RegisteredModelTagMapper">
+  <resultMap id="resultMap" type="org.apache.submarine.server.model.database.entities.RegisteredModelTagEntity">
+    <result column="name" property="name" />
+    <result column="tag" property="tag" />
+  </resultMap>
+
+  <sql id="Base_Column_List">
+    name, tag
+  </sql>
+
+  <delete id="delete" parameterType="org.apache.submarine.server.model.database.entities.RegisteredModelTagEntity">
+    delete from registered_model_tag
+    where name = #{name,jdbcType=VARCHAR} AND tag = #{tag,jdbcType=VARCHAR}
+  </delete>
+
+  <insert id="insert" parameterType="org.apache.submarine.server.model.database.entities.RegisteredModelTagEntity">
+    insert into registered_model_tag (name, tag)
+    values (#{name,jdbcType=VARCHAR}, #{tag,jdbcType=VARCHAR})
+  </insert>
+
+</mapper>
diff --git a/submarine-server/server-core/src/test/java/org/apache/submarine/server/model/database/ModelVersionTagTest.java b/submarine-server/server-core/src/test/java/org/apache/submarine/server/model/database/ModelVersionTagTest.java
new file mode 100644
index 0000000..16f671a
--- /dev/null
+++ b/submarine-server/server-core/src/test/java/org/apache/submarine/server/model/database/ModelVersionTagTest.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.submarine.server.model.database;
+
+import org.apache.submarine.server.model.database.entities.ModelVersionEntity;
+import org.apache.submarine.server.model.database.entities.ModelVersionTagEntity;
+import org.apache.submarine.server.model.database.entities.RegisteredModelEntity;
+import org.apache.submarine.server.model.database.service.ModelVersionService;
+import org.apache.submarine.server.model.database.service.ModelVersionTagService;
+import org.apache.submarine.server.model.database.service.RegisteredModelService;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ModelVersionTagTest {
+  private static final Logger LOG = LoggerFactory.getLogger(ModelVersionTagTest.class);
+  RegisteredModelService registeredModelService = new RegisteredModelService();
+  ModelVersionService modelVersionService = new ModelVersionService();
+  ModelVersionTagService modelVersionTagService = new ModelVersionTagService();
+
+
+  @After
+  public void cleanAll() {
+    registeredModelService.deleteAll();
+  }
+
+  @Test
+  public void testInsertAndDelete() {
+    String name = "InsertModelVersionTag";
+    RegisteredModelEntity registeredModelEntity = new RegisteredModelEntity();
+    registeredModelEntity.setName(name);
+    registeredModelService.insert(registeredModelEntity);
+
+    Integer version = 1;
+    ModelVersionEntity modelVersionEntity = new ModelVersionEntity();
+    modelVersionEntity.setName(name);
+    modelVersionEntity.setVersion(version);
+    modelVersionEntity.setSource("path/to/source");
+    modelVersionEntity.setUserId("test");
+    modelVersionEntity.setExperimentId("application_1234");
+    modelVersionService.insert(modelVersionEntity);
+
+    ModelVersionTagEntity modelVersionTagEntity = new ModelVersionTagEntity();
+    modelVersionTagEntity.setName(name);
+    modelVersionTagEntity.setVersion(version);
+    modelVersionTagEntity.setTag("tag");
+    modelVersionTagService.insert(modelVersionTagEntity);
+
+    ModelVersionEntity modelVersionEntitySelected = modelVersionService.selectWithTag(name, version);
+    Assert.assertEquals(modelVersionTagEntity.getTag(), modelVersionEntitySelected.getTags().get(0));
+
+    modelVersionTagService.delete(modelVersionTagEntity);
+    modelVersionEntitySelected = modelVersionService.selectWithTag(name, version);
+    Assert.assertEquals(0, modelVersionEntitySelected.getTags().size());
+  }
+}
diff --git a/submarine-server/server-core/src/test/java/org/apache/submarine/server/model/database/ModelVersionTest.java b/submarine-server/server-core/src/test/java/org/apache/submarine/server/model/database/ModelVersionTest.java
new file mode 100644
index 0000000..98ba37c
--- /dev/null
+++ b/submarine-server/server-core/src/test/java/org/apache/submarine/server/model/database/ModelVersionTest.java
@@ -0,0 +1,174 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.submarine.server.model.database;
+
+import org.apache.submarine.server.model.database.entities.ModelVersionEntity;
+import org.apache.submarine.server.model.database.entities.RegisteredModelEntity;
+import org.apache.submarine.server.model.database.service.ModelVersionService;
+import org.apache.submarine.server.model.database.service.RegisteredModelService;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ModelVersionTest {
+  RegisteredModelService registeredModelService = new RegisteredModelService();
+  ModelVersionService modelVersionService = new ModelVersionService();
+
+  @After
+  public void cleanAll() {
+    registeredModelService.deleteAll();
+  }
+
+  @Test
+  public void testSelectAllVersions() {
+    String name = "selectAllModelVersions";
+    RegisteredModelEntity registeredModelEntity = new RegisteredModelEntity();
+    registeredModelEntity.setName(name);
+    registeredModelService.insert(registeredModelEntity);
+
+    Integer version = 1;
+    List<String> tags = new ArrayList<>();
+    tags.add("tag");
+    ModelVersionEntity modelVersionEntity = new ModelVersionEntity();
+    modelVersionEntity.setName(name);
+    modelVersionEntity.setVersion(version);
+    modelVersionEntity.setSource("path/to/source");
+    modelVersionEntity.setUserId("test");
+    modelVersionEntity.setExperimentId("application_1234");
+    modelVersionEntity.setTags(tags);
+    modelVersionService.insert(modelVersionEntity);
+
+    Integer version2 = 2;
+    List<String> tags2 = new ArrayList<>();
+    tags2.add("tag2");
+    ModelVersionEntity modelVersionEntity2 = new ModelVersionEntity();
+    modelVersionEntity2.setName(name);
+    modelVersionEntity2.setVersion(version2);
+    modelVersionEntity2.setSource("path/to/source2");
+    modelVersionEntity2.setUserId("test");
+    modelVersionEntity2.setExperimentId("application_1234");
+    modelVersionEntity2.setTags(tags2);
+    modelVersionService.insert(modelVersionEntity2);
+
+    List<ModelVersionEntity> modelVersionEntities = modelVersionService.selectAllVersions(name);
+    compareModelVersion(modelVersionEntity, modelVersionEntities.get(0));
+    compareTags(modelVersionEntity, modelVersionEntities.get(0));
+    compareModelVersion(modelVersionEntity2, modelVersionEntities.get(1));
+    compareTags(modelVersionEntity2, modelVersionEntities.get(1));
+  }
+
+  @Test
+  public void testInsertAndSelect() {
+    String name = "insertModelVersion";
+    RegisteredModelEntity registeredModelEntity = new RegisteredModelEntity();
+    registeredModelEntity.setName(name);
+    registeredModelService.insert(registeredModelEntity);
+
+    Integer version = 1;
+    List<String> tags = new ArrayList<>();
+    tags.add("tag");
+    ModelVersionEntity modelVersionEntity = new ModelVersionEntity();
+    modelVersionEntity.setName(name);
+    modelVersionEntity.setVersion(version);
+    modelVersionEntity.setSource("path/to/source");
+    modelVersionEntity.setUserId("test");
+    modelVersionEntity.setExperimentId("application_1234");
+    modelVersionEntity.setTags(tags);
+    modelVersionService.insert(modelVersionEntity);
+
+    ModelVersionEntity modelVersionEntitySelected = modelVersionService.select(name, version);
+    this.compareModelVersion(modelVersionEntity, modelVersionEntitySelected);
+
+    ModelVersionEntity modelVersionEntitySelectedWithTag = modelVersionService.selectWithTag(name, version);
+    this.compareModelVersion(modelVersionEntity, modelVersionEntitySelectedWithTag);
+    this.compareTags(modelVersionEntity, modelVersionEntitySelectedWithTag);
+  }
+
+  @Test
+  public void testUpdate() {
+    String name = "updateModelVersion";
+    RegisteredModelEntity registeredModelEntity = new RegisteredModelEntity();
+    registeredModelEntity.setName(name);
+    registeredModelService.insert(registeredModelEntity);
+
+    Integer version = 1;
+    ModelVersionEntity modelVersionEntity = new ModelVersionEntity();
+    modelVersionEntity.setName(name);
+    modelVersionEntity.setVersion(version);
+    modelVersionEntity.setSource("path/to/source");
+    modelVersionEntity.setUserId("test");
+    modelVersionEntity.setExperimentId("application_1234");
+    modelVersionService.insert(modelVersionEntity);
+
+    ModelVersionEntity modelVersionEntitySelected = modelVersionService.select(name, version);
+    this.compareModelVersion(modelVersionEntity, modelVersionEntitySelected);
+
+    String newStage = "Developing";
+    String newDataset = "mnist";
+    String newDescription = "New description.";
+    modelVersionEntity.setCurrentStage(newStage);
+    modelVersionEntity.setDataset(newDataset);
+    modelVersionEntity.setDescription(newDescription);
+    modelVersionService.update(modelVersionEntity);
+
+    modelVersionEntitySelected = modelVersionService.select(name, version);
+    this.compareModelVersion(modelVersionEntity, modelVersionEntitySelected);
+  }
+
+  @Test
+  public void testDelete() {
+    String name = "deleteModelVersion";
+    RegisteredModelEntity registeredModelEntity = new RegisteredModelEntity();
+    registeredModelEntity.setName(name);
+    registeredModelService.insert(registeredModelEntity);
+
+    Integer version = 1;
+    ModelVersionEntity modelVersionEntity = new ModelVersionEntity();
+    modelVersionEntity.setName(name);
+    modelVersionEntity.setVersion(version);
+    modelVersionEntity.setSource("path/to/source");
+    modelVersionEntity.setUserId("test");
+    modelVersionEntity.setExperimentId("application_1234");
+    modelVersionService.insert(modelVersionEntity);
+
+    modelVersionService.delete(name, version);
+
+  }
+
+  private void compareModelVersion(ModelVersionEntity expected, ModelVersionEntity actual) {
+    Assert.assertEquals(expected.getName(), actual.getName());
+    Assert.assertEquals(expected.getVersion(), actual.getVersion());
+    Assert.assertEquals(expected.getSource(), actual.getSource());
+    Assert.assertEquals(expected.getUserId(), actual.getUserId());
+    Assert.assertEquals(expected.getExperimentId(), actual.getExperimentId());
+    Assert.assertEquals(expected.getCurrentStage(), actual.getCurrentStage());
+    Assert.assertNotNull(actual.getCreationTime());
+    Assert.assertNotNull(actual.getLastUpdatedTime());
+    Assert.assertEquals(expected.getDataset(), actual.getDataset());
+    Assert.assertEquals(expected.getDescription(), actual.getDescription());
+  }
+
+  private void compareTags(ModelVersionEntity expected, ModelVersionEntity actual) {
+    Assert.assertEquals(expected.getTags(), actual.getTags());
+  }
+}
diff --git a/submarine-server/server-core/src/test/java/org/apache/submarine/server/model/database/RegisteredModelServiceTest.java b/submarine-server/server-core/src/test/java/org/apache/submarine/server/model/database/RegisteredModelServiceTest.java
new file mode 100644
index 0000000..93322f0
--- /dev/null
+++ b/submarine-server/server-core/src/test/java/org/apache/submarine/server/model/database/RegisteredModelServiceTest.java
@@ -0,0 +1,148 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.submarine.server.model.database;
+
+import org.apache.submarine.server.model.database.entities.RegisteredModelEntity;
+import org.apache.submarine.server.model.database.service.RegisteredModelService;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class RegisteredModelServiceTest {
+  RegisteredModelService registeredModelService = new RegisteredModelService();
+
+  @After
+  public void cleanAll() {
+    registeredModelService.deleteAll();
+  }
+
+  @Test
+  public void testSelectAll() {
+    String name = "RegisteredModel1";
+    List<String> tags = new ArrayList<>();
+    tags.add("tag1");
+    RegisteredModelEntity registeredModelEntity = new RegisteredModelEntity();
+    registeredModelEntity.setName(name);
+    registeredModelEntity.setTags(tags);
+    registeredModelService.insert(registeredModelEntity);
+
+    String name2 = "RegisteredModel2";
+    List<String> tags2 = new ArrayList<>();
+    tags2.add("tag2");
+    RegisteredModelEntity registeredModelEntity2 = new RegisteredModelEntity();
+    registeredModelEntity2.setName(name2);
+    registeredModelEntity2.setTags(tags2);
+    registeredModelService.insert(registeredModelEntity2);
+
+    List<RegisteredModelEntity> registeredModelEntities = registeredModelService.selectAll();
+    compareRegisteredModel(registeredModelEntity, registeredModelEntities.get(0));
+    compareTags(registeredModelEntity, registeredModelEntities.get(0));
+    compareRegisteredModel(registeredModelEntity2, registeredModelEntities.get(1));
+    compareTags(registeredModelEntity2, registeredModelEntities.get(1));
+  }
+
+  @Test
+  public void testInsertAndSelect() {
+    String name = "RegisteredModel";
+    String description = "Description.";
+    List<String> tags = new ArrayList<>();
+    tags.add("tag");
+    RegisteredModelEntity registeredModelEntity = new RegisteredModelEntity();
+    registeredModelEntity.setName(name);
+    registeredModelEntity.setDescription(description);
+    registeredModelEntity.setTags(tags);
+    registeredModelService.insert(registeredModelEntity);
+
+    RegisteredModelEntity registeredModelEntitySelected = registeredModelService.select(name);
+    compareRegisteredModel(registeredModelEntity, registeredModelEntitySelected);
+
+    RegisteredModelEntity registeredModelEntitySelectedWithTags = registeredModelService.selectWithTag(name);
+    compareRegisteredModel(registeredModelEntity, registeredModelEntitySelectedWithTags);
+    compareTags(registeredModelEntity, registeredModelEntitySelectedWithTags);
+  }
+
+  @Test
+  public void testUpdate() {
+    String name = "RegisteredModel";
+    String description = "Description.";
+    RegisteredModelEntity registeredModelEntity = new RegisteredModelEntity();
+    registeredModelEntity.setName(name);
+    registeredModelEntity.setDescription(description);
+    registeredModelService.insert(registeredModelEntity);
+
+    RegisteredModelEntity registeredModelEntitySelected = registeredModelService.select(name);
+    compareRegisteredModel(registeredModelEntity, registeredModelEntitySelected);
+
+    String newDescription = "New description.";
+    registeredModelEntity.setDescription(newDescription);
+    registeredModelService.update(registeredModelEntity);
+
+    registeredModelEntitySelected = registeredModelService.select(name);
+    compareRegisteredModel(registeredModelEntity, registeredModelEntitySelected);
+  }
+
+  @Test
+  public void testRename() {
+    String name = "RegisteredModel";
+    RegisteredModelEntity registeredModelEntity = new RegisteredModelEntity();
+    registeredModelEntity.setName(name);
+    registeredModelService.insert(registeredModelEntity);
+
+    RegisteredModelEntity registeredModelEntitySelected = registeredModelService.select(name);
+    compareRegisteredModel(registeredModelEntity, registeredModelEntitySelected);
+
+    String newName = "newRegisteredModel";
+    registeredModelService.rename(name, newName);
+
+    registeredModelEntitySelected = registeredModelService.select(newName);
+    registeredModelEntity.setName(newName);
+    compareRegisteredModel(registeredModelEntity, registeredModelEntitySelected);
+  }
+
+  @Test
+  public void testDelete() {
+    String name = "RegisteredModel";
+    RegisteredModelEntity registeredModelEntity = new RegisteredModelEntity();
+    registeredModelEntity.setName(name);
+    registeredModelService.insert(registeredModelEntity);
+
+    RegisteredModelEntity registeredModelEntitySelected = registeredModelService.select(name);
+    compareRegisteredModel(registeredModelEntity, registeredModelEntitySelected);
+
+    registeredModelService.delete(name);
+    List<RegisteredModelEntity> registeredModelEntities = registeredModelService.selectAll();
+
+    Assert.assertEquals(0, registeredModelEntities.size());
+  }
+
+  private void compareRegisteredModel(RegisteredModelEntity expected, RegisteredModelEntity actual) {
+    Assert.assertEquals(expected.getName(), actual.getName());
+    Assert.assertNotNull(actual.getCreationTime());
+    Assert.assertNotNull(actual.getLastUpdatedTime());
+    Assert.assertEquals(expected.getDescription(), actual.getDescription());
+  }
+
+  private void compareTags(RegisteredModelEntity expected, RegisteredModelEntity actual) {
+    Assert.assertEquals(true, expected.getTags().equals(actual.getTags()));
+  }
+}
diff --git a/submarine-server/server-core/src/test/java/org/apache/submarine/server/model/database/RegisteredModelTagServiceTest.java b/submarine-server/server-core/src/test/java/org/apache/submarine/server/model/database/RegisteredModelTagServiceTest.java
new file mode 100644
index 0000000..1f59ab2
--- /dev/null
+++ b/submarine-server/server-core/src/test/java/org/apache/submarine/server/model/database/RegisteredModelTagServiceTest.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.submarine.server.model.database;
+
+import org.apache.submarine.server.model.database.entities.RegisteredModelEntity;
+import org.apache.submarine.server.model.database.entities.RegisteredModelTagEntity;
+import org.apache.submarine.server.model.database.service.RegisteredModelService;
+import org.apache.submarine.server.model.database.service.RegisteredModelTagService;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class RegisteredModelTagServiceTest {
+  private static final Logger LOG = LoggerFactory.getLogger(RegisteredModelTagServiceTest.class);
+  RegisteredModelService registeredModelService = new RegisteredModelService();
+  RegisteredModelTagService registeredModelTagService = new RegisteredModelTagService();
+
+  @After
+  public void cleanAll() {
+    registeredModelService.deleteAll();
+  }
+
+  @Test
+  public void testInsertAndDelete() {
+    String name = "InsertRegisteredModelTag";
+    RegisteredModelEntity registeredModelEntity = new RegisteredModelEntity();
+    registeredModelEntity.setName(name);
+    registeredModelService.insert(registeredModelEntity);
+
+    RegisteredModelTagEntity registeredModelTagEntity = new RegisteredModelTagEntity();
+    registeredModelTagEntity.setName(name);
+    registeredModelTagEntity.setTag("tag");
+    registeredModelTagService.insert(registeredModelTagEntity);
+
+    RegisteredModelEntity registeredModelEntitySelected = registeredModelService.selectWithTag(name);
+    Assert.assertEquals(registeredModelTagEntity.getTag(), registeredModelEntitySelected.getTags().get(0));
+
+    registeredModelTagService.delete(registeredModelTagEntity);
+    registeredModelEntitySelected = registeredModelService.selectWithTag(name);
+    Assert.assertEquals(0, registeredModelEntitySelected.getTags().size());
+  }
+}

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@submarine.apache.org
For additional commands, e-mail: dev-help@submarine.apache.org