【问题标题】:How to return ids on Inserts with mybatis in mysql with annotations如何在带有注释的mysql中使用mybatis返回插入的id
【发布时间】:2021-08-30 13:39:35
【问题描述】:
  • See this related question 用于 Postgres。出于某种原因,该解决方案对我不起作用 - 插入语句的返回值始终为“1”。
  • 请参阅此其他问题以获取 XML based solution。我想在没有 XML 的情况下做同样的事情 - 插入一条记录并找到我刚刚插入的记录的新自动生成的 id。

我没有找到与<selectkey> 匹配的注释(请参阅此open issue) 我该如何进行?

查看mybatis代码发现INSERT是通过UPDATE实现的,总是返回插入的行数!所以......除非我在这里完全遗漏了一些东西,否则没有办法使用当前的(3.0.3)实现来做到这一点。

【问题讨论】:

    标签: java mysql mybatis


    【解决方案1】:

    实际上,可以通过 @Options 注释来做到这一点(前提是您在数据库中使用 auto_increment 或类似的东西):

    @Insert("insert into table3 (id, name) values(null, #{name})") 
    @Options(useGeneratedKeys=true, keyProperty="idName")
    int insertTable3(SomeBean myBean); 
    

    请注意,如果 SomeBean 中的 key 属性名为“id”,则不需要 keyProperty="idName" 部分。还有一个keyColumn 属性可用,用于MyBatis 自己找不到主键列的极少数情况。另请注意,通过使用@Options,您将您的方法提交给一些默认参数;查阅文档很重要(链接如下——当前版本的第 60 页)!

    (旧答案)(相当新的)@SelectKey 注释可用于更复杂的密钥检索(序列、identity() 函数...)。以下是MyBatis 3 User Guide (pdf) 提供的示例:

    这个例子展示了使用@SelectKey 注解从一个序列中检索一个值之前 插入:

    @Insert("insert into table3 (id, name) values(#{nameId}, #{name})") 
    @SelectKey(statement="call next value for TestSequence", keyProperty="nameId", before=true, resultType=int.class) 
    int insertTable3(Name name); 
    

    这个例子展示了使用@SelectKey 注解在插入之后检索一个标识值:

    @Insert("insert into table2 (name) values(#{name})")
    @SelectKey(statement="call identity()", keyProperty="nameId", before=false, resultType=int.class)
    int insertTable2(Name name);
    

    【讨论】:

      【解决方案2】:

      <insert><update><delete> 语句返回受影响的行数,这在数据库 API 中很常见。

      如果为插入的行生成了新的 ID,它会反映在您作为参数传递的对象中。因此,例如,如果您在带注释的插入方法中调用 mapper.insert(someObject),则插入后,您可以调用 someObject.getId(或类似方法)来检索它。

      使用<insert> 的选项,您可以调整生成或检索 id 的方式(通过提供 SQL 语句)和时间(在实际插入之前或之后),以及将其放置在对象中的位置。

      使用MyBatis generator 从数据库模式生成类并了解如何处理插入和更新可能很有指导意义。具体来说,生成器会生成“示例”类,这些类用作临时容器来传递数据。

      【讨论】:

        【解决方案3】:

        您可以从保存方法中获取生成的 ID, 假设一个具有 ID 和名称属性的 bean,

        bean.setName("xxx");
        mapper.save(bean);
        // here is your id
        logger.debug(bean.getID);
        

        【讨论】:

        • 假设您使用注释进行选择和@Options(useGeneratedKeys=true)
        【解决方案4】:

        我不喜欢我在网上找到的大多数返回生成密钥的答案,因为

        1. 我发现的所有解决方案都称为入站对象的“setter”
        2. 没有一个解决方案返回该方法生成的列

        我想出了以下解决方案,它解决了上面的第 1 点和第 2 点

        1. 将两个参数传递给 mybatis "in" & "out"(mybatis 不会改变 "in",它会在 "out" 上调用 setter)
        2. 需要在接口上额外添加default method 才能返回值
        public interface MyMapper {
           /**
            * this method is used by the mybatis mapper
            * I don't call this method directly in my application code   
            */
           @Insert("INSERT INTO MY_TABLE (FOO) VALUES ({#in.foo})")
           @Options(useGeneratedKeys=true, keyColumn="ID", keyProperty = "out.value")
           void insert(@Param("in") MyTable in, @Param("out") LongReference out);
        
           /**
             * this "default method" is called in my application code and returns the generated id.
             */
           default long insert(MyTable tableBean) {
              LongReference idReference = new LongReference();
              insert(tableBean, idReference);
              return idReference.getValue();
           }
        }
        

        这需要一个额外的类,将来可以在类似的方法上重复使用

        public class LongReference {
            private Long value;
        
            // getter & setter
        }
        
        

        【讨论】:

          猜你喜欢
          • 2010-12-18
          • 1970-01-01
          • 2013-06-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多