-2
我目前使用PHP,ORACLE,PDO和JNDI的組合將我的應用程序連接到數據庫。我無法理解以面向對象的方式管理連接池的最佳方法。因此,當我嘗試執行批量插入(32插入以上(我的最大池大小設置爲))時,我會收到最大連接警告。PHP:面向對象方法管理連接池
考慮這個例子:
Main File:
//User uploads excel document which I parse into an array
$car = array();
foreach($array as $index => $data){
$car[$index] = new Car(null,$data["make"],$data["model"]);
$car[$index]->insert();
}
//return car array of objects
在類別:
//Car Class
class Car{
protected $pkey;
protected $make;
protected $model;
protected $db;
public function __construct($pkey,$make,$model){
$this->pkey = $pkey;
if(isset($make) && ($make != '')){
$this->make = $make;
}else{
throw new Exception("Car must have make");
}
if(isset($model) && ($model != '')){
$this->model = $model;
}else{
throw new Exception("Car must have model");
}
$this->db = new Database();
}
public function insert(){
$sql = "INSERT INTO TABLE (...) VALUES (..)";
$data = array(
":make"=>$this->make,
":model"=>$this->model,
);
try{
$this->pkey = $this->db->insert($sql,$data);
return true;
}catch(Exception $err){
//catch errors
return false;
}
}
}
在這個例子中,假設最大池被設置爲32,任何陣列大於32將導致我超過最大池大小,因爲每個汽車對象都與活動數據庫連接一起存儲。爲了解決這個問題,我嘗試了對這個類實現以下修復。
//Car Class
class Car{
protected $pkey;
protected $make;
protected $model;
protected $db;
public function __construct($pkey,$make,$model){
$this->pkey = $pkey;
if(isset($make) && ($make != '')){
$this->make = $make;
}else{
throw new Exception("Car must have make");
}
if(isset($model) && ($model != '')){
$this->model = $model;
}else{
throw new Exception("Car must have model");
}
//$this->db = new Database(); //Moved out of the constructor
}
public function insert(){
$this->establishDBConn();
$sql = "INSERT INTO TABLE (...) VALUES (...)";
$data = array(
":make"=>$this->make,
":model"=>$this->model,
);
try{
$this->pkey = $this->db->insert($sql,$data);
$this->closeDBConn();
return true;
}catch(Exception $err){
//catch errors
$this->closeDBConn();
return false;
}
}
protected function establishDBConn(){
if(!$this->db){
$this->db = new Database();
}
}
public function closeDBConn(){
if($this->db){
$this->db->close();
$this->db = null;
}
}
}
理論上這種改變應該強制在實際插入過程中只保持一個活動的連接。但是,通過此更改,我繼續達到最大連接池限制。作爲最後的努力,我將所有插入邏輯移出汽車類並創建了批量插入功能。這個函數忽略了一個對象的概念,它只是接收一個數據數組,它循環並插入到單個數據連接中。這很有效,但我很想找到一種方法來解決我在面向對象編程約束中的問題。
有關如何改進我的代碼以便更有效地使用對象和數據庫連接的任何建議?
僅供參考這是我的數據庫類的樣子:
class Database {
protected $conn;
protected $dbstr;
public function __construct() {
$this->conn = null;
$this->dbstr = "jndi connection string";
$this->connect();
}
public function connect(){
try{
$this->conn = new PDO($this->dbstr); // Used with jndi string
} catch (PDOException $e){
// print $e->getMessage();
}
return "";
}
public function insert($query, $data){
try{
$this->conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
/* Execute a prepared statement by passing an array of values */
$sth = $this->conn->prepare($query, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
$count = $sth->execute($data);
return $this->oracleLastInsertId($query);
}catch(PDOException $e){
throw new Exception($e->getMessage());
}
}
public function oracleLastInsertId($sqlQuery){
// Checks if query is an insert and gets table name
if(preg_match("/^INSERT[\t\n ]+INTO[\t\n ]+([a-z0-9\_\-]+)/is", $sqlQuery, $tablename)){
// Gets this table's last sequence value
$query = "select ".$tablename[1]."_SEQ.currval AS last_value from dual";
try{
$temp_q_id = $this->conn->prepare($query);
$temp_q_id->execute();
if($temp_q_id){
$temp_result = $temp_q_id->fetch(PDO::FETCH_ASSOC);
return ($temp_result) ? $temp_result['LAST_VALUE'] : false;
}
}catch(Exception $err){
throw new Exception($err->getMessage());
}
}
return false;
}
public function close(){
$this->conn = null;
}
}
剛看了介紹,但是你是否真的爲每一個單獨的插入使用不同的連接? (或者爲什麼你在32個插入後沒有連接?)那就是......廢話^^ – KingCrunch