报错信息如下:
| let exec = SqlCommandExecutor::new(tran_manager.transaction());
| ---- move occurs because exec
has type SqlCommandExecutor<'_, &mut Transaction<'_, MySql>>
, which does not implement the Copy
trait
...
63 | let result = exec.execute("").await?;
| ----------- exec
moved due to this method call
64 | let result1 = exec.execute("").await?;
| ^^^^ value used here after move
|
note: this function takes ownership of the receiver self
, which moves exec
我把函数的self 改为&self可以解决move的问题,但是调用sqlx的execute又不行了,有什么两全其美的办法吗?
源码连接地址:https://files.cnblogs.com/files/xlabs/sqlx_tran.rar
评论区
写评论好嘞,我瞧瞧,谢谢
--
👇
苦瓜小仔: @Yandros 大佬对为什么需要 drop 的解答 NLL vs drop glue
@Yandros 大佬对为什么需要 drop 的解答 NLL vs drop glue
谢谢,非常的nice的解答
--
👇
苦瓜小仔: > 不手动drop,auth_provider还是一直独占着SqlCommandExecutor
是的 playground
是的 playground
改成这样后,必须要drop(auth_provider)才行,是因为不手动drop,auth_provider还是一直独占着SqlCommandExecutor的原因吗?我试着注解drop(auth_provider),编译不过去
👇
xbitlabs: 搞定了,膜拜,哈哈
--
👇
苦瓜小仔: 你使用了
&'d mut SqlCommandExecutor<'c, 'd>
,这是典型的生命周期标注错误 —— 过度约束。改成
&'r mut SqlCommandExecutor<'c, 'd>
,比如:代码在这。
搞定了,膜拜,哈哈
--
👇
苦瓜小仔: 你使用了
&'d mut SqlCommandExecutor<'c, 'd>
,这是典型的生命周期标注错误 —— 过度约束。改成
&'r mut SqlCommandExecutor<'c, 'd>
,比如:代码在这。
你使用了
&'d mut SqlCommandExecutor<'c, 'd>
,这是典型的生命周期标注错误 —— 过度约束。改成
&'r mut SqlCommandExecutor<'c, 'd>
,比如:代码在这。
我main入口方法试了下,可以多次可变引用,但是后面的声明了,前面的就没法再使用了,像这样:
但是在AuthenticationProcessingFilter这个结构体的实现里这样用,就报错了,应该有些细节问题我没有搞定。
👇
苦瓜小仔: 代码发一下
代码链接https://files.cnblogs.com/files/xlabs/sqlx_tran.rar
--
👇
苦瓜小仔: 代码发一下
代码发一下
同时只能有一个可变引用,那一个请求的业务逻辑只能写在一个方法里了,如果这样,很多代码无法复用。
--
👇
xbitlabs: 大佬,现在还有个问题,就是一个http请求里,同时实例化两个struct,这个两个struct全都依赖同一内存位置的 &'b mut SqlCommandExecutor<'a,'b>,这时候就编译报错了:cannot borrow
*sql_command_executor
as mutable more than once at a time,可变引用只能同时有一个,这样也就没有办法在一个http请求里复用Transaction了。有什么好的解决办法吗?--
👇
xbitlabs: 完美
--
👇
苦瓜小仔: > 枚举也算是if else一个变种把,太多重复代码了,if else 中间的代码都是一样的
写一个宏 :)
大佬,现在还有个问题,就是一个http请求里,同时实例化两个struct,这个两个struct全都依赖同一内存位置的 &'b mut SqlCommandExecutor<'a,'b>,这时候就编译报错了:cannot borrow
*sql_command_executor
as mutable more than once at a time,可变引用只能同时有一个,这样也就没有办法在一个http请求里复用Transaction了。有什么好的解决办法吗?--
👇
xbitlabs: 完美
--
👇
苦瓜小仔: > 枚举也算是if else一个变种把,太多重复代码了,if else 中间的代码都是一样的
写一个宏 :)
完美
--
👇
苦瓜小仔: > 枚举也算是if else一个变种把,太多重复代码了,if else 中间的代码都是一样的
写一个宏 :)
写一个宏 :)
不过枚举还是比if else好,先暂时用枚举来搞吧,非常谢谢
--
👇
苦瓜小仔: 你有想过用枚举体吗?例子
之前有用过if else来实现,枚举也算是if else一个变种把,但是太多重复代码了,if else 中间的代码都是一样的。
--
👇
苦瓜小仔: 你有想过用枚举体吗?例子
你有想过用枚举体吗?例子
非常感谢,码了那么多字。我的想法是,在http接口的入口函数我实现一个#[transaction],实现自动事务管理,如果某些sql在某个http接口不需要事务,但是在别的接口需要事务,抽象出那个SqlCommandExecutor就有必要了,这样我就可以根据接口有没有#[transaction]自动生成SqlCommandExecutor,又因为刚好&Pool跟&mut Transaction都分别实现了Executor,如果这个接口需要事务,那我就往SqlCommandExecutor塞一个&mut Transaction,如果不需要事务那我就往SqlCommandExecutor塞一个&Pool,我这个想法,有没有更好的实现方式呢?
--
👇
苦瓜小仔: 不可能的。对于
impl<'c, 't> Executor<'t> for &'t mut Transaction<'c, MySql>
和所有.execute
方法,如 Query 的 execute 方法被定义成显然,这意味着执行 sqlx 库中任何
.execute
方法需要获取E
的所有权,而&mut
是唯一的,一旦调用这个方法,你不可能复用那个&mut Transaction
。这决定了每次调用.execute
之前需要生成一个&mut Transaction
。而生成&mut Transaction
的前提是你拥有Transaction
(或者拥有&mut Transaction
来 reborrow)。而 reborrow 是 Rust 众多人体工程学设计中的具体规则,并不是任何语法和抽象。总而言之,你无法定义SqlCommandExecutor
那种抽象。你已经拥有了
TransactionManager
只要在这上面通过方法定义你的逻辑就行: rustexplorer
对了,根据
Pool::begin
,你只需要TransactionManager<'a>
不可能的。对于
impl<'c, 't> Executor<'t> for &'t mut Transaction<'c, MySql>
和所有.execute
方法,如 Query 的 execute 方法被定义成显然,这意味着执行 sqlx 库中任何
.execute
方法需要获取E
的所有权,而&mut
是唯一的,一旦调用这个方法,你不可能复用那个&mut Transaction
。这决定了每次调用.execute
之前需要生成一个&mut Transaction
。而生成&mut Transaction
的前提是你拥有Transaction
(或者拥有&mut Transaction
来 reborrow)。而 reborrow 是 Rust 众多人体工程学设计中的具体规则,并不是任何语法和抽象。总而言之,你无法定义SqlCommandExecutor
那种抽象。你已经拥有了
TransactionManager
只要在这上面通过方法定义你的逻辑就行: rustexplorer