MySQLってシーケンスオブジェクトないんですね・・。auto_increment列使えよ〜ということなのかな?
軽くググってみると・・・LAST_INSERT_ID関数を使うとシーケンスっぽいことできるよ〜という記事がちらほら見つかりました。どうやら、この方法は公式のドキュメントでも紹介されている方法のようです。
検証バージョン
- MySQL 8.0
- MyBatis 3.5.6
テーブルを作る
create table sequence (
name varchar(50) primary key,
value bigint
) ENGINE=MyISAM;
NOTE:
ENGINE=MyISAMにするとロールバックの影響を受けない(=ロールバックしても番号が戻らない)ようにすることができる見たいです(MyISAMがトランザクションをサポートしていないからのようです)。
Mapperを作る
@Mapper
public interface SequenceMapper {
@Insert("INSERT INTO sequence (name, value) VALUES(#{name}, LAST_INSERT_ID(1)) " +
"ON DUPLICATE KEY UPDATE value = LAST_INSERT_ID(value + 1)")
@SelectKey(statement = "SELECT LAST_INSERT_ID()", keyProperty = "value", before = false, resultType = long.class)
void incrementAndGet(Sequence sequence);
default long nextSequence(String name) {
Sequence sequence = new Sequence();
sequence.name = name;
incrementAndGet(sequence);
return sequence.value;
}
class Sequence {
private String name;
private long value;
}
}
シーケンス値を取得する
@SpringBootTest
class MyTest {
@Autowired
SequenceMapper sequenceMapper;
@Test
void test() {
Assertions.assertThat(sequenceMapper.nextSequence("file_id")).isEqualTo(1L);
Assertions.assertThat(sequenceMapper.nextSequence("file_id")).isEqualTo(2L);
Assertions.assertThat(sequenceMapper.nextSequence("order_id")).isEqualTo(1L);
Assertions.assertThat(sequenceMapper.nextSequence("order_id")).isEqualTo(2L);
}
}