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/08/09 05:55:59 UTC

[submarine] branch master updated: SUBMARINE-911. Fix the bug about deleting notebook

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 63913bb  SUBMARINE-911. Fix the bug about deleting notebook
63913bb is described below

commit 63913bbed3dfd8a2d64b06a127c69482f90144cb
Author: Lisa <ae...@gmail.com>
AuthorDate: Sun Aug 8 23:46:37 2021 +0800

    SUBMARINE-911. Fix the bug about deleting notebook
    
    ### What is this PR for?
    
    Store notebook data to database.
    Those data used to be saved in cache. The notebook pod have persistent volume to retain them which make the pod still working even if the server restart for some reason. But in this case, we will lose control of the pod on workbench because we don't have the data of these notebooks.
    
    ### What type of PR is it?
    [Bug Fix]
    
    ### Todos
    * [ ] - Task
    
    ### What is the Jira issue?
    https://issues.apache.org/jira/browse/SUBMARINE-911
    
    ### How should this be tested?
    <!--
    * First time? Setup Travis CI as described on https://submarine.apache.org/contribution/contributions.html#continuous-integration
    * Strongly recommended: add automated unit tests for any new or changed behavior
    * Outline any manual steps to test the PR here.
    -->
    ### Screenshots (if appropriate)
    ![image](https://user-images.githubusercontent.com/30621230/126822877-41f0cb23-3fbc-4e2b-86ff-ad5b41781e6d.png)
    
    ### Questions:
    * Do the license files need updating? No
    * Are there breaking changes for older versions? No
    * Does this need new documentation? No
    
    Author: Lisa <ae...@gmail.com>
    
    Signed-off-by: Kevin <pi...@apache.org>
    
    Closes #689 from aeioulisa/SUBMARINE-911 and squashes the following commits:
    
    6ceebfbc [Lisa] address comment
    c4ed8141 [Lisa] reformat code
    8f76dfe4 [Lisa] check if notebook is in the database
    c7cb79aa [Lisa] store notebook to database.
---
 dev-support/database/submarine.sql                 |  14 ++
 .../submarine/server/notebook/NotebookManager.java |  90 +++++++-----
 .../server/notebook/database/NotebookEntity.java   |  52 +++++++
 .../server/notebook/database/NotebookMapper.java   |  34 +++++
 .../server/notebook/database/NotebookService.java  | 156 +++++++++++++++++++++
 .../src/main/resources/mybatis-config.xml          |   1 +
 .../submarine/database/mappers/NotebookMapper.xml  |  73 ++++++++++
 7 files changed, 382 insertions(+), 38 deletions(-)

diff --git a/dev-support/database/submarine.sql b/dev-support/database/submarine.sql
index 56d51a5..04f8b51 100644
--- a/dev-support/database/submarine.sql
+++ b/dev-support/database/submarine.sql
@@ -251,6 +251,20 @@ CREATE TABLE `experiment` (
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 
 -- ----------------------------
+-- Table structure for notebook
+-- ----------------------------
+DROP TABLE IF EXISTS `notebook`;
+CREATE TABLE `notebook` (
+  `id` varchar(64) NOT NULL COMMENT 'Id of the notebook',
+  `notebook_spec` text NOT NULL COMMENT 'Spec of the notebook',
+  `create_by` varchar(32) DEFAULT NULL COMMENT 'create user',
+  `create_time` datetime DEFAULT NULL COMMENT 'create time',
+  `update_by` varchar(32) DEFAULT NULL COMMENT 'last update user',
+  `update_time` datetime DEFAULT NULL COMMENT 'last update time',
+   PRIMARY KEY `id` (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+-- ----------------------------
 -- Table structure for metric
 -- ----------------------------
 DROP TABLE IF EXISTS `metrics`;
diff --git a/submarine-server/server-core/src/main/java/org/apache/submarine/server/notebook/NotebookManager.java b/submarine-server/server-core/src/main/java/org/apache/submarine/server/notebook/NotebookManager.java
index da23c9c..b183f5a 100644
--- a/submarine-server/server-core/src/main/java/org/apache/submarine/server/notebook/NotebookManager.java
+++ b/submarine-server/server-core/src/main/java/org/apache/submarine/server/notebook/NotebookManager.java
@@ -32,39 +32,37 @@ import org.apache.submarine.server.environment.EnvironmentManager;
 import javax.ws.rs.core.Response;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.atomic.AtomicInteger;
+import org.apache.submarine.server.notebook.database.NotebookService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public class NotebookManager {
+  private static final Logger LOG = LoggerFactory.getLogger(NotebookManager.class);
 
   private static volatile NotebookManager manager;
 
   private final Submitter submitter;
 
-  private NotebookManager(Submitter submitter) {
+  private final NotebookService notebookService;
+
+  private NotebookManager(Submitter submitter, NotebookService notebookService) {
     this.submitter = submitter;
+    this.notebookService = notebookService;
   }
 
   private final AtomicInteger notebookCounter = new AtomicInteger(0);
 
   /**
-   * Used to cache the specs by the notebook id.
-   *  key: the string of notebook id
-   *  value: Notebook object
-   */
-  private final ConcurrentMap<String, Notebook> cachedNotebookMap = new ConcurrentHashMap<>();
-
-  /**
    * Get the singleton instance
+   *
    * @return object
    */
   public static NotebookManager getInstance() {
     if (manager == null) {
       synchronized (NotebookManager.class) {
         if (manager == null) {
-          manager = new NotebookManager(SubmitterManager.loadSubmitter());
+          manager = new NotebookManager(SubmitterManager.loadSubmitter(), new NotebookService());
         }
       }
     }
@@ -73,6 +71,7 @@ public class NotebookManager {
 
   /**
    * Create a notebook instance
+   *
    * @param spec NotebookSpec
    * @return object
    * @throws SubmarineRuntimeException the service error
@@ -81,8 +80,9 @@ public class NotebookManager {
     checkNotebookSpec(spec);
     String lowerName = spec.getMeta().getName().toLowerCase();
     spec.getMeta().setName(lowerName);
+    NotebookId notebookId = generateNotebookId();
     Notebook notebook = submitter.createNotebook(spec);
-    notebook.setNotebookId(generateNotebookId());
+    notebook.setNotebookId(notebookId);
     notebook.setSpec(spec);
 
     // environment information
@@ -92,23 +92,23 @@ public class NotebookManager {
     if (environment.getEnvironmentSpec() != null) {
       notebookSpec.setEnvironment(environment.getEnvironmentSpec());
     }
-    cachedNotebookMap.putIfAbsent(notebook.getNotebookId().toString(), notebook);
+    notebookService.insert(notebook);
     return notebook;
   }
 
   /**
    * List notebook instances
+   *
    * @param namespace namespace, if null will return all notebooks
    * @return list
    * @throws SubmarineRuntimeException the service error
    */
   public List<Notebook> listNotebooksByNamespace(String namespace) throws SubmarineRuntimeException {
     List<Notebook> notebookList = new ArrayList<>();
-    for (Map.Entry<String, Notebook> entry : cachedNotebookMap.entrySet()) {
-      Notebook notebook = entry.getValue();
+    for (Notebook notebook : notebookService.selectAll()) {
       Notebook patchNotebook = submitter.findNotebook(notebook.getSpec());
       if (namespace == null || namespace.length() == 0
-              || namespace.toLowerCase().equals(patchNotebook.getSpec().getMeta().getNamespace())) {
+          || namespace.toLowerCase().equals(patchNotebook.getSpec().getMeta().getNamespace())) {
         notebook.rebuild(patchNotebook);
         notebookList.add(notebook);
       }
@@ -118,18 +118,23 @@ public class NotebookManager {
 
   /**
    * Get a list of notebook with user id
+   *
    * @param id user id
    * @return a list of notebook
    */
   public List<Notebook> listNotebooksByUserId(String id) {
-    List<Notebook> notebookList = submitter.listNotebook(id);
-    for (Notebook notebook : notebookList) {
-      for (Map.Entry<String, Notebook> entry : cachedNotebookMap.entrySet()) {
-        Notebook cachedNotebook = entry.getValue();
-        if (cachedNotebook.getUid().equals(notebook.getUid())) {
-          notebook.setNotebookId(cachedNotebook.getNotebookId());
-          notebook.setSpec(cachedNotebook.getSpec());
-        }
+    List<Notebook> serviceNotebooks = notebookService.selectAll();
+    List<Notebook> notebookList = new ArrayList<>();
+    for (Notebook nb : serviceNotebooks) {
+      try {
+        Notebook notebook = submitter.findNotebook(nb.getSpec());
+        notebook.setNotebookId(nb.getNotebookId());
+        notebook.setSpec(nb.getSpec());
+        notebookList.add(notebook);
+      } catch (SubmarineRuntimeException e) {
+        LOG.warn("Submitter can not find notebook: {}, will delete it", nb.getNotebookId());
+        notebookService.delete(nb.getNotebookId().toString());
+        continue;
       }
     }
     return notebookList;
@@ -137,60 +142,69 @@ public class NotebookManager {
 
   /**
    * Get a notebook instance
+   *
    * @param id notebook id
    * @return object
    * @throws SubmarineRuntimeException the service error
    */
   public Notebook getNotebook(String id) throws SubmarineRuntimeException {
     checkNotebookId(id);
-    Notebook notebook = cachedNotebookMap.get(id);
-    NotebookSpec spec = notebook.getSpec();
-    Notebook patchNotebook = submitter.findNotebook(spec);
-    notebook.rebuild(patchNotebook);
-    return notebook;
+
+    Notebook notebook = notebookService.select(id);
+    if (notebook == null) {
+      throw new SubmarineRuntimeException(Response.Status.NOT_FOUND.getStatusCode(),
+          "Notebook not found.");
+    }
+    Notebook foundNotebook = submitter.findNotebook(notebook.getSpec());
+    foundNotebook.rebuild(notebook);
+
+    return foundNotebook;
   }
 
   /**
    * Delete the notebook instance
+   *
    * @param id notebook id
    * @return object
    * @throws SubmarineRuntimeException the service error
    */
   public Notebook deleteNotebook(String id) throws SubmarineRuntimeException {
-    checkNotebookId(id);
-    Notebook notebook = cachedNotebookMap.remove(id);
-    NotebookSpec spec = notebook.getSpec();
-    Notebook patchNotebook = submitter.deleteNotebook(spec);
+    Notebook notebook = getNotebook(id);
+    Notebook patchNotebook = submitter.deleteNotebook(notebook.getSpec());
+    notebookService.delete(id);
     notebook.rebuild(patchNotebook);
     return notebook;
   }
 
   /**
    * Generate a unique notebook id
+   *
    * @return notebook id
    */
   private NotebookId generateNotebookId() {
     return NotebookId.newInstance(SubmarineServer.getServerTimeStamp(),
-            notebookCounter.incrementAndGet());
+        notebookCounter.incrementAndGet());
   }
 
   /**
    * Check if notebook spec is valid
+   *
    * @param spec notebook spec
    */
   private void checkNotebookSpec(NotebookSpec spec) {
     //TODO(ryan): The method need to be improved
     if (spec == null) {
       throw new SubmarineRuntimeException(Response.Status.OK.getStatusCode(),
-              "Invalid. Notebook Spec object is null.");
+          "Invalid. Notebook Spec object is null.");
     }
   }
 
   private void checkNotebookId(String id) throws SubmarineRuntimeException {
     NotebookId notebookId = NotebookId.fromString(id);
-    if (notebookId == null || !cachedNotebookMap.containsKey(id)) {
+    if (notebookId == null) {
       throw new SubmarineRuntimeException(Response.Status.NOT_FOUND.getStatusCode(),
-              "Not found notebook server.");
+          "Notebook not found.");
     }
   }
+
 }
diff --git a/submarine-server/server-core/src/main/java/org/apache/submarine/server/notebook/database/NotebookEntity.java b/submarine-server/server-core/src/main/java/org/apache/submarine/server/notebook/database/NotebookEntity.java
new file mode 100644
index 0000000..0da59ae
--- /dev/null
+++ b/submarine-server/server-core/src/main/java/org/apache/submarine/server/notebook/database/NotebookEntity.java
@@ -0,0 +1,52 @@
+/*
+ * 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.notebook.database;
+
+import org.apache.submarine.server.database.entity.BaseEntity;
+
+public class NotebookEntity extends BaseEntity {
+  /*
+    Take id (inherited from BaseEntity) as the primary key for notebook table
+  */
+  private String notebookSpec;
+
+  public NotebookEntity() {
+  }
+
+  public String getNotebookSpec() {
+    return notebookSpec;
+  }
+
+  public void setNotebookSpec(String notebookSpec) {
+    this.notebookSpec = notebookSpec;
+  }
+
+  @Override
+  public String toString() {
+    return "NotebookEntity{" +
+        "notebookSpec='" + notebookSpec + '\'' +
+        ", id='" + id + '\'' +
+        ", createBy='" + createBy + '\'' +
+        ", createTime=" + createTime +
+        ", updateBy='" + updateBy + '\'' +
+        ", updateTime=" + updateTime +
+        '}';
+  }
+}
diff --git a/submarine-server/server-core/src/main/java/org/apache/submarine/server/notebook/database/NotebookMapper.java b/submarine-server/server-core/src/main/java/org/apache/submarine/server/notebook/database/NotebookMapper.java
new file mode 100644
index 0000000..eded0c1
--- /dev/null
+++ b/submarine-server/server-core/src/main/java/org/apache/submarine/server/notebook/database/NotebookMapper.java
@@ -0,0 +1,34 @@
+/*
+ * 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.notebook.database;
+
+import java.util.List;
+
+public interface NotebookMapper {
+  List<NotebookEntity> selectAll();
+
+  NotebookEntity select(String id);
+
+  int insert(NotebookEntity notebook);
+
+  int update(NotebookEntity notebook);
+
+  int delete(String id);
+}
diff --git a/submarine-server/server-core/src/main/java/org/apache/submarine/server/notebook/database/NotebookService.java b/submarine-server/server-core/src/main/java/org/apache/submarine/server/notebook/database/NotebookService.java
new file mode 100644
index 0000000..839ca0e
--- /dev/null
+++ b/submarine-server/server-core/src/main/java/org/apache/submarine/server/notebook/database/NotebookService.java
@@ -0,0 +1,156 @@
+/*
+ * 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.notebook.database;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import java.util.ArrayList;
+import org.apache.ibatis.session.SqlSession;
+import org.apache.submarine.commons.utils.exception.SubmarineRuntimeException;
+import org.apache.submarine.server.api.notebook.Notebook;
+import org.apache.submarine.server.api.notebook.NotebookId;
+import org.apache.submarine.server.api.spec.NotebookSpec;
+import org.apache.submarine.server.database.utils.MyBatisUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+
+public class NotebookService {
+
+  private static final Logger LOG = LoggerFactory.getLogger(NotebookService.class);
+
+  public List<Notebook> selectAll() throws SubmarineRuntimeException {
+    LOG.info("Notebook selectAll");
+    List<NotebookEntity> entities;
+    List<Notebook> notebooks = new ArrayList<>();
+    try (SqlSession sqlSession = MyBatisUtil.getSqlSession()) {
+      NotebookMapper mapper = sqlSession.getMapper(NotebookMapper.class);
+      entities = mapper.selectAll();
+      sqlSession.commit();
+    } catch (Exception e) {
+      LOG.error(e.getMessage(), e);
+      throw new SubmarineRuntimeException("Unable to get notebook entities from database");
+    }
+    for (NotebookEntity entity : entities) {
+      notebooks.add(buildNotebookFromEntity(entity));
+    }
+    return notebooks;
+  }
+
+  public Notebook select(String id) throws SubmarineRuntimeException {
+    LOG.info("Notebook select " + id);
+    NotebookEntity entity;
+    Notebook notebook;
+    try (SqlSession sqlSession = MyBatisUtil.getSqlSession()) {
+      NotebookMapper mapper = sqlSession.getMapper(NotebookMapper.class);
+      entity = mapper.select(id);
+      sqlSession.commit();
+    } catch (Exception e) {
+      LOG.error(e.getMessage(), e);
+      throw new SubmarineRuntimeException("Unable to get notebook entity from database");
+    }
+    if (entity != null) {
+      notebook = buildNotebookFromEntity(entity);
+      return notebook;
+    }
+    return null;
+  }
+
+  public boolean insert(Notebook notebook) throws SubmarineRuntimeException {
+    LOG.info("Notebook insert");
+    LOG.debug(notebook.toString());
+    NotebookEntity entity = buildEntityFromNotebook(notebook);
+    try (SqlSession sqlSession = MyBatisUtil.getSqlSession()) {
+      NotebookMapper mapper = sqlSession.getMapper(NotebookMapper.class);
+      mapper.insert(entity);
+      sqlSession.commit();
+    } catch (Exception e) {
+      LOG.error(e.getMessage(), e);
+      throw new SubmarineRuntimeException("Unable to insert notebook entity to database");
+    }
+    return true;
+  }
+
+  public boolean update(Notebook notebook) throws SubmarineRuntimeException {
+    LOG.info("Notebook update");
+    NotebookEntity entity = buildEntityFromNotebook(notebook);
+    try (SqlSession sqlSession = MyBatisUtil.getSqlSession()) {
+      NotebookMapper mapper = sqlSession.getMapper(NotebookMapper.class);
+      mapper.update(entity);
+      sqlSession.commit();
+    } catch (Exception e) {
+      LOG.error(e.getMessage(), e);
+      throw new SubmarineRuntimeException("Unable to update notebook entity in database");
+    }
+    return true;
+  }
+
+  public boolean delete(String id) throws SubmarineRuntimeException {
+    LOG.info("Notebook delete " + id);
+
+    try (SqlSession sqlSession = MyBatisUtil.getSqlSession()) {
+      NotebookMapper mapper = sqlSession.getMapper(NotebookMapper.class);
+      mapper.delete(id);
+      sqlSession.commit();
+    } catch (Exception e) {
+      LOG.error(e.getMessage(), e);
+      throw new SubmarineRuntimeException("Unable to delete notebook entity from database");
+    }
+    return true;
+  }
+
+  /**
+   * Create a NotebookEntity instance from experiment
+   *
+   * @param notebook
+   * @return NotebookEntity
+   */
+  private NotebookEntity buildEntityFromNotebook(Notebook notebook) {
+    NotebookEntity entity = new NotebookEntity();
+    try {
+      entity.setId(notebook.getNotebookId().toString());
+      entity.setNotebookSpec(new GsonBuilder().disableHtmlEscaping().create().toJson(notebook.getSpec()));
+    } catch (Exception e) {
+      LOG.error(e.getMessage(), e);
+      throw new SubmarineRuntimeException("Unable to build entity from notebook");
+    }
+    return entity;
+  }
+
+  /**
+   * Create a new notebook instance from entity
+   *
+   * @param entity
+   * @return Notebook
+   */
+  private Notebook buildNotebookFromEntity(NotebookEntity entity) {
+    Notebook notebook = new Notebook();
+    try {
+      notebook.setNotebookId(NotebookId.fromString(entity.getId()));
+      notebook.setSpec(new Gson().fromJson(entity.getNotebookSpec(), NotebookSpec.class));
+      notebook.setName(notebook.getSpec().getMeta().getName());
+    } catch (Exception e) {
+      LOG.error(e.getMessage(), e);
+      throw new SubmarineRuntimeException("Unable to build notebook from entity");
+    }
+    return notebook;
+  }
+}
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 2982281..e251084 100755
--- a/submarine-server/server-core/src/main/resources/mybatis-config.xml
+++ b/submarine-server/server-core/src/main/resources/mybatis-config.xml
@@ -69,5 +69,6 @@
     <mapper resource='org/apache/submarine/database/mappers/EnvironmentMapper.xml'/>
     <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'/>
   </mappers>
 </configuration>
diff --git a/submarine-server/server-core/src/main/resources/org/apache/submarine/database/mappers/NotebookMapper.xml b/submarine-server/server-core/src/main/resources/org/apache/submarine/database/mappers/NotebookMapper.xml
new file mode 100644
index 0000000..6c99197
--- /dev/null
+++ b/submarine-server/server-core/src/main/resources/org/apache/submarine/database/mappers/NotebookMapper.xml
@@ -0,0 +1,73 @@
+<?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.notebook.database.NotebookMapper">
+  <resultMap id="BaseEntityResultMap" type="org.apache.submarine.server.database.entity.BaseEntity">
+    <id property="id" column="id"/>
+    <result column="create_by" property="createBy"/>
+    <result column="create_time" property="createTime"/>
+    <result column="update_by" property="updateBy"/>
+    <result column="update_time" property="updateTime"/>
+  </resultMap>
+
+  <resultMap id="NotebookEntityResultMap" type="org.apache.submarine.server.notebook.database.NotebookEntity" extends="BaseEntityResultMap">
+    <result column="notebook_spec" jdbcType="VARCHAR" property="notebookSpec" />
+  </resultMap>
+
+  <sql id="Base_Column_List">
+    id, notebook_spec, create_by, create_time, update_by, update_time
+  </sql>
+
+  <select id="selectAll" parameterType="java.lang.String" resultMap="NotebookEntityResultMap">
+    select
+    <include refid="Base_Column_List" />
+    from notebook
+  </select>
+
+  <select id="select" parameterType="java.lang.String" resultMap="NotebookEntityResultMap">
+    select
+    <include refid="Base_Column_List" />
+    from notebook
+    where id = #{id,jdbcType=VARCHAR}
+  </select>
+
+  <delete id="delete" parameterType="java.lang.String">
+    delete from notebook
+    where id = #{id,jdbcType=VARCHAR}
+  </delete>
+
+  <insert id="insert" parameterType="org.apache.submarine.server.notebook.database.NotebookEntity">
+    insert into notebook (id, notebook_spec, create_by, create_time, update_by, update_time)
+    values (#{id,jdbcType=VARCHAR}, #{notebookSpec,jdbcType=VARCHAR},
+            #{createBy,jdbcType=VARCHAR}, now(), #{updateBy,jdbcType=VARCHAR}, now())
+  </insert>
+
+  <update id="update" parameterType="org.apache.submarine.server.notebook.database.NotebookEntity">
+    update notebook
+    <set>
+      <if test="notebookSpec != null">
+        notebook_spec = #{notebookSpec,jdbcType=VARCHAR},
+      </if>
+      update_time = now()
+    </set>
+    where id = #{id,jdbcType=VARCHAR}
+  </update>
+
+</mapper>

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