@TableGenerator for mybatis

时间:2019-07-15 20:49:40

标签: java mybatis

我在EclipseLink上成功使用了@TableGenerator:

@Id
@TableGenerator(name = "ID_GEN",
        table = "seq",
        pkColumnName = "seqName",
        valueColumnName = "`id`",
        pkColumnValue = "SEQUENCE")
@GeneratedValue(strategy = GenerationType.TABLE, generator = "ID_GEN")
private Long id;

我正在搜索Mybatis是否有相同的可能性来完成相同的结果,但是我唯一看到的是对generateKey的引用:

http://www.mybatis.org/generator/configreference/generatedKey.html#

下面的语句(来自上面的链接)指的是一些可能的“序列”,这使我认为可能存在一种使用相同类型的序列表来实现此目的的方法。

“该元素用于指定自动生成的键的属性(来自标识字段或序列)。”

在Mybatis中可以使用此@ GeneratedValue / @ TableGenerator机制吗?

任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:0)

@TableGenerator是JPA的功能。在后台,JPA实现发出多个查询以生成值。 mybatis不会执行此操作,也就是说,它不会执行您未明确指定的任何查询,因此没有简单和声明性的方法来实现与@TableGenerator相同的功能。您将需要模拟休眠模式对序列表的查询。

在mybatis中,您可以使用selectKey来生成值。

以下是对documentation的模仿GenerationType.SEQUENCE策略的示例:

<insert id="insertAuthor">
  <selectKey keyProperty="id" resultType="int" order="BEFORE">
    select nextval('author_id_seq') 
  </selectKey>
  insert into Author
    (id, username, password, email,bio, favourite_section)
  values
    (#{id}, #{username}, #{password}, #{email}, #{bio}, #{favouriteSection,jdbcType=VARCHAR})
</insert>

selectKey部分中,可以指定任意查询。在这种情况下,结果将被分配给keyProperty中指定的属性,该属性是传递对象的id

模拟@TableGenerator策略GenerationType.TABLE的实际查询取决于数据库。对于Postgresql,selectKey中的查询将类似于:

INSERT INTO seq (seqName, id) values ('SEQUENCE', 1)
ON CONFLICT
 DO UPDATE id = id + 1
 WHERE seqName = 'SEQUENCE'
RETURNING id

答案 1 :(得分:0)

最后,我实现了一个自定义id生成器序列管理器,以实现mybatis中的GenerationType.TABLE行为:

@Mapper
public interface ReadOnly {

    @Select("SELECT `index` from sequence WHERE sequenceName = #{sequenceName}")
    Long getNextIndex(@Param("sequenceName") String sequenceName);
}

@Mapper
public interface ReadWrite {

    @Update("UPDATE sequence SET `index` = #{index} WHERE (sequenceName = #{sequenceName})")
    void updateIndex(@Param("index") long index, @Param("sequenceName") String sequenceName);


@Component
public class SequenceManager {

    @Autowired
    ReadOnly readonly;

    @Autowired
    ReadWrite readwrite;

    private long index = 0;

    private static long blockSize = 10;

    public SequenceManager() {
    }

    public long getNextIndex(String sequenceName) {
        if (index % blockSize == 0) {
            index = getAfterIncrement(sequenceName);
        }
        return index++;
    }

    @Transactional
    public long getAfterIncrement(String sequenceName) {
        index = readonly.getNextIndex(sequenceName);
        readwrite.updateIndex(index + blockSize, sequenceName);
        return index + blockSize;
    }
}

谢谢大家对此的帮助。