Changeset 482

Show
Ignore:
Timestamp:
04/12/07 22:23:28 (1 year ago)
Author:
mikey
Message:

major overhaul of net.stubbles.rdbms.persistence
added unit tests for classes in net.stubbles.rdbms.persistence and net.stubbles.rdbms.querybuilder
examples in experiments/people/mikey/persistence will be corrected when the new annotation parser is available

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/src/main/php/net/stubbles/rdbms/criteria/stubAbstractCompositeCriterion.php

    r321 r482  
    2222     */ 
    2323    protected $criteria = array(); 
    24      
     24 
    2525    /** 
    2626     * add a criterion to the composition 
     
    3232        $this->criteria[] = $criterion; 
    3333    } 
    34      
     34 
     35    /** 
     36     * checks whether there is any criterion 
     37     * 
     38     * @return  bool 
     39     */ 
     40    public function hasCriterion() 
     41    { 
     42        return (count($this->criteria) > 0); 
     43    } 
     44 
    3545    /** 
    3646     * returns the criterion as sql 
     
    5666        return $sql . ')'; 
    5767    } 
    58      
     68 
    5969    /** 
    6070     * returns the the operator to connect the criteria 
  • trunk/src/main/php/net/stubbles/rdbms/pdo/stubDatabasePDOConnection.php

    r396 r482  
    3131     */ 
    3232    protected  $pdo           = null; 
    33      
     33 
    3434    /** 
    3535     * constructor 
     
    4545        $this->connectionData = $connectionData; 
    4646    } 
    47      
     47 
    4848    /** 
    4949     * destructor 
     
    5353        $this->disconnect(); 
    5454    } 
    55      
     55 
    5656    /** 
    5757     * establishes the connection 
     
    7272        } 
    7373    } 
    74      
     74 
    7575    /** 
    7676     * tries to create a new pdo instance 
     
    8686                     ); 
    8787    } 
    88      
     88 
    8989    /** 
    9090     * disconnects the database 
     
    9494        $this->pdo = null; 
    9595    } 
    96      
     96 
    9797    /** 
    9898     * returns the connection data used for the connection 
     
    129129        } 
    130130    } 
    131      
     131 
    132132    /** 
    133133     * start a transaction 
     
    140140        return $this->__call('beginTransaction', array()); 
    141141    } 
    142      
     142 
    143143    /** 
    144144     * commit a transaction 
     
    151151        return $this->__call('commit', array()); 
    152152    } 
    153      
     153 
    154154    /** 
    155155     * rollback a transaction 
     
    162162        return $this->__call('rollBack', array()); 
    163163    } 
    164      
     164 
    165165    /** 
    166166     * creates a prepared statement 
     
    185185        } 
    186186    } 
    187      
     187 
    188188    /** 
    189189     * executes a SQL statement 
     
    252252        return $statement; 
    253253    } 
    254      
     254 
    255255    /** 
    256256     * execute an SQL statement and return the number of affected rows 
     
    273273        } 
    274274    } 
    275      
     275 
    276276    /** 
    277277     * returns the last insert id 
     
    281281     * @throws  stubDatabaseException 
    282282     */ 
    283     public function getLastInsertID($name = null) 
    284     { 
    285         if (null === $this->pdo) { 
    286             $this->connect(); 
     283    public function getLastInsertId($name = null) 
     284    { 
     285        if (null === $this->pdo) { 
     286            throw new stubDatabaseException('Not connected: can not retrieve last insert id.'); 
    287287        } 
    288288         
     
    293293        } 
    294294    } 
    295      
     295 
    296296    /** 
    297297     * returns the database name (e.g. MySQL or PostgreSQL) 
  • trunk/src/main/php/net/stubbles/rdbms/persistence/annotations/stubDBColumnAnnotation.php

    r432 r482  
    88 */ 
    99stubClassLoader::load('net.stubbles.reflection.annotations.stubAnnotation', 
    10                       'net.stubbles.reflection.annotations.stubAbstractAnnotation' 
     10                      'net.stubbles.reflection.annotations.stubAbstractAnnotation', 
     11                      'net.stubbles.rdbms.querybuilder.stubDatabaseTableColumn' 
    1112); 
    1213/** 
     
    1920{ 
    2021    /** 
    21      * order of column within table 
     22     * the db table column container 
    2223     * 
    23      * @var  int 
     24     * @var  stubDatabaseTableColumn 
    2425     */ 
    25     protected $order        = 0; 
     26    protected $dbTableColumn; 
     27     
    2628    /** 
    27      * name of the column 
     29     * constructor 
     30     */ 
     31    public function __construct() 
     32    { 
     33        $this->dbTableColumn = new stubDatabaseTableColumn(); 
     34    } 
     35     
     36    /** 
     37     * returns the table column container 
    2838     * 
    29      * @var  string 
     39     * @return  stubDatabaseTableColumn 
    3040     */ 
    31     protected $name; 
    32     /** 
    33      * type of the column 
    34      * 
    35      * @var  string 
    36      */ 
    37     protected $type; 
    38     /** 
    39      * size of the field 
    40      * 
    41      * @var  int|string 
    42      */ 
    43     protected $size; 
    44     /** 
    45      * switch whether column is unsigned or not 
    46      * 
    47      * @var  bool 
    48      */ 
    49     protected $isUnsigned   = false; 
    50     /** 
    51      * switch whether the column can be null or not 
    52      * 
    53      * @var  bool 
    54      */ 
    55     protected $isNullable   = true; 
    56     /** 
    57      * default value of the column 
    58      * 
    59      * @var  mixed 
    60      */ 
    61     protected $defaultValue = null; 
    62     /** 
    63      * switch whether column is a primary key or not 
    64      * 
    65      * @var  bool 
    66      */ 
    67     protected $isPrimaryKey = false; 
    68     /** 
    69      * switch whether column is a key or not 
    70      * 
    71      * @var  bool 
    72      */ 
    73     protected $isKey        = false; 
    74     /** 
    75      * the name of the setter method to use for restoring the value from database 
    76      * 
    77      * @var  string 
    78      */ 
    79     protected $setterMethod = null; 
     41    public function getTableColumn() 
     42    { 
     43        return $this->dbTableColumn; 
     44    } 
    8045     
    8146    /** 
     
    9661    public function setOrder($order) 
    9762    { 
    98         $this->order = $order
     63        $this->dbTableColumn->setOrder($order)
    9964    } 
    100      
    101     /** 
    102      * returns the order within the table 
    103      * 
    104      * @return  int 
    105      */ 
    106     public function getOrder() 
    107     { 
    108         return $this->order; 
    109     } 
    110      
     65 
    11166    /** 
    11267     * sets the name of the column 
     
    11671    public function setName($name) 
    11772    { 
    118         $this->name = $name
     73        $this->dbTableColumn->setName($name)
    11974    } 
    12075 
    121     /** 
    122      * returns the name of the column 
    123      * 
    124      * @return  string 
    125      */ 
    126     public function getName() 
    127     { 
    128         return $this->name; 
    129     } 
    130      
    13176    /** 
    13277     * sets the type of the column 
     
    13681    public function setType($type) 
    13782    { 
    138         $this->type = $type
     83        $this->dbTableColumn->setType($type)
    13984    } 
    14085 
    141     /** 
    142      * returns the type of the column 
    143      * 
    144      * @return  string 
    145      */ 
    146     public function getType() 
    147     { 
    148         return $this->type; 
    149     } 
    150      
    15186    /** 
    15287     * sets the size of the column 
     
    15691    public function setSize($size) 
    15792    { 
    158         $this->size = $size
     93        $this->dbTableColumn->setSize($size)
    15994    } 
    16095 
    161     /** 
    162      * returns the size of the column 
    163      * 
    164      * @return  int|string 
    165      */ 
    166     public function getSize() 
    167     { 
    168         return $this->size; 
    169     } 
    170      
    17196    /** 
    17297     * set whether the column may be null or not 
     
    176101    public function setIsUnsigned($isUnsigned) 
    177102    { 
    178         if (is_string($isUnsigned) == true && 'false' == $isUnsigned) { 
    179             $isUnsigned = false; 
    180         } 
    181          
    182         $this->isUnsigned = $isUnsigned; 
     103        $this->dbTableColumn->setIsUnsigned($this->castToBool($isUnsigned)); 
    183104    } 
    184      
    185     /** 
    186      * check whether the column may be null or not 
    187      * 
    188      * @return  bool 
    189      */ 
    190     public function isUnsigned() 
    191     { 
    192         return (strstr(strtoupper($this->type), 'INT') == true && true == $this->isUnsigned); 
    193     } 
    194      
     105 
    195106    /** 
    196107     * set whether the column may be null or not 
     
    200111    public function setIsNullable($isNullable) 
    201112    { 
    202         if (is_string($isNullable) == true && 'false' == $isNullable) { 
    203             $isNullable = false; 
    204         } 
    205          
    206         $this->isNullable = $isNullable; 
     113        $this->dbTableColumn->setIsNullable($this->castToBool($isNullable)); 
    207114    } 
    208      
    209     /** 
    210      * check whether the column may be null or not 
    211      * 
    212      * @return  bool 
    213      */ 
    214     public function isNullable() 
    215     { 
    216         return (false == $this->isPrimaryKey && true == $this->isNullable); 
    217     } 
    218      
     115 
    219116    /** 
    220117     * sets the default value of the column 
     
    224121    public function setDefaultValue($defaultValue) 
    225122    { 
    226         $this->defaultValue = $defaultValue
     123        $this->dbTableColumn->setDefaultValue($defaultValue)
    227124    } 
    228125 
    229     /** 
    230      * returns the default value of the column 
    231      * 
    232      * @return  mixed 
    233      */ 
    234     public function getDefaultValue() 
    235     { 
    236         return $this->defaultValue; 
    237     } 
    238      
    239126    /** 
    240127     * set whether the column is a primary key or not 
     
    244131    public function setIsPrimaryKey($isPrimaryKey) 
    245132    { 
    246         if (is_string($isPrimaryKey) == true && 'false' == $isPrimaryKey) { 
    247             $isPrimaryKey = false; 
    248         } 
    249          
    250         $this->isPrimaryKey = $isPrimaryKey; 
    251     } 
    252      
    253     /** 
    254      * check whether the column is a primary key or not 
    255      * 
    256      * @return  bool 
    257      */ 
    258     public function isPrimaryKey() 
    259     { 
    260         return $this->isPrimaryKey; 
     133        $this->dbTableColumn->setIsPrimaryKey($this->castToBool($isPrimaryKey)); 
    261134    } 
    262135     
     
    268141    public function setIsKey($isKey) 
    269142    { 
    270         if (is_string($isKey) == true && 'false' == $isKey) { 
    271             $isKey = false; 
    272         } 
    273          
    274         $this->isKey = $isKey; 
     143        $this->dbTableColumn->setIsKey($this->castToBool($isKey)); 
    275144    } 
    276      
    277     /** 
    278      * check whether the column is a primary key or not 
    279      * 
    280      * @return  bool 
    281      */ 
    282     public function isKey() 
    283     { 
    284         return (false == $this->isPrimaryKey && true == $this->isKey); 
    285     } 
    286      
     145 
    287146    /** 
    288147     * set the name of the setter method 
     
    292151    public function setSetterMethod($setterMethod) 
    293152    { 
    294         $this->setterMethod = $setterMethod; 
     153        $this->dbTableColumn->setSetterMethod($setterMethod); 
     154    } 
     155 
     156    /** 
     157     * set the character set of the table 
     158     * 
     159     * @param  string  $characterSet 
     160     */ 
     161    public function setCharacterSet($characterSet) 
     162    { 
     163        $this->dbTableColumn->setCharacterSet($characterSet); 
    295164    } 
    296165     
    297166    /** 
    298      * checks whether the name of the setter method is known 
     167     * set the collation of the table 
    299168     * 
    300      * @return  bool 
     169     * @param  string  $collation 
    301170     */ 
    302     public function hasSetterMethod(
     171    public function setCollation($collation
    303172    { 
    304         return (null !== $this->setterMethod); 
     173        $this->dbTableColumn->setCollation($collation); 
    305174    } 
    306175     
    307176    /** 
    308      * returns the name of the setter method 
     177     * helper method to cast a value to bool 
    309178     * 
    310      * @return  string 
     179     * @param   mixed  $value 
     180     * @return  bool 
    311181     */ 
    312     public function getSetterMethod(
     182    protected function castToBool($value
    313183    { 
    314         return $this->setterMethod; 
     184        if (is_string($value) == true && 'false' == $value) { 
     185            return false; 
     186        } 
     187         
     188        return (bool) $value; 
    315189    } 
    316190} 
  • trunk/src/main/php/net/stubbles/rdbms/persistence/annotations/stubDBTableAnnotation.php

    r432 r482  
    88 */ 
    99stubClassLoader::load('net.stubbles.reflection.annotations.stubAnnotation', 
    10                       'net.stubbles.reflection.annotations.stubAbstractAnnotation' 
     10                      'net.stubbles.reflection.annotations.stubAbstractAnnotation', 
     11                      'net.stubbles.rdbms.querybuilder.stubDatabaseTableDescription' 
    1112); 
    1213/** 
     
    1920{ 
    2021    /** 
    21      * the name of the table 
     22     * the table description container 
    2223     * 
    23      * @var  string 
     24     * @var  stubDatabaseTableDescription 
    2425     */ 
    25     protected $name; 
     26    protected $tableDescription; 
     27     
    2628    /** 
    27      * type of the table 
     29     * constructor 
     30     */ 
     31    public function __construct() 
     32    { 
     33        $this->tableDescription = new stubDatabaseTableDescription(); 
     34    } 
     35     
     36    /** 
     37     * returns the table description container 
    2838     * 
    29      * @var  string 
     39     * @return  stubDatabaseTableDescription 
    3040     */ 
    31     protected $type; 
    32     /** 
    33      * the character set to use for this table 
    34      * 
    35      * @var  string 
    36      */ 
    37     protected $characterSet = null; 
    38     /** 
    39      * the collation to use for this table 
    40      * 
    41      * @var  string 
    42      */ 
    43     protected $collation    = null; 
    44     /** 
    45      * an optional comment for this table 
    46      * 
    47      * @var  string 
    48      */ 
    49     protected $comment      = null; 
     41    public function getTableDescription() 
     42    { 
     43        return $this->tableDescription; 
     44    } 
    5045     
    5146    /** 
     
    5651    public function getAnnotationTarget() 
    5752    { 
    58         return stubAnnotation::TARGET_CLASS + stubAnnotation::TARGET_METHOD
     53        return stubAnnotation::TARGET_CLASS
    5954    } 
    6055     
     
    6661    public function setName($name) 
    6762    { 
    68         $this->name = $name
     63        $this->tableDescription->setName($name)
    6964    } 
    7065 
    71     /** 
    72      * returns the name of the table 
    73      * 
    74      * @return  string 
    75      */ 
    76     public function getName() 
    77     { 
    78         return $this->name; 
    79     } 
    80      
    8166    /** 
    8267     * sets the type of the table 
     
    8671    public function setType($type) 
    8772    { 
    88         $this->type = $type
     73        $this->tableDescription->setType($type)
    8974    } 
    9075 
    91     /** 
    92      * returns the type of the table 
    93      * 
    94      * @return  string 
    95      */ 
    96     public function getType() 
    97     { 
    98         return $this->type; 
    99     } 
    100      
    10176    /** 
    10277     * sets the character set of the table 
     
    10681    public function setCharacterSet($characterSet) 
    10782    { 
    108         $this->characterSet = $characterSet
     83        $this->tableDescription->setCharacterSet($characterSet)
    10984    } 
    110      
    111     /** 
    112      * check if a character set is set 
    113      * 
    114      * @return  bool 
    115      */ 
    116     public function hasCharacterSet() 
    117     { 
    118         return (null !== $this->characterSet); 
    119     } 
    120      
    121     /** 
    122      * returns the character set of the table if set, else null 
    123      * 
    124      * @return  string 
    125      */ 
    126     public function getCharacterSet() 
    127     { 
    128         return $this->characterSet; 
    129     } 
    130      
     85 
    13186    /** 
    13287     * sets the collation of the table 
     
    13691    public function setCollation($collation) 
    13792    { 
    138         $this->collation = $collation
     93        $this->tableDescription->setCollation($collation)
    13994    } 
    140      
    141     /** 
    142      * check if a collation is set 
    143      * 
    144      * @return  bool 
    145      */ 
    146     public function hasCollation() 
    147     { 
    148         return (null !== $this->collation); 
    149     } 
    150      
    151     /** 
    152      * returns the collation of the table if set, else null 
    153      * 
    154      * @return  string 
    155      */ 
    156     public function getCollation() 
    157     { 
    158         return $this->collation; 
    159     } 
    160      
     95 
    16196    /** 
    16297     * sets the comment of the table 
     
    166101    public function setComment($comment) 
    167102    { 
    168         $this->comment = $comment; 
    169     } 
    170      
    171     /** 
    172      * check if a comment is set 
    173      * 
    174      * @return  bool 
    175      */ 
    176     public function hasComment() 
    177     { 
    178         return (null !== $this->comment); 
    179     } 
    180      
    181     /** 
    182      * returns the comment of the table if set, else null 
    183      * 
    184      * @return  string 
    185      */ 
    186     public function getComment() 
    187     { 
    188         return $this->comment; 
     103        $this->tableDescription->setComment($comment); 
    189104    } 
    190105} 
  • trunk/src/main/php/net/stubbles/rdbms/persistence/creator/stubDatabaseCreator.php

    r333 r482  
    88 */ 
    99stubClassLoader::load('net.stubbles.rdbms.stubDatabaseConnection', 
     10                      'net.stubbles.rdbms.persistence.annotations.stubDBColumnAnnotation', 
     11                      'net.stubbles.rdbms.persistence.annotations.stubDBJoinAnnotation', 
    1012                      'net.stubbles.rdbms.persistence.annotations.stubDBTableAnnotation', 
    11                       'net.stubbles.rdbms.persistence.annotations.stubDBColumnAnnotation', 
    1213                      'net.stubbles.rdbms.persistence.creator.stubDatabaseCreatorException', 
    1314                      'net.stubbles.rdbms.querybuilder.stubDatabaseQueryBuilderFactory', 
    14                       'net.stubbles.rdbms.querybuilder.stubDatabaseTableDescription', 
    15                       'net.stubbles.rdbms.querybuilder.stubDatabaseTableColumn', 
    1615                      'net.stubbles.reflection.reflection' 
    1716); 
     
    2423class stubDatabaseCreator extends stubBaseObject 
    2524{ 
    26      
    2725    /** 
    2826     * list of creator instances 
     
    3735     */ 
    3836    protected $connection; 
    39      
     37 
    4038    /** 
    4139     * constructor 
     
    4341     * @param  stubDatabaseConnection  $connection  connection to use for creating the tables 
    4442     */ 
    45     protected function __construct(stubDatabaseConnection $connection) 
     43    protected final function __construct(stubDatabaseConnection $connection) 
    4644    { 
    4745        $this->connection = $connection; 
    4846    } 
    49      
     47 
    5048    /** 
    5149     * method to return instances of the creator depending of the connection 
     
    5654     * 
    5755     * @param   stubDatabaseConnection  $connection  connection to use for creating the tables 
     56     * @param   bool                    $refresh     optional  set to true to recreate the instance 
    5857     * @return  stubDatabaseFinder 
    5958     */ 
    60     public function getInstance(stubDatabaseConnection $connection
     59    public function getInstance(stubDatabaseConnection $connection, $refresh = false
    6160    { 
    62         if (isset(self::$instances[$connection->hashCode()]) == false) { 
     61        if (isset(self::$instances[$connection->hashCode()]) == false || true == $refresh) { 
    6362            self::$instances[$connection->hashCode()] = new self($connection); 
    6463        } 
     
    6665        return self::$instances[$connection->hashCode()]; 
    6766    } 
    68      
     67 
    6968    /** 
    7069     * cloning is forbidden 
     
    7675        throw new stubDatabaseCreatorException('Cloning ' . $this->getClassName() . ' is not allowed.'); 
    7776    } 
    78      
     77 
    7978    /** 
    8079     * creates the table description from the given class 
     
    8584    public function createTable($fqClassName) 
    8685    { 
    87         $nqClassName = stubClassLoader::getNonQualifiedClassName($fqClassName); 
    88         if (class_exists($nqClassName, false) == false) { 
    89             stubClassLoader::load($fqClassName); 
    90         } 
    91          
    92         $refClass = new stubReflectionClass($nqClassName); 
     86        $refClass = new stubReflectionClass($fqClassName); 
    9387        if ($refClass->hasAnnotation('DBTable') == false) { 
    9488            throw new stubDatabaseCreatorException('Class ' . $refClass->getName() . ' is missing the DBTable annotation.'); 
    9589        } 
    9690         
    97         $dbTable          = $refClass->getAnnotation('DBTable'); 
    98         $tableDescription = new stubDatabaseTableDescription(); 
    99         $tableDescription->setName($dbTable->getName()); 
    100         $tableDescription->setType($dbTable->getType()); 
    101         $tableDescription->setCharacterSet($dbTable->getCharacterSet()); 
    102         $tableDescription->setCollation($dbTable->getCollation()); 
    103         $tableDescription->setComment($dbTable->getComment()); 
    104         $methods = $refClass->getMethods(); 
     91        $tableDescription = $refClass->getAnnotation('DBTable')->getTableDescription(); 
     92        $methods          = $refClass->getMethods(); 
    10593        foreach ($methods as $method) { 
    10694            if ($method->hasAnnotation('DBColumn') == false) { 
    10795                continue; 
    108             } elseif ($method->hasAnnotation('DBTable') == true && $method->getAnnotation('DBTable')->getName() != $tableDescription->getName()) { 
     96            } elseif ($method->hasAnnotation('DBJoin') == true && $method->getAnnotation('DBJoin')->getTableJoin()->getName() != $tableDescription->getName()) { 
    10997                continue; 
    11098            } 
    11199             
    112             $dbColumn = $method->getAnnotation('DBColumn'); 
    113             $columnDescription = new stubDatabaseTableColumn(); 
    114             $columnDescription->setOrder($dbColumn->getOrder()); 
    115             $columnDescription->setName($dbColumn->getName()); 
    116             $columnDescription->setType($dbColumn->getType()); 
    117  
    118             if (strtoupper($dbColumn->getType()) != 'TEXT') { 
    119                 $columnDescription->setSize(str_replace('_', ',', $dbColumn->getSize())); 
    120             } 
    121              
    122             $columnDescription->setIsUnsigned($dbColumn->isUnsigned()); 
    123             $columnDescription->setIsNullable($dbColumn->isNullable()); 
    124             $columnDescription->setDefaultValue($dbColumn->getDefaultValue()); 
    125             $columnDescription->setIsPrimaryKey($dbColumn->isPrimaryKey()); 
    126             $columnDescription->setIsKey($dbColumn->isKey()); 
    127             $tableDescription->addColumn($columnDescription); 
     100            $tableDescription->addColumn($method->getAnnotation('DBColumn')->getTableColumn()); 
    128101        } 
    129102         
     
    134107        } 
    135108    } 
     109 
     110    /** 
     111     * returns a unique hash code for the class 
     112     *  
     113     * Two creators are equal if they use the same connection. 
     114     * 
     115     * @return  string 
     116     */ 
     117    public function hashCode() 
     118    { 
     119        return 'creator:' . $this->connection->hashCode(); 
     120    } 
    136121} 
    137122?> 
  • trunk/src/main/php/net/stubbles/rdbms/persistence/finder/stubDatabaseFinder.php

    r256 r482  
    99stubClassLoader::load('net.stubbles.rdbms.stubDatabaseConnection', 
    1010                      'net.stubbles.rdbms.criteria.stubCriterion', 
    11                       'net.stubbles.rdbms.criteria.stubAndCriterion', 
    1211                      'net.stubbles.rdbms.criteria.stubEqualCriterion', 
    1312                      'net.stubbles.rdbms.persistence.stubPersistable', 
    1413                      'net.stubbles.rdbms.persistence.stubSetterMethodFactory', 
     14                      'net.stubbles.rdbms.persistence.annotations.stubDBColumnAnnotation', 
     15                      'net.stubbles.rdbms.persistence.annotations.stubDBJoinAnnotation', 
    1516                      'net.stubbles.rdbms.persistence.annotations.stubDBTableAnnotation', 
    16                       'net.stubbles.rdbms.persistence.annotations.stubDBColumnAnnotation', 
    1717                      'net.stubbles.rdbms.persistence.finder.stubDatabaseFinderException', 
    1818                      'net.stubbles.rdbms.querybuilder.stubDatabaseQueryBuilderFactory', 
     19                      'net.stubbles.rdbms.querybuilder.stubDatabaseSelect', 
    1920                      'net.stubbles.reflection.reflection' 
    2021); 
     
    3940     */ 
    4041    protected $connection; 
    41      
     42 
    4243    /** 
    4344     * constructor 
     
    4546     * @param  stubDatabaseConnection  $connection  connection to use for finding the data 
    4647     */ 
    47     protected function __construct(stubDatabaseConnection $connection) 
     48    protected final function __construct(stubDatabaseConnection $connection) 
    4849    { 
    4950        $this->connection = $connection; 
    5051    } 
    51      
     52 
    5253    /** 
    5354     * method to return instances of the finder depending of the connection 
     
    5859     * 
    5960     * @param   stubDatabaseConnection  $connection  connection to use for finding the data 
     61     * @param   bool                    $refresh     optional  set to true to recreate the instance 
    6062     * @return  stubDatabaseFinder 
    6163     */ 
    62     public function getInstance(stubDatabaseConnection $connection
    63     { 
    64         if (isset(self::$instances[$connection->hashCode()]) == false) { 
     64    public function getInstance(stubDatabaseConnection $connection, $refresh = false
     65    { 
     66        if (isset(self::$instances[$connection->hashCode()]) == false || true == $refresh) { 
    6567            self::$instances[$connection->hashCode()] = new self($connection); 
    6668        } 
     
    6870        return self::$instances[$connection->hashCode()]; 
    6971    } 
    70      
     72 
    7173    /** 
    7274     * cloning is forbidden 
     
    7880        throw new stubDatabaseFinderException('Cloning ' . $this->getClassName() . ' is not allowed.'); 
    7981    } 
    80      
     82 
    8183    /** 
    8284     * get a persistable object from database by its primary keys 
     
    8890    public function findByPrimaryKeys(stubPersistable $persistable) 
    8991    { 
    90         $refObject      = $persistable->getClass(); 
    91         $annotationData = $this->getAnnotationData($refObject); 
     92        $refObject = $persistable->getClass(); 
     93        $select    = $this->createSelect($refObject); 
    9294        try { 
    93             $result = $this->connection->query(stubDatabaseQueryBuilderFactory::create($this->connection)->createSelect($annotationData['criterion'], $annotationData['tables'])); 
     95            $result = $this->connection->query(stubDatabaseQueryBuilderFactory::create($this->connection)->createSelect($select)); 
    9496            $data   = $result->fetch(); 
     97            $result->free(); 
    9598        } catch (stubException $se) { 
    9699            throw new stubDatabaseFinderException('Can not find instance of ' . $refObject->getFullQualifiedClassName() . ' by its primary keys.', $se); 
     
    100103            return; 
    101104        } 
    102         $result->free(); 
    103  
    104         foreach ($annotationData['setterMethods'] as $dataName => $setterMethod) { 
    105             if (isset($data[$dataName]) == false) { 
    106                 continue; 
    107             } 
    108              
    109             $setterMethod->invoke($persistable, $data[$dataName]); 
    110         } 
    111          
    112         $persistable->setPersistent(true); 
     105         
     106        $select->fillPersistable($persistable, $data); 
    113107    } 
    114108 
     
    118112     * @param   stubCriterion                 $criterion 
    119113     * @param   string                        $persistableClassName  non qualified classname of the persistable class to find instances of 
     114     * @param   array                         $arguments             optional  arguments for constructor 
    120115     * @return  array<$persistableClassName>  list of instances of $persistableClassName found with $criterion