使用sqlx进行结构嵌入,但无法从数据库返回值。

huangapple go评论81阅读模式
英文:

Struct embedding with sqlx not returning value from db

问题

我有一个包含时间字段的结构体,该字段可能为空:

type Order struct {
    ...
    PickupTime  *time.Time    `json:"-"`
}

我想使用 sqlx 将其保存到数据库中,所以我想我需要使用 pq.NullTime,如此处所建议的 链接

为了避免直接在模型层中泄漏数据库代码,我决定将 Order 嵌入到 PgOrder 中,并修改 PickupTime 的类型:

type PgOrder struct {
    Order
    PickupTime pq.NullTime
}

问题是,当我简单地更新数据库中的 Order,然后再获取该订单时,返回的 PickupTime 是空的。

// 更新
func (pg Postgres) UpdateOrderPickupTime(order *Order, pickupTime time.Time) error {
    _, err := pg.Exec(`UPDATE orders SET pickup_time = $1 WHERE id = $2`, pickupTime, order.ID)
    return err
}

// 检索
func (pg Postgres) GetOrder(orderID DatabaseID) (*Order, error) {
    pgOrder := PgOrder{}
    err := pg.Get(&pgOrder, `SELECT * FROM orders WHERE id = $1`, orderID)
    if err == sql.ErrNoRows {
        return nil, nil
    }
    ... // 此时 pgOrder.PickupTime 为 0001-01-01 00:00:00 +0000 UTC
}

如果我在更新和检索之间设置断点,我可以检查数据库并看到一个值被保存为 2017-04-20 12:05:37-04。所以问题必须出现在检索部分。如果我从 文档 正确理解的话,sqlx 应该能够处理嵌入的结构体。

英文:

I have a struct with a time field that may be nil:

type Order struct {
    ...
	PickupTime  *time.Time    `json:"-"`
}

I want to save this to DB with sqlx so I figure I need to use pq.NullTime as suggested here.

Instead of updating the Order object (I don't want to leak DB code into the model layer), I figured I could embedd Order in a PgOrder and alter the PickupTime type:

type PgOrder struct {
	Order
	PickupTime pq.NullTime
}

The problem is that when I simply update an Order in DB, then turn around and fetch that order, the returned PickupTime is empty.

// update
func (pg Postgres) UpdateOrderPickupTime(order *Order, pickupTime time.Time) error {
	_, err := pg.Exec(`UPDATE orders SET pickup_time = $1 WHERE id = $2`, pickupTime, order.ID)
	return err
}

// retrieve
func (pg Postgres) GetOrder(orderID DatabaseID) (*Order, error) {
	pgOrder := PgOrder{}
	err := pg.Get(&pgOrder, `SELECT * FROM orders WHERE id = $1`, orderID)
	if err == sql.ErrNoRows {
		return nil, nil
	}
    ... // at this point pgOrder.PickupTime is 0001-01-01 00:00:00 +0000 UTC

}

If I put a breakpoint betwen updating and retrieving, I can inspect the DB and see that a value is being saved as 2017-04-20 12:05:37-04. So the problem must be in the retrieve portion. If I understand right from the docs, sqlx should be able to handle embedded structs.

答案1

得分: 2

看起来你正在遮蔽PickupTime。如果我正确理解sqlx文档,这意味着它会将值存储在第一个找到的位置(在Order中),然后当你读取PgOrder中的值时,它是一个未初始化的time.Time。你可以检查PgOrder.PickupTime的Valid字段来确认这一点(它应该是无效的)。

英文:

It looks like you're shadowing PickupTime. If I'm reading the sqlx docs right that means it will store the value in the first one it found (in Order) and then when you read the one in PgOrder it's an uninitialized time.Time. You can check the Valid field of PgOrder.PickupTime to confirm this (it should be invalid).

答案2

得分: 1

如果你的字段是指向某个东西的指针,例如 *time.Time*string,你不需要使用 NullXxx 类型。当你有一个非空字段,例如 time.Timestring,而对应的列可以是 NULL 时,应该使用这些类型。

如果你仍然想嵌入你的类型,以避免 @Dmitri Goldring 提到的潜在遮蔽问题,你可以告诉 sqlx 跳过你不想它扫描到的列。就像你在 json 标签中所做的那样,你可以在 db 标签中这样做:

type Order struct {
    ...
    PickupTime *time.Time `json:"-" db:"-"`
}

type PgOrder struct {
    Order
    PickupTime pq.NullTime
}
英文:

If your field is a pointer to something, e.g. *time.Time, or *string you shouldn't need to use the NullXxx types. Those types are to be used when you have a non-nil field, e.g. time.Time, or string while it's corresponding column can be NULL.

If you want to ebmed your type anyway, to avoid potential shadowing already mentioned by @Dmitri Goldring, you can to tell sqlx to skip the field you don't want it to scan the column into. So just as you did with the json tag, you can do so with the db tag:

type Order struct {
    ...
    PickupTime *time.Time `json:"-" db:"-"`
}

type PgOrder struct {
    Order
    PickupTime pq.NullTime
}

huangapple
  • 本文由 发表于 2017年4月22日 06:17:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/43552813.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定