From 70a3b0641f82287e220d1413378f0cdb7e2be229 Mon Sep 17 00:00:00 2001
From: joyyizhang <joyyizhang@tencent.com>
Date: Mon, 16 Jan 2023 19:38:06 +0800
Subject: [PATCH 1/4] more -

---
 go.mod        | 30 ++++++++++++++++++++++++++++--
 go.sum        | 27 +++++++++++++++++++++++++++
 transition.go |  2 +-
 3 files changed, 56 insertions(+), 3 deletions(-)

diff --git a/go.mod b/go.mod
index 598e388..aed9189 100644
--- a/go.mod
+++ b/go.mod
@@ -1,6 +1,6 @@
-module github.com/qor/transition
+module github.com/joykk/transition
 
-go 1.13
+go 1.18
 
 require (
 	github.com/jinzhu/gorm v1.9.16
@@ -9,4 +9,30 @@ require (
 	github.com/qor/audited v0.0.0-20171228121055-b52c9c2f0571
 	github.com/qor/qor v0.0.0-20200729071734-d587cffbbb93
 	github.com/qor/roles v0.0.0-20201008080147-dcaf8a4646d8
+	github.com/qor/transition v0.0.0-20201010035849-dcb875909eb7
+)
+
+require (
+	github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535 // indirect
+	github.com/aymerick/douceur v0.2.0 // indirect
+	github.com/chris-ramon/douceur v0.2.0 // indirect
+	github.com/go-sql-driver/mysql v1.5.0 // indirect
+	github.com/gorilla/context v1.1.1 // indirect
+	github.com/gorilla/css v1.0.0 // indirect
+	github.com/gorilla/securecookie v1.1.1 // indirect
+	github.com/gorilla/sessions v1.2.0 // indirect
+	github.com/gosimple/slug v1.9.0 // indirect
+	github.com/jinzhu/inflection v1.0.0 // indirect
+	github.com/jinzhu/now v1.1.1 // indirect
+	github.com/lib/pq v1.8.0 // indirect
+	github.com/microcosm-cc/bluemonday v1.0.3 // indirect
+	github.com/qor/assetfs v0.0.0-20170713023933-ff57fdc13a14 // indirect
+	github.com/qor/middlewares v0.0.0-20170822143614-781378b69454 // indirect
+	github.com/qor/responder v0.0.0-20171031032654-b6def473574f // indirect
+	github.com/qor/session v0.0.0-20170907035918-8206b0adab70 // indirect
+	github.com/qor/validations v0.0.0-20171228122639-f364bca61b46 // indirect
+	github.com/rainycape/unidecode v0.0.0-20150907023854-cb7f23ec59be // indirect
+	github.com/theplant/cldr v0.0.0-20190423050709-9f76f7ce4ee8 // indirect
+	golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e // indirect
+	gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
 )
diff --git a/go.sum b/go.sum
index 774c26f..1992192 100644
--- a/go.sum
+++ b/go.sum
@@ -1,4 +1,5 @@
 github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
+github.com/andybalholm/cascadia v1.1.0 h1:BuuO6sSfQNFRu1LppgbD25Hr2vLYW25JvxHs5zzsLTo=
 github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
 github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535 h1:4daAzAu0S6Vi7/lbWECcX0j45yZReDZ56BQsrVBOEEY=
 github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg=
@@ -6,12 +7,17 @@ github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuP
 github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
 github.com/chris-ramon/douceur v0.2.0 h1:IDMEdxlEUUBYBKE4z/mJnFyVXox+MjuEVDJNN27glkU=
 github.com/chris-ramon/douceur v0.2.0/go.mod h1:wDW5xjJdeoMm1mRt4sD4c/LbF/mWdEpRXQKjTR8nIBE=
+github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd h1:83Wprp6ROGeiHFAP8WJdI2RoxALQYgdllERc3N5N2DM=
 github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
+github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c=
 github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4=
+github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 h1:Yzb9+7DPaBjB8zlTR87/ElzFsnQfuHnVUVqpZZIcV5Y=
 github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0=
+github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s=
 github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
 github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
 github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
+github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=
 github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
 github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8=
 github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
@@ -31,17 +37,25 @@ github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkr
 github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
 github.com/jinzhu/now v1.1.1 h1:g39TucaRWyV3dwDO++eEc6qf8TVIQ/Da48WmqjZ3i7E=
 github.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
+github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
+github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
+github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
+github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
+github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
 github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
 github.com/lib/pq v1.8.0 h1:9xohqzkUwzR4Ga4ivdTcawVS89YSDVxXMa3xJX3cGzg=
 github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
+github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA=
 github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
 github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
+github.com/mattn/go-isatty v0.0.11 h1:FxPOTFNqGkuDUGi3H/qkUbQO4ZiBa2brKq5r0l8TGeM=
 github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
 github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus=
 github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U=
 github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
 github.com/microcosm-cc/bluemonday v1.0.3 h1:EjVH7OqbU219kdm8acbveoclh2zZFqPJTJw6VUlTLAQ=
 github.com/microcosm-cc/bluemonday v1.0.3/go.mod h1:8iwZnFn2CDDNZ0r6UXhF4xawGvzaqzCRa1n3/lO3W2w=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/qor/admin v0.0.0-20200908023436-0c0a0b041c88 h1:fMtNHN6WgFSfFZ+ZXpnJW62h4kZ+jsk1/WIsnPX9GuE=
 github.com/qor/admin v0.0.0-20200908023436-0c0a0b041c88/go.mod h1:TiMo/I9p4pjVFtLI8+ellx2YbeiirVYcoh5UrQc9v9I=
@@ -49,9 +63,11 @@ github.com/qor/assetfs v0.0.0-20170713023933-ff57fdc13a14 h1:JRpyNNSRAkwNHd4WgyP
 github.com/qor/assetfs v0.0.0-20170713023933-ff57fdc13a14/go.mod h1:GZSCP3jIneuPsav3pXmpmJwz9ES+Fuq4ZPOUC3wwckQ=
 github.com/qor/audited v0.0.0-20171228121055-b52c9c2f0571 h1:87fy9oxrDUTN77K9VwHkmyNynRYl+Kn7HkX2HZbQYrE=
 github.com/qor/audited v0.0.0-20171228121055-b52c9c2f0571/go.mod h1:XQ/SY+Bgd2pHTAQhsSwN7KoCJSr8jJVnUqDMPk9rhYk=
+github.com/qor/media v0.0.0-20200720100650-60c52edf57cb h1:LgWyG2gPmfiEukIo0yjlQ93oWWyTbmvX04rcOs4SDtk=
 github.com/qor/media v0.0.0-20200720100650-60c52edf57cb/go.mod h1:hzx9cTt5MpROMVIhwNhRJETc7e3a1J4bLNYflkcQ1wk=
 github.com/qor/middlewares v0.0.0-20170822143614-781378b69454 h1:+WCc1IigwWpWBxMFsmLUsIF230TakGHstDajd8aKDAc=
 github.com/qor/middlewares v0.0.0-20170822143614-781378b69454/go.mod h1:PejEyg3hS+Toh5m0AKRv2jK5br8qIoHLqmHrpg0WJYg=
+github.com/qor/oss v0.0.0-20191031055114-aef9ba66bf76 h1:J2Xj92efYLxPl3BiibgEDEUiMsCBzwTurE/8JjD8CG4=
 github.com/qor/oss v0.0.0-20191031055114-aef9ba66bf76/go.mod h1:JhtPzUhP5KGtCB2yksmxuYAD4hEWw4qGQJpucjsm3U0=
 github.com/qor/qor v0.0.0-20200715033016-13227382be83/go.mod h1:oG+LgDEnsI9avcFFdczoZnBe3rw42s4cG433w6XpEig=
 github.com/qor/qor v0.0.0-20200729071734-d587cffbbb93 h1:kxseRCbX7NxSvKYSO1rXQCALzl3YLZvooxhhQdA23fU=
@@ -61,21 +77,29 @@ github.com/qor/responder v0.0.0-20171031032654-b6def473574f/go.mod h1:0TL2G+qGDY
 github.com/qor/roles v0.0.0-20171127035124-d6375609fe3e/go.mod h1:++RicL9Ia/BrQHppwAsMc5CA7mAjnBLNniB46MzUteA=
 github.com/qor/roles v0.0.0-20201008080147-dcaf8a4646d8 h1:Yv4gbXvj1JL/G4Ck4HPK7tz7gF42yntoiNINqd85NbU=
 github.com/qor/roles v0.0.0-20201008080147-dcaf8a4646d8/go.mod h1:++RicL9Ia/BrQHppwAsMc5CA7mAjnBLNniB46MzUteA=
+github.com/qor/serializable_meta v0.0.0-20180510060738-5fd8542db417 h1:dnqlvo4M/uR0KhB6Tyhsv6XbSokcpfwQ4ublD9D/PBQ=
 github.com/qor/serializable_meta v0.0.0-20180510060738-5fd8542db417/go.mod h1:ZhRkze6qCgCNNqisHEFTAkndoBtY/XJbA03LJLJrzDY=
 github.com/qor/session v0.0.0-20170907035918-8206b0adab70 h1:8l21EEdlZ9R0AA3FbeUAANc5NAx8Y3tn1VKbyAgjYlI=
 github.com/qor/session v0.0.0-20170907035918-8206b0adab70/go.mod h1:ldgcaca0ZGx6tFtd/w0ELq5jHD/KLJ1Lbdn8qhr/pQ0=
+github.com/qor/transition v0.0.0-20201010035849-dcb875909eb7 h1:046W/Dwt9pLHMRIEWLXfPML6J9uhYgBSBJaoDiJKeR0=
+github.com/qor/transition v0.0.0-20201010035849-dcb875909eb7/go.mod h1:ScGjxMdvT1OGwmASNhAKtKXeR1umsnPlYIzBcQE87ek=
 github.com/qor/validations v0.0.0-20171228122639-f364bca61b46 h1:dRlsVUhwD1pwrasuVbNooGQITYjKzmXK5eYoEEvBGQI=
 github.com/qor/validations v0.0.0-20171228122639-f364bca61b46/go.mod h1:UJsA0AuvrKNaWtrb1UzKai10mN3ZBbQkPjUHpxwahTc=
 github.com/rainycape/unidecode v0.0.0-20150907023854-cb7f23ec59be h1:ta7tUOvsPHVHGom5hKW5VXNc2xZIkfCKP8iaqOyYtUQ=
 github.com/rainycape/unidecode v0.0.0-20150907023854-cb7f23ec59be/go.mod h1:MIDFMn7db1kT65GmV94GzpX9Qdi7N/pQlwb+AN8wh+Q=
 github.com/theplant/cldr v0.0.0-20190423050709-9f76f7ce4ee8 h1:di0cR5qqo2DllBMwmP75kZpUX6dAXhsn1O2dshQfMaA=
 github.com/theplant/cldr v0.0.0-20190423050709-9f76f7ce4ee8/go.mod h1:MIL7SmF8wRAYDn+JexczVRUiJXTCi4VbQavsCKWKwXI=
+github.com/theplant/htmltestingutils v0.0.0-20190423050759-0e06de7b6967 h1:yPrgtU8bj7Q/XbXgjjmngZtOhsUufBAraruNwxv/eXM=
 github.com/theplant/htmltestingutils v0.0.0-20190423050759-0e06de7b6967/go.mod h1:86iN4EAYaQbx1VTW5uPslTIviRkYH8CzslMC//g+BgY=
+github.com/theplant/testingutils v0.0.0-20190603093022-26d8b4d95c61 h1:757/ruZNgTsOf5EkQBo0i3Bx/P2wgF5ljVkODeUX/uA=
 github.com/theplant/testingutils v0.0.0-20190603093022-26d8b4d95c61/go.mod h1:p22Q3Bg5ML+hdI3QSQkB/pZ2+CjfOnGugoQIoyE2Ub8=
+github.com/yosssi/gohtml v0.0.0-20200519115854-476f5b4b8047 h1:YWaOkupKL+BRRJSWRq/uhSkWXc1K0QVIYVG36XUBGOc=
 github.com/yosssi/gohtml v0.0.0-20200519115854-476f5b4b8047/go.mod h1:+ccdNT0xMY1dtc5XBxumbYfOUhmduiGudqaDgD2rVRE=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd h1:GGJVjV8waZKRHrgwvtH66z9ZGVurTD1MT0n1Bb+q4aM=
 golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8 h1:hVwzHzIUGRjiF7EcUjqNxk3NCfkPxbDKRdnNE1Rpg0U=
 golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
 golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -87,5 +111,8 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h
 golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
 golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
diff --git a/transition.go b/transition.go
index 8fd0d81..25b8819 100644
--- a/transition.go
+++ b/transition.go
@@ -13,7 +13,7 @@ import (
 // Transition is a struct, embed it in your struct to enable state machine for the struct
 type Transition struct {
 	State           string
-	StateChangeLogs []StateChangeLog `sql:"-"`
+	StateChangeLogs []StateChangeLog `sql:"-" gorm:"-"`
 }
 
 // SetState set state to Stater, just set, won't save it into database

From ff2b007c5413c54ba66d0d9cdb935989dac31c98 Mon Sep 17 00:00:00 2001
From: joyyizhang <joyyizhang@tencent.com>
Date: Fri, 5 May 2023 13:55:39 +0800
Subject: [PATCH 2/4] add ok

---
 .gitignore          |   1 +
 go.mod              |  23 ++++++---
 go.sum              |  40 +++++++++++---
 state_change_log.go |  72 +++++++++++++++++---------
 transition.go       |  37 +++++++------
 transition_test.go  | 123 ++++++++++++++++++++++++++++++++++----------
 6 files changed, 217 insertions(+), 79 deletions(-)
 create mode 100644 .gitignore

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..7c0f65c
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+/gorm.db
diff --git a/go.mod b/go.mod
index aed9189..931da46 100644
--- a/go.mod
+++ b/go.mod
@@ -1,30 +1,35 @@
-module github.com/joykk/transition
+module github.com/qor/transition
 
 go 1.18
 
 require (
-	github.com/jinzhu/gorm v1.9.16
+	github.com/glebarez/sqlite v1.8.0
 	github.com/mattn/go-sqlite3 v2.0.3+incompatible
 	github.com/qor/admin v0.0.0-20200908023436-0c0a0b041c88
 	github.com/qor/audited v0.0.0-20171228121055-b52c9c2f0571
 	github.com/qor/qor v0.0.0-20200729071734-d587cffbbb93
 	github.com/qor/roles v0.0.0-20201008080147-dcaf8a4646d8
-	github.com/qor/transition v0.0.0-20201010035849-dcb875909eb7
+	gorm.io/driver/mysql v1.5.0
+	gorm.io/gorm v1.25.0
 )
 
 require (
 	github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535 // indirect
 	github.com/aymerick/douceur v0.2.0 // indirect
 	github.com/chris-ramon/douceur v0.2.0 // indirect
-	github.com/go-sql-driver/mysql v1.5.0 // indirect
+	github.com/dustin/go-humanize v1.0.1 // indirect
+	github.com/glebarez/go-sqlite v1.21.1 // indirect
+	github.com/go-sql-driver/mysql v1.7.0 // indirect
+	github.com/google/uuid v1.3.0 // indirect
 	github.com/gorilla/context v1.1.1 // indirect
 	github.com/gorilla/css v1.0.0 // indirect
 	github.com/gorilla/securecookie v1.1.1 // indirect
 	github.com/gorilla/sessions v1.2.0 // indirect
 	github.com/gosimple/slug v1.9.0 // indirect
+	github.com/jinzhu/gorm v1.9.16 // indirect
 	github.com/jinzhu/inflection v1.0.0 // indirect
-	github.com/jinzhu/now v1.1.1 // indirect
-	github.com/lib/pq v1.8.0 // indirect
+	github.com/jinzhu/now v1.1.5 // indirect
+	github.com/mattn/go-isatty v0.0.17 // indirect
 	github.com/microcosm-cc/bluemonday v1.0.3 // indirect
 	github.com/qor/assetfs v0.0.0-20170713023933-ff57fdc13a14 // indirect
 	github.com/qor/middlewares v0.0.0-20170822143614-781378b69454 // indirect
@@ -32,7 +37,13 @@ require (
 	github.com/qor/session v0.0.0-20170907035918-8206b0adab70 // indirect
 	github.com/qor/validations v0.0.0-20171228122639-f364bca61b46 // indirect
 	github.com/rainycape/unidecode v0.0.0-20150907023854-cb7f23ec59be // indirect
+	github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
 	github.com/theplant/cldr v0.0.0-20190423050709-9f76f7ce4ee8 // indirect
 	golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e // indirect
+	golang.org/x/sys v0.4.0 // indirect
 	gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
+	modernc.org/libc v1.22.3 // indirect
+	modernc.org/mathutil v1.5.0 // indirect
+	modernc.org/memory v1.5.0 // indirect
+	modernc.org/sqlite v1.21.1 // indirect
 )
diff --git a/go.sum b/go.sum
index 1992192..e7a670b 100644
--- a/go.sum
+++ b/go.sum
@@ -11,14 +11,24 @@ github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd h1:83Wprp6RO
 github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
 github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c=
 github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4=
+github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
+github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
 github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 h1:Yzb9+7DPaBjB8zlTR87/ElzFsnQfuHnVUVqpZZIcV5Y=
 github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0=
 github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s=
 github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
-github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
+github.com/glebarez/go-sqlite v1.21.1 h1:7MZyUPh2XTrHS7xNEHQbrhfMZuPSzhkm2A1qgg0y5NY=
+github.com/glebarez/go-sqlite v1.21.1/go.mod h1:ISs8MF6yk5cL4n/43rSOmVMGJJjHYr7L2MbZZ5Q4E2E=
+github.com/glebarez/sqlite v1.8.0 h1:02X12E2I/4C1n+v90yTqrjRa8yuo7c3KeHI3FRznCvc=
+github.com/glebarez/sqlite v1.8.0/go.mod h1:bpET16h1za2KOOMb8+jCp6UBP/iahDpfPQqSaYLTLx8=
 github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
+github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc=
+github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
 github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=
 github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
+github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ=
+github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
+github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8=
 github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
 github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY=
@@ -35,8 +45,9 @@ github.com/jinzhu/gorm v1.9.16/go.mod h1:G3LB3wezTOWM2ITLzPxEXgSkOXAntiLHS7UdBef
 github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
 github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
 github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
-github.com/jinzhu/now v1.1.1 h1:g39TucaRWyV3dwDO++eEc6qf8TVIQ/Da48WmqjZ3i7E=
 github.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
+github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
+github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
 github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
 github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
 github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
@@ -48,8 +59,9 @@ github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
 github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA=
 github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
 github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
-github.com/mattn/go-isatty v0.0.11 h1:FxPOTFNqGkuDUGi3H/qkUbQO4ZiBa2brKq5r0l8TGeM=
 github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
+github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
+github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
 github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus=
 github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U=
 github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
@@ -81,12 +93,13 @@ github.com/qor/serializable_meta v0.0.0-20180510060738-5fd8542db417 h1:dnqlvo4M/
 github.com/qor/serializable_meta v0.0.0-20180510060738-5fd8542db417/go.mod h1:ZhRkze6qCgCNNqisHEFTAkndoBtY/XJbA03LJLJrzDY=
 github.com/qor/session v0.0.0-20170907035918-8206b0adab70 h1:8l21EEdlZ9R0AA3FbeUAANc5NAx8Y3tn1VKbyAgjYlI=
 github.com/qor/session v0.0.0-20170907035918-8206b0adab70/go.mod h1:ldgcaca0ZGx6tFtd/w0ELq5jHD/KLJ1Lbdn8qhr/pQ0=
-github.com/qor/transition v0.0.0-20201010035849-dcb875909eb7 h1:046W/Dwt9pLHMRIEWLXfPML6J9uhYgBSBJaoDiJKeR0=
-github.com/qor/transition v0.0.0-20201010035849-dcb875909eb7/go.mod h1:ScGjxMdvT1OGwmASNhAKtKXeR1umsnPlYIzBcQE87ek=
 github.com/qor/validations v0.0.0-20171228122639-f364bca61b46 h1:dRlsVUhwD1pwrasuVbNooGQITYjKzmXK5eYoEEvBGQI=
 github.com/qor/validations v0.0.0-20171228122639-f364bca61b46/go.mod h1:UJsA0AuvrKNaWtrb1UzKai10mN3ZBbQkPjUHpxwahTc=
 github.com/rainycape/unidecode v0.0.0-20150907023854-cb7f23ec59be h1:ta7tUOvsPHVHGom5hKW5VXNc2xZIkfCKP8iaqOyYtUQ=
 github.com/rainycape/unidecode v0.0.0-20150907023854-cb7f23ec59be/go.mod h1:MIDFMn7db1kT65GmV94GzpX9Qdi7N/pQlwb+AN8wh+Q=
+github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
+github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
+github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
 github.com/theplant/cldr v0.0.0-20190423050709-9f76f7ce4ee8 h1:di0cR5qqo2DllBMwmP75kZpUX6dAXhsn1O2dshQfMaA=
 github.com/theplant/cldr v0.0.0-20190423050709-9f76f7ce4ee8/go.mod h1:MIL7SmF8wRAYDn+JexczVRUiJXTCi4VbQavsCKWKwXI=
 github.com/theplant/htmltestingutils v0.0.0-20190423050759-0e06de7b6967 h1:yPrgtU8bj7Q/XbXgjjmngZtOhsUufBAraruNwxv/eXM=
@@ -111,8 +124,23 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h
 golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
 golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18=
+golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
+gorm.io/driver/mysql v1.5.0 h1:6hSAT5QcyIaty0jfnff0z0CLDjyRgZ8mlMHLqSt7uXM=
+gorm.io/driver/mysql v1.5.0/go.mod h1:FFla/fJuCvyTi7rJQd27qlNX2v3L6deTR1GgTjSOLPo=
+gorm.io/gorm v1.24.7-0.20230306060331-85eaf9eeda11/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
+gorm.io/gorm v1.25.0 h1:+KtYtb2roDz14EQe4bla8CbQlmb9dN3VejSai3lprfU=
+gorm.io/gorm v1.25.0/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
+modernc.org/libc v1.22.3 h1:D/g6O5ftAfavceqlLOFwaZuA5KYafKwmr30A6iSqoyY=
+modernc.org/libc v1.22.3/go.mod h1:MQrloYP209xa2zHome2a8HLiLm6k0UT8CoHpV74tOFw=
+modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ=
+modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
+modernc.org/memory v1.5.0 h1:N+/8c5rE6EqugZwHii4IFsaJ7MUhoWX07J5tC/iI5Ds=
+modernc.org/memory v1.5.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU=
+modernc.org/sqlite v1.21.1 h1:GyDFqNnESLOhwwDRaHGdp2jKLDzpyT/rNLglX3ZkMSU=
+modernc.org/sqlite v1.21.1/go.mod h1:XwQ0wZPIh1iKb5mkvCJ3szzbhk+tykC8ZWqTRTgYRwI=
diff --git a/state_change_log.go b/state_change_log.go
index f4a2beb..62743c4 100644
--- a/state_change_log.go
+++ b/state_change_log.go
@@ -1,10 +1,11 @@
 package transition
 
 import (
-	"fmt"
+	gormv2 "gorm.io/gorm"
+	"gorm.io/gorm/schema"
 	"strings"
+	"sync"
 
-	"github.com/jinzhu/gorm"
 	"github.com/qor/admin"
 	"github.com/qor/audited"
 	"github.com/qor/qor/resource"
@@ -13,7 +14,7 @@ import (
 
 // StateChangeLog a model that used to keep state change logs
 type StateChangeLog struct {
-	gorm.Model
+	gormv2.Model
 	ReferTable string
 	ReferID    string
 	From       string
@@ -22,44 +23,67 @@ type StateChangeLog struct {
 	audited.AuditedModel
 }
 
-// GenerateReferenceKey generate reference key used for change log
-func GenerateReferenceKey(model interface{}, db *gorm.DB) string {
-	var (
-		scope         = db.NewScope(model)
-		primaryValues []string
-	)
+var tableColumn = &sync.Map{}
 
-	for _, field := range scope.PrimaryFields() {
-		primaryValues = append(primaryValues, fmt.Sprint(field.Field.Interface()))
+// GenerateReferenceKey generate reference key used for change log
+func GenerateReferenceKey(model interface{}, db *gormv2.DB) (string, error) {
+	ss, err := schema.Parse(model, tableColumn, db.NamingStrategy)
+	if err != nil {
+		return "", err
 	}
+	var primaryValues []string
+	for _, field := range ss.Fields {
+		if field.PrimaryKey {
+			primaryValues = append(primaryValues, field.Name)
+		}
+	}
+	resStr := strings.Join(primaryValues, "::")
+	return resStr, nil
+}
 
-	return strings.Join(primaryValues, "::")
+// GenTableName table name
+func GenTableName(model interface{}, db *gormv2.DB) (string, error) {
+	ss, err := schema.Parse(model, tableColumn, db.NamingStrategy)
+	if err != nil {
+		return "", err
+	}
+	return ss.Table, nil
 }
 
 // GetStateChangeLogs get state change logs
-func GetStateChangeLogs(model interface{}, db *gorm.DB) []StateChangeLog {
+func GetStateChangeLogs(model interface{}, db *gormv2.DB) ([]StateChangeLog, error) {
 	var (
 		changelogs []StateChangeLog
-		scope      = db.NewScope(model)
 	)
-
-	db.Where("refer_table = ? AND refer_id = ?", scope.TableName(), GenerateReferenceKey(model, db)).Find(&changelogs)
-
-	return changelogs
+	tableName, err := GenTableName(model, db)
+	if err != nil {
+		return nil, err
+	}
+	key, err := GenerateReferenceKey(model, db)
+	if err != nil {
+		return nil, err
+	}
+	return changelogs, db.Where("refer_table = ? AND refer_id = ?", tableName, key).Find(&changelogs).Error
 }
 
 // GetLastStateChange gets last state change
-func GetLastStateChange(model interface{}, db *gorm.DB) *StateChangeLog {
+func GetLastStateChange(model interface{}, db *gormv2.DB) (*StateChangeLog, error) {
 	var (
 		changelog StateChangeLog
-		scope      = db.NewScope(model)
 	)
-
-	db.Where("refer_table = ? AND refer_id = ?", scope.TableName(), GenerateReferenceKey(model, db)).Last(&changelog)
+	tableName, err := GenTableName(model, db)
+	if err != nil {
+		return nil, err
+	}
+	key, err := GenerateReferenceKey(model, db)
+	if err != nil {
+		return nil, err
+	}
+	db.Where("refer_table = ? AND refer_id = ?", tableName, key).Last(&changelog)
 	if changelog.To == "" {
-		return nil
+		return nil, nil
 	}
-	return &changelog
+	return &changelog, nil
 }
 
 // ConfigureQorResource used to configure transition for qor admin
diff --git a/transition.go b/transition.go
index 25b8819..851f5d9 100644
--- a/transition.go
+++ b/transition.go
@@ -2,9 +2,9 @@ package transition
 
 import (
 	"fmt"
+	gormv2 "gorm.io/gorm"
 	"strings"
 
-	"github.com/jinzhu/gorm"
 	"github.com/qor/admin"
 	"github.com/qor/qor/resource"
 	"github.com/qor/roles"
@@ -68,14 +68,14 @@ func (sm *StateMachine) Event(name string) *Event {
 }
 
 // Trigger trigger an event
-func (sm *StateMachine) Trigger(name string, value Stater, tx *gorm.DB, notes ...string) error {
+func (sm *StateMachine) Trigger(name string, value Stater, tx *gormv2.DB, notes ...string) error {
 	var (
-		newTx    *gorm.DB
+		newTx    *gormv2.DB
 		stateWas = value.GetState()
 	)
 
 	if tx != nil {
-		newTx = tx.New()
+		newTx = tx.Session(&gormv2.Session{NewDB: true})
 	}
 
 	if stateWas == "" {
@@ -140,10 +140,17 @@ func (sm *StateMachine) Trigger(name string, value Stater, tx *gorm.DB, notes ..
 			}
 
 			if newTx != nil {
-				scope := newTx.NewScope(value)
+				referID, err := GenerateReferenceKey(value, tx)
+				if err != nil {
+					return err
+				}
+				referTable, err := GenTableName(value, tx)
+				if err != nil {
+					return err
+				}
 				log := StateChangeLog{
-					ReferTable: scope.TableName(),
-					ReferID:    GenerateReferenceKey(value, tx),
+					ReferTable: referTable,
+					ReferID:    referID,
 					From:       stateWas,
 					To:         transition.to,
 					Note:       strings.Join(notes, ""),
@@ -160,18 +167,18 @@ func (sm *StateMachine) Trigger(name string, value Stater, tx *gorm.DB, notes ..
 // State contains State information, including enter, exit hooks
 type State struct {
 	Name   string
-	enters []func(value interface{}, tx *gorm.DB) error
-	exits  []func(value interface{}, tx *gorm.DB) error
+	enters []func(value interface{}, tx *gormv2.DB) error
+	exits  []func(value interface{}, tx *gormv2.DB) error
 }
 
 // Enter register an enter hook for State
-func (state *State) Enter(fc func(value interface{}, tx *gorm.DB) error) *State {
+func (state *State) Enter(fc func(value interface{}, tx *gormv2.DB) error) *State {
 	state.enters = append(state.enters, fc)
 	return state
 }
 
 // Exit register an exit hook for State
-func (state *State) Exit(fc func(value interface{}, tx *gorm.DB) error) *State {
+func (state *State) Exit(fc func(value interface{}, tx *gormv2.DB) error) *State {
 	state.exits = append(state.exits, fc)
 	return state
 }
@@ -193,8 +200,8 @@ func (event *Event) To(name string) *EventTransition {
 type EventTransition struct {
 	to      string
 	froms   []string
-	befores []func(value interface{}, tx *gorm.DB) error
-	afters  []func(value interface{}, tx *gorm.DB) error
+	befores []func(value interface{}, tx *gormv2.DB) error
+	afters  []func(value interface{}, tx *gormv2.DB) error
 }
 
 // From used to define from states
@@ -204,13 +211,13 @@ func (transition *EventTransition) From(states ...string) *EventTransition {
 }
 
 // Before register before hooks
-func (transition *EventTransition) Before(fc func(value interface{}, tx *gorm.DB) error) *EventTransition {
+func (transition *EventTransition) Before(fc func(value interface{}, tx *gormv2.DB) error) *EventTransition {
 	transition.befores = append(transition.befores, fc)
 	return transition
 }
 
 // After register after hooks
-func (transition *EventTransition) After(fc func(value interface{}, tx *gorm.DB) error) *EventTransition {
+func (transition *EventTransition) After(fc func(value interface{}, tx *gormv2.DB) error) *EventTransition {
 	transition.afters = append(transition.afters, fc)
 	return transition
 }
diff --git a/transition_test.go b/transition_test.go
index 1ebd457..3bc8f59 100644
--- a/transition_test.go
+++ b/transition_test.go
@@ -2,13 +2,14 @@ package transition_test
 
 import (
 	"errors"
-	"testing"
-
-	"github.com/jinzhu/gorm"
+	"fmt"
+	"github.com/glebarez/sqlite"
 	_ "github.com/mattn/go-sqlite3"
-
-	"github.com/qor/qor/test/utils"
 	"github.com/qor/transition"
+	"gorm.io/driver/mysql" // Gorm Mysql驱动
+	gormv2 "gorm.io/gorm"
+	"os"
+	"testing"
 )
 
 type Order struct {
@@ -18,15 +19,71 @@ type Order struct {
 	transition.Transition
 }
 
-var db = utils.TestDB()
+// TestDB initialize a db for testing
+func TDB() *gormv2.DB {
+	var db *gormv2.DB
+	var err error
+	var dbuser, dbpwd, dbname, dbhost = "qor", "qor", "qor_test", "localhost"
 
-func init() {
-	for _, model := range []interface{}{&Order{}, &transition.StateChangeLog{}} {
-		if err := db.DropTableIfExists(model).Error; err != nil {
+	if os.Getenv("DB_USER") != "" {
+		dbuser = os.Getenv("DB_USER")
+	}
+
+	if os.Getenv("DB_PWD") != "" {
+		dbpwd = os.Getenv("DB_PWD")
+	}
+
+	if os.Getenv("DB_NAME") != "" {
+		dbname = os.Getenv("DB_NAME")
+	}
+
+	if os.Getenv("DB_HOST") != "" {
+		dbhost = os.Getenv("DB_HOST")
+	}
+	var dsn, driverName string
+	if os.Getenv("TEST_DB") == "postgres" {
+		driverName = "postgres"
+		dsn = fmt.Sprintf("postgres://%s:%s@%s/%s?sslmode=disable", dbuser, dbpwd, dbhost, dbname)
+	} else if os.Getenv("TEST_DB") == "mysql" {
+		// CREATE USER 'qor'@'localhost' IDENTIFIED BY 'qor';
+		// CREATE DATABASE qor_test;
+		// GRANT ALL ON qor_test.* TO 'qor'@'localhost';
+		driverName = "mysql"
+		dsn = fmt.Sprintf("%s:%s@/%s?charset=utf8&parseTime=True&loc=Local", dbuser, dbpwd, dbname)
+	} else {
+		db, err = gormv2.Open(sqlite.Open("gorm.db"), &gormv2.Config{})
+		if err != nil {
 			panic(err)
 		}
+		return db
+	}
+	db, err = gormv2.Open(mysql.New(mysql.Config{
+		DriverName:        driverName,
+		DSN:               dsn, // data source name, refer https://github.com/go-sql-driver/mysql#dsn-data-source-name
+		DefaultStringSize: 255,
+	}), &gormv2.Config{
+		CreateBatchSize:        500, // 批量写入
+		SkipDefaultTransaction: false,
+		NamingStrategy:         nil,
+		FullSaveAssociations:   false,
+	})
+	if err != nil {
+		panic(err)
+	}
+	return db
+}
+
+var db = TDB()
 
-		if err := db.AutoMigrate(model).Error; err != nil {
+func init() {
+	for _, model := range []interface{}{&Order{}, &transition.StateChangeLog{}} {
+		if ok := db.Migrator().HasTable(model); ok {
+			err := db.Migrator().DropTable(model)
+			if err != nil {
+				panic(err)
+			}
+		}
+		if err := db.AutoMigrate(model); err != nil {
 			panic(err)
 		}
 	}
@@ -34,7 +91,6 @@ func init() {
 
 func getStateMachine() *transition.StateMachine {
 	var orderStateMachine = transition.New(&Order{})
-
 	orderStateMachine.Initial("draft")
 	orderStateMachine.State("checkout")
 	orderStateMachine.State("paid")
@@ -71,7 +127,11 @@ func TestStateTransition(t *testing.T) {
 		t.Errorf("state doesn't changed to checkout")
 	}
 
-	var stateChangeLogs = transition.GetStateChangeLogs(order, db)
+	var stateChangeLogs, err = transition.GetStateChangeLogs(order, db)
+	if err != nil {
+		t.Error(err)
+		return
+	}
 	if len(stateChangeLogs) != 1 {
 		t.Errorf("should get one state change log with GetStateChangeLogs")
 	} else {
@@ -102,7 +162,11 @@ func TestGetLastStateChange(t *testing.T) {
 		t.Errorf("state doesn't changed to paid")
 	}
 
-	var lastStateChange = transition.GetLastStateChange(order, db)
+	var lastStateChange, err = transition.GetLastStateChange(order, db)
+	if err != nil {
+		t.Error(err)
+		return
+	}
 	if lastStateChange.To != "paid" {
 		t.Errorf("state to not set")
 	} else {
@@ -158,13 +222,15 @@ func TestStateCallbacks(t *testing.T) {
 
 	address1 := "I'm an address should be set when enter checkout"
 	address2 := "I'm an address should be set when exit checkout"
-	orderStateMachine.State("checkout").Enter(func(order interface{}, tx *gorm.DB) error {
-		order.(*Order).Address = address1
-		return nil
-	}).Exit(func(order interface{}, tx *gorm.DB) error {
-		order.(*Order).Address = address2
-		return nil
-	})
+	orderStateMachine.State("checkout").Enter(
+		func(order interface{}, tx *gormv2.DB) error {
+			order.(*Order).Address = address1
+			return nil
+		}).
+		Exit(func(order interface{}, tx *gormv2.DB) error {
+			order.(*Order).Address = address2
+			return nil
+		})
 
 	if err := orderStateMachine.Trigger("checkout", order, db); err != nil {
 		t.Errorf("should not raise any error when trigger event checkout")
@@ -190,10 +256,11 @@ func TestEventCallbacks(t *testing.T) {
 		prevState, afterState string
 	)
 
-	orderStateMachine.Event("checkout").To("checkout").From("draft").Before(func(order interface{}, tx *gorm.DB) error {
-		prevState = order.(*Order).State
-		return nil
-	}).After(func(order interface{}, tx *gorm.DB) error {
+	orderStateMachine.Event("checkout").To("checkout").From("draft").
+		Before(func(order interface{}, tx *gormv2.DB) error {
+			prevState = order.(*Order).State
+			return nil
+		}).After(func(order interface{}, tx *gormv2.DB) error {
 		afterState = order.(*Order).State
 		return nil
 	})
@@ -218,7 +285,7 @@ func TestTransitionOnEnterCallbackError(t *testing.T) {
 		orderStateMachine = getStateMachine()
 	)
 
-	orderStateMachine.State("checkout").Enter(func(order interface{}, tx *gorm.DB) (err error) {
+	orderStateMachine.State("checkout").Enter(func(order interface{}, tx *gormv2.DB) (err error) {
 		return errors.New("intentional error")
 	})
 
@@ -237,7 +304,7 @@ func TestTransitionOnExitCallbackError(t *testing.T) {
 		orderStateMachine = getStateMachine()
 	)
 
-	orderStateMachine.State("checkout").Exit(func(order interface{}, tx *gorm.DB) (err error) {
+	orderStateMachine.State("checkout").Exit(func(order interface{}, tx *gormv2.DB) (err error) {
 		return errors.New("intentional error")
 	})
 
@@ -260,7 +327,7 @@ func TestEventOnBeforeCallbackError(t *testing.T) {
 		orderStateMachine = getStateMachine()
 	)
 
-	orderStateMachine.Event("checkout").To("checkout").From("draft").Before(func(order interface{}, tx *gorm.DB) error {
+	orderStateMachine.Event("checkout").To("checkout").From("draft").Before(func(order interface{}, tx *gormv2.DB) error {
 		return errors.New("intentional error")
 	})
 
@@ -279,7 +346,7 @@ func TestEventOnAfterCallbackError(t *testing.T) {
 		orderStateMachine = getStateMachine()
 	)
 
-	orderStateMachine.Event("checkout").To("checkout").From("draft").After(func(order interface{}, tx *gorm.DB) error {
+	orderStateMachine.Event("checkout").To("checkout").From("draft").After(func(order interface{}, tx *gormv2.DB) error {
 		return errors.New("intentional error")
 	})
 

From b86f77a3be78dbdb2fdbb886c9b331a3e8ccb726 Mon Sep 17 00:00:00 2001
From: joyyizhang <joyyizhang@tencent.com>
Date: Fri, 5 May 2023 16:27:07 +0800
Subject: [PATCH 3/4] fix id

---
 state_change_log.go | 19 ++++++++++++++++++-
 transition_test.go  | 27 +++++++++++++++++++++++++--
 2 files changed, 43 insertions(+), 3 deletions(-)

diff --git a/state_change_log.go b/state_change_log.go
index 62743c4..528ed3d 100644
--- a/state_change_log.go
+++ b/state_change_log.go
@@ -1,8 +1,10 @@
 package transition
 
 import (
+	"fmt"
 	gormv2 "gorm.io/gorm"
 	"gorm.io/gorm/schema"
+	"reflect"
 	"strings"
 	"sync"
 
@@ -25,8 +27,21 @@ type StateChangeLog struct {
 
 var tableColumn = &sync.Map{}
 
+func getStructFieldValueByName(myStruct interface{}, columnName string) interface{} {
+	structValue := reflect.ValueOf(myStruct)
+	fieldValue := structValue.FieldByName(columnName)
+	return fieldValue.Interface()
+}
+
 // GenerateReferenceKey generate reference key used for change log
 func GenerateReferenceKey(model interface{}, db *gormv2.DB) (string, error) {
+	modelType := reflect.ValueOf(model)
+	for modelType.Kind() == reflect.Slice || modelType.Kind() == reflect.Array || modelType.Kind() == reflect.Ptr {
+		modelType = modelType.Elem()
+	}
+	if modelType.Kind() != reflect.Struct {
+		return "", fmt.Errorf("modelType.Kind() != reflect.Struct,%d", modelType.Kind())
+	}
 	ss, err := schema.Parse(model, tableColumn, db.NamingStrategy)
 	if err != nil {
 		return "", err
@@ -34,10 +49,12 @@ func GenerateReferenceKey(model interface{}, db *gormv2.DB) (string, error) {
 	var primaryValues []string
 	for _, field := range ss.Fields {
 		if field.PrimaryKey {
-			primaryValues = append(primaryValues, field.Name)
+			primaryValues = append(primaryValues, fmt.Sprintf("%v",
+				modelType.FieldByName(field.Name).Interface()))
 		}
 	}
 	resStr := strings.Join(primaryValues, "::")
+	fmt.Println(resStr)
 	return resStr, nil
 }
 
diff --git a/transition_test.go b/transition_test.go
index 3bc8f59..5a0bec0 100644
--- a/transition_test.go
+++ b/transition_test.go
@@ -13,7 +13,7 @@ import (
 )
 
 type Order struct {
-	Id      int
+	Id      int `gorm:"primarykey"`
 	Address string
 
 	transition.Transition
@@ -117,7 +117,9 @@ func CreateOrderAndExecuteTransition(transition *transition.StateMachine, event
 }
 
 func TestStateTransition(t *testing.T) {
-	order := &Order{}
+	order := &Order{
+		Id: 1,
+	}
 
 	if err := getStateMachine().Trigger("checkout", order, db); err != nil {
 		t.Errorf("should not raise any error when trigger event checkout")
@@ -358,3 +360,24 @@ func TestEventOnAfterCallbackError(t *testing.T) {
 		t.Errorf("state transitioned on Enter callback error")
 	}
 }
+
+type ss int
+
+func TestConvertInterfaceToString(t *testing.T) {
+	var a interface{}
+	a = 1
+	fmt.Println(fmt.Sprintf("%v", a))
+
+	var b interface{}
+	b = 1.1
+	fmt.Println(fmt.Sprintf("%v", b))
+
+	var d interface{}
+	d = "ss"
+	fmt.Println(fmt.Sprintf("%v", d))
+
+	var c interface{}
+	var ss = 1
+	c = ss
+	fmt.Println(fmt.Sprintf("%v", c))
+}

From 56ed3ed958169a722f1b43282d9140ad07639784 Mon Sep 17 00:00:00 2001
From: joyyizhang <joyyizhang@tencent.com>
Date: Fri, 5 May 2023 16:31:51 +0800
Subject: [PATCH 4/4] fix id

---
 state_change_log.go | 1 -
 1 file changed, 1 deletion(-)

diff --git a/state_change_log.go b/state_change_log.go
index 528ed3d..e0d3db3 100644
--- a/state_change_log.go
+++ b/state_change_log.go
@@ -54,7 +54,6 @@ func GenerateReferenceKey(model interface{}, db *gormv2.DB) (string, error) {
 		}
 	}
 	resStr := strings.Join(primaryValues, "::")
-	fmt.Println(resStr)
 	return resStr, nil
 }