【问题标题】:MyBatis, how to get the auto generated key of an insert? [MySql]MyBatis,如何获取插入的自动生成密钥? [MySql]
【发布时间】:2013-09-01 16:24:59
【问题描述】:

如何使用 MyBatis 获取插入的生成密钥? 我阅读了很多关于这个问题的页面,但我仍然被阻止,有人可以帮助我吗? 这是我的代码:

桌子:

ID_ERROR long primary key
DATE timestamp
TYPE varchar
MESSAGE varchar
SOURCE varchar

道:

Long returnedId = 0L;
MyMapper myMapper = this.sqlSession.getMapper(MyMapper.class);
myMapper.insertRecord(returnedId, Utils.now(), t.getClass().getName(), t.getMessage(), c.getName());
return returnedId;

mapper.java:

public void insertRecord(@Param("returnedId") Long returnedId, @Param("timestamp")Timestamp timestamp,@Param("type") String type,@Param("message") String message,@Param("source") String source);

mapper.xml

 <insert id="insertRecord" parameterType="map" useGeneratedKeys="true"  keyProperty="ID_ERROR">
    INSERT INTO errors (
        DATE,
        TYPE,
        MESSAGE,
        SOURCE
    )
    VALUES (
        #{timestamp},
        #{type},
        #{message},
        #{source}
    )
    <selectKey resultType="long" order="AFTER" keyProperty="returnedId">
        SELECT LAST_INSERT_ID() as returnedId
    </selectKey>
</insert>

怎么了?如何获取此插入的生成密钥? 谢谢!

【问题讨论】:

    标签: java mysql insert mybatis


    【解决方案1】:

    在xml文件中放5行以下:

    <insert id="createPet" parameterType="java.util.Map"
        useGeneratedKeys="true" keyProperty="id">
        INSERT INTO Pet (NAME, OWNER, SPECIES, SEX, BIRTH)
        VALUES (#{name}, #{owner}, #{species}, #{sex}, #{birth})
    </insert>
    

    在Java主类中创建该方法,并在主方法中调用:

    public int createPet(PetDVO petDVO) throws Exception {
        HashMap<String, Object> inputMap = new HashMap<String, Object>();
        inputMap.put("name", petDVO.getName());
        inputMap.put("owner", petDVO.getOwner());
        inputMap.put("species", petDVO.getSpecies());
        inputMap.put("sex", petDVO.getSex());
        inputMap.put("birth", petDVO.getBirth());
    
        /**
         * Get the sql session and commit the data
         */
        SqlSession sqlSession = getSqlSession();
        sqlSession.insert("createPet", inputMap);
        sqlSession.commit();
    
        BigInteger newID = (BigInteger)inputMap.get("id");
        return newID.intValue();
    }
    

    但是您应该自己创建 PetDVO 类。就是这样。

    【讨论】:

      【解决方案2】:

      如果您查看MyBatis documentationuseGeneratedKeyskeyProperty 是您至少需要获取自动增量数据(对于某些数据库,您需要添加 keyColumn)。

      如您所见,useGeneratedKeys 取决于是否/如何实现数据库的 JDBC 的 getGeneretadKeys 方法。

      例如,mysql 或 H2,getGeneretadKeys 仅支持一列。最后生成的密钥将是 getGeneretadKeys 返回的一个。

      总之,在您的情况下,您只需要添加 useGeneratedKeys 和 keyProperty(带有 ID_ERROR auto_increment):

      映射器.xml

      <resultMap type='pathToJavaClass/Error' id='error'>
          <id property='id' column='ID_ERROR' />
          <result property='timestamp' column='DATE' />
          <result property='type' column='TYPE'/>
          <result property='message' column='MESSAGE'/>
          <result property='source' column='SOURCE'/>
      </resultMap>
      <insert id="insertRecord" parameterType="error" useGeneratedKeys="true" keyProperty="id">
      INSERT INTO errors (
          DATE,
          TYPE,
          MESSAGE,
          SOURCE
      )
      VALUES (
          #{timestamp},
          #{type},
          #{message},
          #{source}
      )
      </insert>
      

      接口.java

      public void insertRecord(@Param("error") Error error);
      

      如果您在检索生成的密钥时仍然遇到问题,请查看 mysql 的 JDBC 文档(旧版本可能无法实现 getGeneretadKeys)。

      【讨论】:

      • 如果我有一个 mapper.java 而不是 mapper.xml 如何实现这个?
      【解决方案3】:

      您可以通过两种方式实现这一点,

      1. 通过使用useGeneratedKeys="true", keyProperty="id", keyColumn="id"

        keyProperty 指 POJO 变量名,keyColumn 指数据库中生成的列名

      2. 通过在插入标签中使用&lt;selectKey/&gt;

      【讨论】:

      • 你为什么使用useGeneratedKeys="true", keyProperty="id", keyColumn="id"?应该是useGeneratedKeys="true" keyProperty="id" keyColumn="id"
      【解决方案4】:

      在 Mapper Xml 下,使用查询:

          <insert id="saveDemo" parameterType="com.abc.demo"
             useGeneratedKeys="true" keyProperty="demoId" keyColumn="DEMOID">
             INSERT INTO TBL_DEMO (DEMONAME,DEMODESCRIPTION)
             VALUE (#{demoName},#{demoDescription})
             <selectKey keyProperty="demoId" resultType="int" order="AFTER">
              SELECT LAST_INSERT_ID();
             </selectKey>
          </insert>
      

      Java端

      @Override
      public boolean saveDemo(Demo demo) {
          boolean status = false;
          SqlSession session = this.sqlSessionFactory.openSession();
          try {
              DemoMapper mapper = session.getMapper(DemoMapper.class);
              mapper.saveDemo(demo);
              session.commit();
              status = true;
          } catch(PersistenceException e) {
              System.out.println(e);
          } finally {
              session.close();
          }
          return status;
      }
      

      【讨论】:

        【解决方案5】:

        对我来说它是这样工作的(mybatis 3.x).. mysql表中id必须设置自增

        <insert id="createEmpty" parameterType="Project" useGeneratedKeys="true" keyProperty="project.projectId" keyColumn="PROJECT_ID">
            INSERT INTO PROJECT (TITLE,DESCRIPTION)
            VALUES
            (#{title},#{description})
        </insert>
        

        NOTEkeyProperty="project.projectId"useGeneratedKeys="true"

        我的界面是:

        public int createEmpty(@Param("project") Project project, @Param("title") String title,
            @Param("description") String description);
        

        最后得到我使用的值(将自动分配给 pojo 的 id 属性):

        projectRepository.createEmpty(p, "one", "two");
        System.err.print(p.getProjectId() + "\n");
        

        【讨论】:

        • 你应该从 keyProperty="project.projectId" 中删除对象名称,这里是项目
        • @HumoyunAhmad 从 keyProperty 值中删除参数名称(即:keyProperty="projectId")导致 id 属性未填充。我使用的是 Mybatis 3.4.5 版本。
        • 这个答案听起来很奇怪。我想知道如何简单地返回一个像 int 这样的值。就像在 T-SQL 中一样,您会编写类似 OUTPUT Inserted.id 的内容。现在我们正在传递项目对象,以便它可以接收我们可以使用 getProjectId() 检索的 id;为什么我们不事先填充项目的标题和描述,只将项目对象传递给 create 方法......这在这种情况下是可行的,但对我来说这似乎不太正确。
        【解决方案6】:

        简单的解决方案:

        使用KeyProperty 属性作为objectName.AutoincrementId 如下图...

        useGeneratedKeys="true", KeyProperty="person.id", KeyColumn="id"

        【讨论】:

          【解决方案7】:

          请按以下步骤操作:

          1. 使用 id 作为属性创建错误 POJO

          2. 将returnId替换为错误如下,

          public void insertRecord(@Param("error") 错误错误, @Param("timestamp")Timestamp 时间戳,@Param("type") 字符串 type,@Param("message") String message,@Param("source") String source);

          1. 将 keyProperty="ID_ERROR" 更改为 keyProperty="error.id"

          2. 删除

            <selectKey resultType="long" order="AFTER" keyProperty="returnedId">
                SELECT LAST_INSERT_ID() as returnedId
            </selectKey>
            

          您将在error.id 中插入id

          【讨论】:

          • 除了错误 ID 之外,永远不要使用 error.id。像这样的黑客使代码变得肮脏和不可读
          【解决方案8】:

          如果你想得到生成的主键,你应该通过MapPOJO Object传递参数

          public void insertRecord(Map<String, Object> map);
          

          调用映射方法时,将值放入映射中。

          Map<String, Object> map = new HashMap<String, Object>();
          map.put("returnedId", 0);
          map.put("message", message);
          // other paramters
          mapper.insertRecord(map);
          return map.get("returnedId");
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2013-09-05
            • 1970-01-01
            • 1970-01-01
            • 2012-05-22
            • 1970-01-01
            • 1970-01-01
            • 2013-05-28
            • 1970-01-01
            相关资源
            最近更新 更多