用户
 找回密码
 入住 CI 中国社区
搜索
查看: 2118|回复: 4
收起左侧

[版本 3.x] ci在引入多个model时,事务回滚,只回滚第一个model的操作

[复制链接]
发表于 2017-1-16 17:35:58 | 显示全部楼层 |阅读模式
如题:
ci在引入多个model时,事务回滚,只回滚第一个model的操作
帮忙解答下,有人遇到过吗
发表于 2017-1-18 11:21:26 | 显示全部楼层
这跟你引入model的数量无关吧,你是指事务嵌套后只回滚最外面的事务,还是说多个事务只回滚第一个事务?我记得CI3开始就支持了事务的嵌套,你贴你的代码出来看看
 楼主| 发表于 2017-1-18 13:59:36 | 显示全部楼层
本帖最后由 kikiku 于 2017-1-18 15:04 编辑

见下面的代码

在$this->product_model->edit对数据库进行了update
在$this->notice_model->addNotice对数据库进行了insert,这是两个model
然后在throw new Exception('这是一个测试异常', 1);抛出异常,奇怪的是update回滚了,insert正常插入了

PHP复制代码
/**
 * 编辑供应商op
 */

public function editOp(){
    $result = array(
        'success' => false,
        'msg' => &$this->msg
    );
    try{
        $this->load->model('notice_model');
        if ($this->input->method() == 'post' && $this->input->is_ajax_request()) {
            $data = $this->input->post(null, true);
            if (!empty($data['ids'])) {
                $ids = json_decode($data['ids'], true);
                if ($ids !== false) {
                    //开启事务
                    $this->db->trans_start();
                    $notice = '管理员已将%s条产品OP更改为您,请留意。';
                    $productId = array();
                    foreach ($ids as $val) {
                        $beforeUpdate = $this->product_model->getProductByWhere(array('id' => $val['id']), 'id, product_name');
                        if (empty($beforeUpdate)) {
                            $result['msg'] = "产品{$val['id']}的数据不存在,请刷新后重试";
                            return $this->jsonFormat(201, $result);
                        }
                        $data = $this->checkInput($data);
                        if ($this->checkAccess) {
                            if (!$this->product_model->edit(array('id' => $val['id']), array('op' => $data['op'], 'updatetime' => $this->now))) {
                                throw new Exception("产品{$beforeUpdate['product_name']}修改OP失败", 201);
                            } else {
                                $productId[] = $val['id'];
                            }
                        }
                    }
                    $notice = sprintf($notice, count($ids));
                    $id = $this->notice_model->addNotice(array(
                        'message_type' => 5,
                        'title' => $notice,
                        'user_id' => $data['op'],
                        'url' => json_encode(array('id' => implode(',', $productId))),
                    ));                    
                    throw new Exception('这是一个测试异常', 1);
                    if ($this->db->trans_status() === FALSE) throw new Exception('修改数据失败', 201);
                    $this->db->trans_complete();
                    //执行成功
                    $result['success'] = true;
                    $result['msg'] = '恭喜,已成功修改供应商OP。';
                    return $this->jsonFormat(200, $result);
                }
            }
        }
        return $this->jsonFormat(201, $result);
    } catch (Exception $e) {
        $this->msg = $e->getMessage();
        return $this->jsonFormat($e->getCode(), $result);
    }
}
 
 
复制代码

addNotice的代码
PHP复制代码
 
/**
 * 添加到数据库
 */

public function add($data, $table = ''){
    $table or $table = $this->table_name_notice;
    if (!empty($data)) {
        $this->db->insert($table, $data);
        return $this->db->insert_id();
    }
    return false;
}
/**
 * 添加通知公共方法
 */

public function addNotice($conf = array()){
    $insert = array(
        'message_time' => $this->now,
        'operation_id' => $this->userInfo['true_name'],
        'createtime' => $this->now,
        'updatetime' => $this->now,
        'is_read' => 0,
    );
    $insert = array_merge($insert, $conf);
    return $this->add($insert);
}
 
 
复制代码



 楼主| 发表于 2017-1-18 14:32:34 | 显示全部楼层
Michael锐生 发表于 2017-1-18 11:21
这跟你引入model的数量无关吧,你是指事务嵌套后只回滚最外面的事务,还是说多个事务只回滚第一个事务?我 ...

帮忙看看吧,贴了下代码
发表于 2017-1-18 16:28:33 | 显示全部楼层
你的事务回滚语句写在哪里了?catch里面没有看到,就算你要靠trans_complete自动回滚,你抛出异常后,也执行不到trans_complete语句了

本版积分规则