beeg中orm的坑

在使用beego的orm的过程中,基本是使用文档进行开发,但是有一处我没有细看文档,于是在开发的过程中,就产生了一些疑问,有这些疑问后,我就要清楚到底是怎么回事

疑问一

如果在beego框架中的controller中开启了事务,既不进行提交事务,也不进行回滚事务,会发生什么?

示例代码一

func (controller *CalendarController) Test() {
	//此处开启事务
	tx, err := global.ORM.Begin()
	logs.Info(err)
	//此处更新一条数据
	exec, err := tx.Raw("update event_batch set next_time=10 where id=1").Exec()
	logs.Info(exec,err)
	if err != nil {
		return
	}
	if true {
		//err := tx.Rollback()
		logs.Info(err)
		goto ERR
	}
	//tx.Commit()
	//成功返回
	controller.Data["json"] = global.OutMsgFormat(0, "success", nil, nil)
	_ = controller.ServeJSON()
	return
ERR:
	//返回错误提示
	controller.Data["json"] = global.OutMsgFormat(1002, " 出错了", nil, nil)
	_ = controller.ServeJSON()
}

此时访问这个接口,则会直接返回

{
    "code": 1002,
    "params": null,
    "reason": " 出错了",
    "result": null
}

此时我们通过mysql客户端进行更新这条数据,则会发现这条语句会一直卡住,最后得到错误Lock wait timeout exceeded; try restarting transaction,很明显,这条数据被之前的事务锁住了,还会带来的一个影响就是我们重新请求这个接口,也会被卡住,直到超时。
以下是发生的错误的截图

  • 运行sql卡住
    在这里插入图片描述
  • 运行sql报错

  • 访问接口卡住

在这里插入图片描述

结论一

之前想当然的认为,发生错误后直接goto ERR,返回,则此进程结束,事务不显示的回滚,那么也没有进行提交,则不会有问题,这在php的开发过程中都是如此写的,但是经过实验发现,必须显示的进行事务回滚,否则这个事务则会一直存在,直到把这个go项目进行重启。

踩坑二

func (controller *CalendarController) Test() {
	//此处开启事务
	tx, err := global.ORM.Begin()
	logs.Info(err)
	//此处更新一条数据
	//注意⚠️⚠️⚠️,此处使用的是global.ORM进行更新操作,那么此时事务是没有任何作用的
	exec, err := global.ORM.Raw("update event_batch set next_time=10 where id=1").Exec()
	logs.Info(exec,err)
	if err != nil {
		return
	}
	if true {
		//err := tx.Rollback()
		logs.Info(err)
		goto ERR
	}
	//tx.Commit()
	//成功返回
	controller.Data["json"] = global.OutMsgFormat(0, "success", nil, nil)
	_ = controller.ServeJSON()
	return
ERR:
	//返回错误提示
	controller.Data["json"] = global.OutMsgFormat(1002, " 出错了", nil, nil)
	_ = controller.ServeJSON()
}
<think>我们正在处理一个数据库插入操作错误,错误信息为“must be in insert fields list”。这通常意味着在插入语句中指定的字段列表与提供的值不匹配,或者字段名有误。 根据引用[1],我们得知在插入时间时,应尽量使用数据库函数(如CURRENT_TIMESTAMP)而不是字符串字面值。同时,引用[2]提到了使用Django的get_or_create方法来避免重复插入,但这里的问题可能不是重复插入,而是字段列表错误。 错误原因分析: 1. 插入语句中列出的字段数量与值的数量不匹配。 2. 字段名拼写错误,或者使用了不存在的字段名。 3. 可能由于表结构变更(如字段重命名或删除)导致。 解决步骤: 1. 检查插入语句中字段列表和值列表的数量是否一致。 2. 核对字段名是否与数据库表结构中的字段名完全一致(注意大小写敏感问题,具体取决于数据库配置)。 3. 如果使用了框架(如Django),检查模型定义与数据库表结构是否一致。 例如,一个错误的插入语句可能是: ```sql INSERT INTO table_name (field1, field2, field3) VALUES (value1, value2); ``` 这里字段有三个,但值只有两个,会导致错误。 另一个例子: ```sql INSERT INTO table_name (field1, field2, field3) VALUES (value1, value2, value3); ``` 但如果表结构中并没有field3这个字段,那么也会出现同样的错误。 根据引用[1]中的建议,如果我们插入时间,最好使用数据库函数,例如: ```sql INSERT INTO tdate (ctime) VALUES (CURRENT_TIMESTAMP); ``` 如果使用ORM(如Django),如引用[2]所示,我们可以使用get_or_create方法,但要注意该方法需要字段名与模型中的字段名匹配。 因此,针对当前错误,我们需要仔细检查插入操作中的字段列表,确保每个字段都在表结构中存在,并且数量与值的数量匹配。 举例说明: 假设我们有一个表`users`,包含字段:`id`(自增主键),`name`,`email`,`created_at`。 正确的插入语句应该是: ```sql INSERT INTO users (name, email, created_at) VALUES ('Alice', 'alice@example.com', CURRENT_TIMESTAMP); ``` 如果我们在字段列表中写了一个不存在的字段,比如`create_time`(正确的字段是`created_at`),那么就会出现错误。 在编程中,如果使用ORM,则应该检查模型类中定义的字段,确保插入操作使用的字段名与模型一致。 如果问题仍然存在,建议检查数据库表结构(如使用`DESCRIBE table_name;`或`\d table_name`等命令)以确认字段名。 总结:必须确保插入语句中字段列表的每个字段都是目标表中存在的,且字段数量与值数量相同。</think>### 数据库插入操作字段列表错误解决方案 当遇到"must be in insert fields list"错误时,通常表示您的SQL插入语句存在以下问题: 1. **字段数量不匹配** 插入语句中字段数量与值数量不一致,例如: ```sql -- 错误示例(3个字段 vs 2个值) INSERT INTO users (name, email, age) VALUES ('Alice', 'alice@example.com'); ``` 2. **字段名拼写错误** 使用了不存在的字段名或大小写不匹配: ```sql -- 错误示例(正确字段应为created_at) INSERT INTO logs (create_time) VALUES (CURRENT_TIMESTAMP); ``` 3. **主键/唯一键冲突** 尝试插入重复的主键或唯一键值(部分数据库报此错误)[^2]。 --- ### 解决方法 #### 1. 检查字段与值数量 确保`INSERT`语句中字段列表和值列表数量严格一致: ```sql -- 正确示例 INSERT INTO products (name, price, stock) VALUES ('Laptop', 1200.00, 50); -- 3字段=3值 ``` #### 2. 验证字段名称 核对数据库表结构: ```sql -- 查看表结构(MySQL) DESCRIBE your_table; -- 查看表结构(PostgreSQL) \d your_table ``` #### 3. 使用ORM工具避免错误(推荐) 如引用[2]所示,使用Django的`get_or_create`可自动处理字段映射: ```python # Django ORM示例 data = { 'book_name': '西游记', 'pub_date': '1988-05-03', 'read_count': 150 } BookInfo.objects.get_or_create(**data) # 自动匹配字段[^2] ``` #### 4. 时间字段处理 如引用[1]建议,时间字段应让数据库自动生成: ```sql -- 正确时间处理(避免硬编码) INSERT INTO orders (product_id, created_at) VALUES (1001, CURRENT_TIMESTAMP); -- 数据库自动生成时间[^1] ``` #### 5. 检查约束条件 确认是否违反唯一约束: ```sql -- 先查询避免冲突 INSERT INTO users (id, name) SELECT 101, 'Bob' WHERE NOT EXISTS (SELECT 1 FROM users WHERE id = 101); ``` --- ### 错误排查流程 ```mermaid graph TD A[报错 must be in insert fields list] --> B{检查字段/值数量} B -->|匹配| C{验证字段名是否存在} B -->|不匹配| D[修正字段或值数量] C -->|存在| E{检查时间字段处理} C -->|不存在| F[修正字段拼写] E -->|硬编码时间| G[改用CURRENT_TIMESTAMP] E -->|正确| H{检查唯一约束} H -->|冲突| I[添加防重逻辑] H -->|无冲突| J[检查SQL语法] ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

micro_cloud_fly

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值