public function save($argments = NULL, $argReplaced = TRUE)
 {
     // insertかupdateかを決める
     $insert = FALSE;
     if (FALSE === $argReplaced) {
         // 強制インサート
         $insert = TRUE;
     } elseif (FALSE === $this->loaded) {
         // インサート
         $insert = TRUE;
     }
     if (is_array($argments)) {
         // $argmentsが配列ならargmentsの値をセット
         $this->sets($argments);
     }
     $replaceFields = array();
     $replaceCLOBFields = array();
     $replaceBLOBFields = array();
     $binds = array();
     if (TRUE === $insert) {
         // インサート処理
         foreach ($this->describes as $key => $val) {
             if (isset($val["replace"]) && TRUE === $val["replace"]) {
                 if ("clob" === $val["type"]) {
                     $replaceCLOBFields[$key] = $this->{$key};
                 } elseif ("blob" === $val["type"]) {
                     $replaceBLOBFields[$key] = $this->{$key};
                 } elseif ("date" === $val["type"]) {
                     if ("mysql" === $this->_DBO->DBType || "postgres" === $this->_DBO->DBType) {
                         // mysqlとPostgresはそのまま文字列を与えられる
                         $replaceFields[$key] = " :" . $key;
                     } elseif ("oracle" === $this->_DBO->DBType) {
                         // Oralceでは日付型はTO_DATE関数で変換する
                         $replaceFields[$key] = " TO_DATE(:" . $key . " , 'yyyy-mm-dd hh24:mi:ss')";
                     } else {
                         // 未対応のDBエンジン
                         throw new Exception("");
                     }
                     $binds[$key] = $this->{$key};
                 } else {
                     $replaceFields[$key] = " :" . $key;
                     $binds[$key] = $this->{$key};
                 }
             }
         }
         // インサートする新しいシーケンスIDの取得に関する処理
         if (NULL === $this->pkey && NULL !== $this->pkeyName && !isset($replaceFields[$this->pkeyName])) {
             // Insertでpkeyにあたるキーの値がセットされていなければシーケンス処理を試みる
             if ("mysql" === $this->_DBO->DBType) {
                 if (isset($this->describes[$this->pkeyName]["autoincrement"]) && TRUE !== $this->describes[$this->pkeyName]["autoincrement"]) {
                     // mysqlでも独自シーケンスを使っているのであらばそれに準拠する
                     if (isset($sequenceSelectQuery) && NULL !== $sequenceSelectQuery && strlen($sequenceSelectQuery) > 0) {
                         // 独自シーケンス取得SQLが定義済みならばそれを使う
                         $seqSql = $sequenceSelectQuery;
                     } else {
                         // 独自シーケンス取得SQLが未定義済みならばフレームワーク固有のSQLを実行
                         $seqSql = "UPDATE " . strtolower($this->tableName) . "_" . $this->pkeyName . "_seq SET id=LAST_INSERT_ID(id+1)";
                         $response = $this->_DBO->execute($seqSql);
                         if (FALSE === $response) {
                             throw new Exception("");
                         }
                         $seqSql = "SELECT LAST_INSERT_ID() as new_id FROM " . strtolower($this->tableName) . "_" . $this->pkeyName . "_seq";
                     }
                 } else {
                     // インサート完了後、mysqlのlast_insert_idを使う
                     $lastInsertIdEnabled = TRUE;
                 }
             } elseif ("postgres" === $this->_DBO->DBType) {
                 // posgreは先にシーケンスを取れるので取っておく
                 if (isset($sequenceSelectQuery) && NULL !== $sequenceSelectQuery && strlen($sequenceSelectQuery) > 0) {
                     // 独自シーケンス取得SQLが定義済みならばそれを使う
                     $seqSql = $sequenceSelectQuery;
                 } else {
                     // 独自シーケンス取得SQLが未定義済みならばフレームワーク固有のSQLを実行
                     $seqSql = "SELECT nextval(" . strtolower($this->tableName) . "_" . $this->pkeyName . "_seq) as new_id";
                 }
             } elseif ("oracle" === $this->_DBO->DBType) {
                 // oracleは先にシーケンスを取れるので取っておく
                 if (isset($sequenceSelectQuery) && NULL !== $sequenceSelectQuery && strlen($sequenceSelectQuery) > 0) {
                     // 独自シーケンス取得SQLが定義済みならばそれを使う
                     $seqSql = $sequenceSelectQuery;
                 } else {
                     // 独自シーケンス取得SQLが未定義済みならばフレームワーク固有のSQLを実行
                     $seqSql = "SELECT " . strtolower($this->tableName) . "_" . $this->pkeyName . "_seq.NEXTVAL as new_id FROM DUAL";
                 }
             } else {
                 // 未対応のDBエンジン
                 throw new Exception("");
             }
             if (!(isset($lastInsertIdEnabled) && TRUE === $lastInsertIdEnabled)) {
                 debug('$seqSql=' . $seqSql);
                 $response = $this->_DBO->execute($seqSql);
                 if (FALSE === $response) {
                     throw new Exception("");
                 } else {
                     $responseArr = $response->GetAll();
                     $pkey = $responseArr[0]["new_id"];
                 }
                 $replaceFields[$this->pkeyName] = $pkey;
                 debug($this->pkeyName);
                 debug($replaceFields);
             }
         }
         // インサート文
         $sql = "INSERT INTO `" . strtolower($this->tableName) . "` ";
         $sql .= "(`" . implode("`, `", array_keys($replaceFields)) . "`) ";
         $sql .= "VALUES (" . implode(" , ", $replaceFields) . " ) ";
         // DB操作実行
         $response = $this->_DBO->execute($sql, $binds);
         if (FALSE === $response) {
             throw new Exception("");
         }
         // MySQLのauto_increment用処理
         if (isset($lastInsertIdEnabled) && TRUE === $lastInsertIdEnabled) {
             $response = $this->_DBO->execute("SELECT LAST_INSERT_ID() AS new_id FROM " . strtolower($this->tableName) . " LIMIT 1");
             if (FALSE === $response) {
                 throw new Exception("");
             } else {
                 $responseArr = $response->GetAll();
                 $pkey = $responseArr[0]["new_id"];
             }
         }
         // CLOBを処理する
         $replaceCLOBFieldKeys = array_keys($replaceCLOBFields);
         for ($replaceCLOBFieldsNum = 0; count($replaceCLOBFields) > $replaceCLOBFieldsNum; $replaceCLOBFieldsNum++) {
             $key = $replaceCLOBFieldKeys[$replaceCLOBFieldsNum];
             $where = "1=1";
             for ($pkeyNum = 0; count($this->pkeys) > $pkeyNum; $pkeyNum++) {
                 $where .= " AND `" . $this->pkeys[$pkeyNum] . "` = " . $this->{$this->pkeys[$pkeyNum]};
             }
             if (FALSE === $this->_DBO->updateClob(strtolower($this->tableName), $key, $replaceCLOBFields[$key], $where)) {
                 throw new Exception("");
             }
         }
         // BLOBを処理する
         $replaceBLOBFieldKeys = array_keys($replaceBLOBFields);
         for ($replaceBLOBFieldsNum = 0; count($replaceBLOBFields) > $replaceBLOBFieldsNum; $replaceBLOBFieldsNum++) {
             $key = $replaceBLOBFieldKeys[$replaceBLOBFieldsNum];
             $where = "1=1";
             for ($pkeyNum = 0; count($this->pkeys) > $pkeyNum; $pkeyNum++) {
                 $where .= " AND `" . $this->pkeys[$pkeyNum] . "` = " . $this->{$this->pkeys[$pkeyNum]};
             }
             if (FALSE === $this->_DBO->updateBlob(strtolower($this->tableName), $key, $replaceBLOBFields[$key], $where)) {
                 throw new Exception("");
             }
         }
         // DB操作に成功したのでpkeyの置き換えを行う
         if (isset($pkey) && count($pkey) > 0) {
             $this->pkey = $pkey;
             $this->{$this->pkeyName} = $pkey;
         } elseif (isset($this->{$this->pkeyName}) && strlen($this->{$this->pkeyName})) {
             // オートインクリメント以外で、Pkeyに該当するフィールドにデータが入っていたらそれをPkeyとして自動補完する
             $this->pkey = $this->{$this->pkeyName};
         }
         // XXX 読み込み済み扱いとする
         $this->loaded = TRUE;
     } else {
         // アップデート処理
         foreach ($this->describes as $key => $val) {
             if (isset($val["replace"]) && TRUE === $val["replace"]) {
                 if ("clob" === $val["type"]) {
                     $replaceCLOBFields[$key] = $this->{$key};
                 } elseif ("blob" === $val["type"]) {
                     $replaceBLOBFields[$key] = $this->{$key};
                 } elseif ("date" === $val["type"]) {
                     if ("mysql" === $this->_DBO->DBType || "postgres" === $this->_DBO->DBType) {
                         // mysqlとPostgresはそのまま文字列を与えられる
                         $replaceFields[$key] = " `" . $key . "` = :" . $key;
                     } elseif ("oracle" === $this->_DBO->DBType) {
                         // oracleでは日付型はTO_DATE関数で変換する
                         $replaceFields[$key] = " `" . $key . "` = TO_DATE( :" . $key . " , 'yyyy-mm-dd hh24:mi:ss')";
                     } else {
                         // 未対応のDBエンジン
                         throw new Exception("");
                     }
                     $binds[$key] = $this->{$key};
                 } elseif ("int" === $val["type"] && "increment" === strtolower($this->{$key})) {
                     $replaceFields[$key] = " `" . $key . "` = (`" . $key . "` + 1)";
                 } elseif ("int" === $val["type"] && "decrement" === strtolower($this->{$key})) {
                     $replaceFields[$key] = " `" . $key . "` = (`" . $key . "` - 1)";
                 } else {
                     $replaceFields[$key] = " `" . $key . "` = :" . $key;
                     $binds[$key] = $this->{$key};
                 }
             }
         }
         // アップデート文
         $sql = "UPDATE `" . strtolower($this->tableName) . "` ";
         $sql .= "SET " . implode(" , ", $replaceFields) . " ";
         $sql .= "WHERE 1=1 ";
         if (NULL !== $this->pkeys && TRUE === is_array($this->pkeys) && count($this->pkeys) > 1) {
             // 複合プライマリーキーの為の処理
             foreach ($this->pkeys as $key => $val) {
                 $sql .= "AND `" . $val . "` = :pkey_" . $val . " ";
                 $binds["pkey_" . $val] = $this->{$val};
             }
         } elseif (NULL !== $this->pkeyName) {
             // 単一プライマリーキーの処理
             $sql .= "AND `" . $this->pkeyName . "` = :pkey_" . $this->pkeyName . " ";
             $binds["pkey_" . $this->pkeyName] = $this->pkey;
         } else {
             // プライマリーキーが無いレコードなので
             foreach ($replaceFields as $key => $val) {
                 $sql .= "AND `" . $key . "` = :before_" . $key . " ";
                 $binds["before_" . $key] = $this->describes[$key]["before"];
             }
         }
         // DB操作実行
         $response = $this->_DBO->execute($sql, $binds);
         if (FALSE === $response) {
             throw new Exception("");
         }
         // CLOBを処理する
         $replaceCLOBFieldKeys = array_keys($replaceCLOBFields);
         for ($replaceCLOBFieldsNum = 0; count($replaceCLOBFields) > $replaceCLOBFieldsNum; $replaceCLOBFieldsNum++) {
             $key = $replaceCLOBFieldKeys[$replaceCLOBFieldsNum];
             $where = "1=1";
             for ($pkeyNum = 0; count($this->pkeys) > $pkeyNum; $pkeyNum++) {
                 $where .= " AND `" . $this->pkeys[$pkeyNum] . "` = " . $this->{$this->pkeys[$pkeyNum]};
             }
             if (FALSE === $this->_DBO->updateClob(strtolower($this->tableName), $key, $replaceCLOBFields[$key], $where)) {
                 throw new Exception("");
             }
         }
         // BLOBを処理する
         $replaceBLOBFieldKeys = array_keys($replaceBLOBFields);
         for ($replaceBLOBFieldsNum = 0; count($replaceBLOBFields) > $replaceBLOBFieldsNum; $replaceBLOBFieldsNum++) {
             $key = $replaceBLOBFieldKeys[$replaceBLOBFieldsNum];
             $where = "1=1";
             for ($pkeyNum = 0; count($this->pkeys) > $pkeyNum; $pkeyNum++) {
                 $where .= " AND `" . $this->pkeys[$pkeyNum] . "` = " . $this->{$this->pkeys[$pkeyNum]};
             }
             if (FALSE === $this->_DBO->updateBlob(strtolower($this->tableName), $key, $replaceBLOBFields[$key], $where)) {
                 throw new Exception("");
             }
         }
         // DB操作に成功したのでpkeyの置き換えを行う(Updateで置き換わってる場合があるので)
         $this->pkey = $this->{$this->pkeyName};
     }
     // DB操作に成功したのでdescribes内のreplaceとexec値を初期化しておく
     foreach ($replaceFields as $key => $val) {
         if ("int" === $this->describes[$key]["type"] && 'increment' === $this->{$key}) {
             $this->{$key} = (int) $this->describes[$key]["before"] + 1;
         } elseif ("int" === $this->describes[$key]["type"] && 'decrement' === $this->{$key}) {
             $this->{$key} = (int) $this->describes[$key]["before"] - 1;
         }
         $this->describes[$key]["replace"] = NULL;
     }
     return TRUE;
 }