kikiku 发表于 2017-1-16 17:35:58

ci在引入多个model时,事务回滚,只回滚第一个model的操作

如题:
ci在引入多个model时,事务回滚,只回滚第一个model的操作
帮忙解答下,有人遇到过吗

Michael锐生 发表于 2017-1-18 11:21:26

这跟你引入model的数量无关吧,你是指事务嵌套后只回滚最外面的事务,还是说多个事务只回滚第一个事务?我记得CI3开始就支持了事务的嵌套,你贴你的代码出来看看

kikiku 发表于 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正常插入了

/**
* 编辑供应商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的代码

/**
* 添加到数据库
*/
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);
}




kikiku 发表于 2017-1-18 14:32:34

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

帮忙看看吧,贴了下代码

Michael锐生 发表于 2017-1-18 16:28:33

你的事务回滚语句写在哪里了?catch里面没有看到,就算你要靠trans_complete自动回滚,你抛出异常后,也执行不到trans_complete语句了
页: [1]
查看完整版本: ci在引入多个model时,事务回滚,只回滚第一个model的操作