英文:
Gorm: How to store a struct in a field
问题
我正在尝试将类型为hedera.ContractID
的Hedera合约ID保存到Gorm字段中,但是我遇到了错误:“invalid field found for struct github.com/hashgraph/hedera-sdk-go/v2.AccountID's field AliasKey: define a valid foreign key for relations or implement the Valuer interface”。
package contract
import (
"fmt"
"github.com/.../scanner/controllers/blockchain"
database "github.com/.../scanner/db"
model "github.com/.../scanner/models"
"github.com/rs/xid"
"gorm.io/gorm"
)
func DeployContract() *gorm.DB {
// 连接数据库
db, err := database.ConnectToDB()
// 如果数据库连接失败
if err != nil {
panic(err)
}
// 初始化模型
var modelContract model.Contract
// 检查是否已部署合约
if err := db.First(&modelContract); err.Error != nil {
// 没有找到已部署的合约
// 迁移模式
db.AutoMigrate(&model.Contract{})
// 部署合约
contract, _ := blockchain.DeployContract()
// 创建记录
// 生成随机ID
id := xid.New()
// 创建
db.Create(&model.Contract{
Id: id.String(),
ContractId: contract.Receipt.ContractID,
GasUsed: contract.CallResult.GasUsed,
TransactionId: fmt.Sprint(contract.TransactionID),
Timestamp: contract.ConsensusTimestamp,
ChargeFee: fmt.Sprint(contract.TransactionFee),
PayerAccount: fmt.Sprint(contract.TransactionID.AccountID),
Status: fmt.Sprint(contract.Receipt.Status),
})
}
return db
}
Gorm模型
package models
import (
"time"
"github.com/hashgraph/hedera-sdk-go/v2"
"gorm.io/gorm"
)
type Contract struct {
gorm.Model
Id string
ContractId *hedera.ContractID
GasUsed uint64
TransactionId string
Timestamp time.Time
ChargeFee string
PayerAccount string
Status string
}
希望对你有所帮助!
英文:
I am trying to save an hederea contract ID of type *hedera.ContractID into a Gorm field but i get the error "invalid field found for struct github.com/hashgraph/hedera-sdk-go/v2.AccountID's field AliasKey: define a valid foreign key for relations or implement the Valuer interface"
package contract
import (
"fmt"
"github.com/.../scanner/controllers/blockchain"
database "github.com/.../scanner/db"
model "github.com/.../scanner/models"
"github.com/rs/xid"
"gorm.io/gorm"
)
func DeployContract() *gorm.DB {
//connect to database
db, err := database.ConnectToDB()
//if db connection fails
if err != nil {
panic(err)
}
//init model
var modelContract model.Contract
//check if a contract has been deployed
if err := db.First(&modelContract); err.Error != nil {
//no deployment found
//Migrate the schema
db.AutoMigrate(&model.Contract{})
//deploy contract
contract, _ := blockchain.DeployContract()
//create record
// generate random id
id := xid.New()
// Create
db.Create(&model.Contract{
Id: id.String(),
ContractId: contract.Receipt.ContractID,
GasUsed: contract.CallResult.GasUsed,
TransactionId: fmt.Sprint(contract.TransactionID),
Timestamp: contract.ConsensusTimestamp,
ChargeFee: fmt.Sprint(contract.TransactionFee),
PayerAccount: fmt.Sprint(contract.TransactionID.AccountID),
Status: fmt.Sprint(contract.Receipt.Status),
})
}
return db
}
Gorm Model
package models
import (
"time"
"github.com/hashgraph/hedera-sdk-go/v2"
"gorm.io/gorm"
)
type Contract struct {
gorm.Model
Id string
ContractId *hedera.ContractID
GasUsed uint64
TransactionId string
Timestamp time.Time
ChargeFee string
PayerAccount string
Status string
}
答案1
得分: 0
对于自定义数据类型,您需要指定如何将值存储和从数据库中检索出来。这可以通过实现Scanner
和Valuer
接口来完成。
然而,由于hedera.ContractID
是在另一个包中定义的,您需要创建自己的ContractID
并实现这些接口。可以像这样进行操作:
type ContractID hedera.ContractID
type Contract struct {
gorm.Model
Id string
ContractId *ContractID
GasUsed uint64
TransactionId string
Timestamp time.Time
ChargeFee string
PayerAccount string
Status string
}
func (c *ContractID) Scan(value interface{}) error {
bytes, ok := value.([]byte)
if !ok {
return errors.New(fmt.Sprint("Failed to unmarshal ContractID value:", value))
}
return json.Unmarshal(bytes, c)
}
func (c ContractID) Value() (driver.Value, error) {
return json.Marshal(c)
}
此外,在使用时将hedera.ContractID
转换为model.ContractID
。例如:
cID := model.ContractID(*contract.Receipt.ContractID)
// 创建
db.Create(&model.Contract{
Id: id.String(),
ContractId: &cID,
GasUsed: contract.CallResult.GasUsed,
TransactionId: fmt.Sprint(contract.TransactionID),
Timestamp: contract.ConsensusTimestamp,
ChargeFee: fmt.Sprint(contract.TransactionFee),
PayerAccount: fmt.Sprint(contract.TransactionID.AccountID),
Status: fmt.Sprint(contract.Receipt.Status),
})
英文:
For custom data types, you need to specify how the value will be stored and retrieved from your database. This is done by implementing the Scanner
and Valuer
interfaces.
However, since hedera.ContractID
is defined in another package, you will need to create your own ContractID
and implement these interfaces. Something like this:
type ContractID hedera.ContractID
type Contract struct {
gorm.Model
Id string
ContractId *ContractID
GasUsed uint64
TransactionId string
Timestamp time.Time
ChargeFee string
PayerAccount string
Status string
}
func (c *ContractID) Scan(value interface{}) error {
bytes, ok := value.([]byte)
if !ok {
return errors.New(fmt.Sprint("Failed to unmarshal ContractID value:", value))
}
return json.Unmarshal(bytes, c)
}
func (c ContractID) Value() (driver.Value, error) {
return json.Marshal(c)
}
Additionally, cast hedera.ContractID
into model.ContractID
wherever it is used. For example:
cID := model.ContractID(*contract.Receipt.ContractID)
// Create
db.Create(&model.Contract{
Id: id.String(),
ContractId: &cID,
GasUsed: contract.CallResult.GasUsed,
TransactionId: fmt.Sprint(contract.TransactionID),
Timestamp: contract.ConsensusTimestamp,
ChargeFee: fmt.Sprint(contract.TransactionFee),
PayerAccount: fmt.Sprint(contract.TransactionID.AccountID),
Status: fmt.Sprint(contract.Receipt.Status),
})
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论