Changeset 1066
- Timestamp:
- 11/26/07 16:55:12 (11 months ago)
- Files:
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/src/main/php/net/stubbles/rdbms/persistence/serializer/stubDatabaseSerializer.php
r1051 r1066 85 85 86 86 /** 87 * takes an entity and serializes it into the database87 * takes an entity and inserts it into the database 88 88 * 89 89 * @param object $entity … … 92 92 * @throws stubPersistenceException 93 93 */ 94 public function serialize($entity)94 public function insert($entity) 95 95 { 96 96 if (is_object($entity) === false) { … … 103 103 } 104 104 105 $tableRow = new stubDatabaseTableRow($this->getTableDescription($entityClass)->getName()); 106 $methods = $entityClass->getMethods(); 107 $singlePrimaryKey = null; 108 $defaultValues = array(); 105 $stuff = $this->processEntity($entityClass, $entity, self::INSERT); 106 try { 107 $this->processInsertQueries($this->getInsertQuery($stuff['tableRow'], $entity, $stuff['defaultValues']), $entity, array_shift($stuff['primaryKeys'])); 108 } catch (stubDatabaseException $dbe) { 109 throw new stubDatabaseSerializerException('Can not persist ' . $entityClass->getFullQualifiedClassName() . ': a database error occured.', $dbe); 110 } 111 112 return self::INSERT; 113 } 114 115 /** 116 * takes an entity and updates its database entry 117 * 118 * @param object $entity 119 * @return string 120 * @throws stubDatabaseSerializerException 121 * @throws stubPersistenceException 122 */ 123 public function update($entity) 124 { 125 if (is_object($entity) === false) { 126 throw new stubIllegalArgumentException('Can only serialize objects.'); 127 } 128 129 $entityClass = (($entity instanceof stubObject) ? ($entity->getClass()) : (new stubReflectionObject($entity))); 130 if ($entityClass->hasAnnotation('Entity') === false) { 131 throw new stubPersistenceException('Class ' . $entityClass->getFullQualifiedClassName() . ' is not an entity.'); 132 } 133 134 $stuff = $this->processEntity($entityClass, $entity, self::UPDATE); 135 try { 136 $this->processUpdateQueries($this->getUpdateQuery($stuff['tableRow'], $stuff['defaultValues'])); 137 } catch (stubDatabaseException $dbe) { 138 throw new stubDatabaseSerializerException('Can not persist ' . $entityClass->getFullQualifiedClassName() . ': a database error occured.', $dbe); 139 } 140 141 return self::UPDATE; 142 } 143 144 /** 145 * takes an entity and serializes it into the database 146 * 147 * @param object $entity 148 * @return string 149 * @throws stubDatabaseSerializerException 150 * @throws stubPersistenceException 151 */ 152 public function serialize($entity) 153 { 154 if (is_object($entity) === false) { 155 throw new stubIllegalArgumentException('Can only serialize objects.'); 156 } 157 158 $entityClass = (($entity instanceof stubObject) ? ($entity->getClass()) : (new stubReflectionObject($entity))); 159 if ($entityClass->hasAnnotation('Entity') === false) { 160 throw new stubPersistenceException('Class ' . $entityClass->getFullQualifiedClassName() . ' is not an entity.'); 161 } 162 163 $stuff = $this->processEntity($entityClass, $entity); 164 if (count($stuff['primaryKeys']) > 1) { 165 throw new stubDatabaseSerializerException('Persistence error for ' . $entityClass->getFullQualifiedClassName() . ': only one primary key can be null, but at least two primary keys are null: ' . join(', ', array_keys($stuff['primaryKeys']))); 166 } 167 168 if ($stuff['tableRow']->hasCriterion() === true) { 169 try { 170 $this->processUpdateQueries($this->getUpdateQuery($stuff['tableRow'], $stuff['defaultValues'])); 171 } catch (stubDatabaseException $dbe) { 172 throw new stubDatabaseSerializerException('Can not persist ' . $entityClass->getFullQualifiedClassName() . ': a database error occured.', $dbe); 173 } 174 175 return self::UPDATE; 176 } 177 178 try { 179 $this->processInsertQueries($this->getInsertQuery($stuff['tableRow'], $entity, $stuff['defaultValues']), $entity, array_shift($stuff['primaryKeys'])); 180 } catch (stubDatabaseException $dbe) { 181 throw new stubDatabaseSerializerException('Can not persist ' . $entityClass->getFullQualifiedClassName() . ': a database error occured.', $dbe); 182 } 183 184 return self::INSERT; 185 } 186 187 /** 188 * processes the entity: create another presentation of data 189 * 190 * @param stubBaseReflectionClass $entityClass 191 * @param object $entity 192 * @param string $type optional 193 * @return array 194 */ 195 protected function processEntity(stubBaseReflectionClass $entityClass, $entity, $type = null) 196 { 197 $tableRow = new stubDatabaseTableRow($this->getTableDescription($entityClass)->getName()); 198 $methods = $entityClass->getMethods(); 199 $primaryKeys = array(); 200 $defaultValues = array(); 109 201 foreach ($methods as $method) { 110 202 $column = $this->getTableColumn($method); … … 120 212 121 213 if ($column->isPrimaryKey() === true) { 122 if (null === $value) { 123 if (null !== $singlePrimaryKey) { 124 throw new stubDatabaseSerializerException('Persistence error for ' . $entityClass->getFullQualifiedClassName() . ': only one primary key can be null, but at least two primary keys are null: ' . $singlePrimaryKey['propertyName'] . ' and ' . $method->getName()); 125 } 126 127 $singlePrimaryKey = array('setterMethod' => stubSetterMethodHelper::create($column, $entityClass, $method->getName()), 128 'tableName' => $tableRow->getTableName() 129 ); 130 continue; 214 if (null === $value && self::UPDATE === $type) { 215 throw new stubDatabaseSerializerException('Persistence error for ' . $entityClass->getFullQualifiedClassName() . ': should be updated, but one primary key column is null: ' . $method->getName()); 216 } elseif (null === $value) { 217 $primaryKeys[$method->getName()] = array('setterMethod' => stubSetterMethodHelper::create($column, $entityClass, $method->getName()), 218 'tableName' => $tableRow->getTableName() 219 ); 220 } elseif (self::INSERT === $type) { 221 $tableRow->setColumn($column->getName(), $value); 131 222 } else { 132 223 $tableRow->addCriterion(new stubEqualCriterion($column->getName(), $value, $tableRow->getTableName())); … … 148 239 } 149 240 150 try { 151 $this->processQueries($this->getQuery($tableRow, $entity, $defaultValues), $entity, $singlePrimaryKey); 152 } catch (stubDatabaseException $dbe) { 153 throw new stubDatabaseSerializerException('Can not persist ' . $entityClass->getFullQualifiedClassName() . ': a database error occured.', $dbe); 154 } 155 156 return (($tableRow->hasCriterion() === true) ? (self::UPDATE) : (self::INSERT)); 157 } 158 159 /** 160 * build the query out of the serialized value 241 return array('tableRow' => $tableRow, 242 'defaultValues' => $defaultValues, 243 'primaryKeys' => $primaryKeys 244 ); 245 } 246 247 /** 248 * creates the queries required to process the insert 161 249 * 162 250 * @param stubDatabaseTableRow $tableRow 251 * @param object $entity 163 252 * @param array $defaultValues 164 * @return array<string ,string>165 * @throws 166 */ 167 protected function get Query(stubDatabaseTableRow $tableRow, $entity, array $defaultValues)253 * @return array<string> 254 * @throws stubDatabaseSerializerException 255 */ 256 protected function getInsertQuery(stubDatabaseTableRow $tableRow, $entity, array $defaultValues) 168 257 { 169 258 $queryBuilder = stubDatabaseQueryBuilderFactory::create($this->connection); 170 259 try { 171 // criterion for update exists => update172 if ($tableRow->hasCriterion() === true) {173 // set any null values174 foreach ($defaultValues as $defaultValue) {175 $tableRow->setColumn($defaultValue['column'], $defaultValue['value']);176 }177 178 return $queryBuilder->createUpdate(array($tableRow->getTableName() => $tableRow));179 }180 181 260 // fill default values into entity and table row 182 261 foreach ($defaultValues as $defaultValue) { … … 192 271 193 272 /** 194 * process the queries 273 * creates the queries required to process the update 274 * 275 * @param stubDatabaseTableRow $tableRow 276 * @param array $defaultValues 277 * @return array<string> 278 * @throws stubDatabaseSerializerException 279 */ 280 protected function getUpdateQuery(stubDatabaseTableRow $tableRow, array $defaultValues) 281 { 282 $queryBuilder = stubDatabaseQueryBuilderFactory::create($this->connection); 283 try { 284 foreach ($defaultValues as $defaultValue) { 285 $tableRow->setColumn($defaultValue['column'], $defaultValue['value']); 286 } 287 288 return $queryBuilder->createUpdate(array($tableRow->getTableName() => $tableRow)); 289 } catch (stubIllegalArgumentException $iae) { 290 throw new stubDatabaseSerializerException('Creating the queries failed.', $iae); 291 } 292 } 293 294 /** 295 * process insert queries 195 296 * 196 297 * @param array<string,string> $queries list of queries to process … … 199 300 * @throws stubDatabaseException 200 301 */ 201 protected function process Queries(array $queries, $entity, array $singlePrimaryKey = null)302 protected function processInsertQueries(array $queries, $entity, array $singlePrimaryKey = null) 202 303 { 203 304 foreach ($queries as $tableName => $query) { … … 210 311 211 312 /** 313 * process update queries 314 * 315 * @param array<string,string> $queries list of queries to process 316 * @param object $entity the entity to process the queries for 317 * @param array<string,string> $singlePrimaryKey optional information about the single primary key 318 * @throws stubDatabaseException 319 */ 320 protected function processUpdateQueries(array $queries) 321 { 322 foreach ($queries as $tableName => $query) { 323 $this->connection->exec($query); 324 } 325 } 326 327 /** 212 328 * returns a unique hash code for the class 213 329 * trunk/src/test/php/net/stubbles/rdbms/persistence/serializer/stubDatabaseSerializerTestCase.php
r997 r1066 100 100 * check that a non-object throws an exception 101 101 */ 102 public function testInsertNonObject() 103 { 104 $this->expectException('stubIllegalArgumentException'); 105 $this->dbSerializer->insert('foo'); 106 } 107 108 /** 109 * test that trying to find a class that does not have an entity annotation throws an exception 110 */ 111 public function testInsertNonEntity() 112 { 113 $this->expectException('stubPersistenceException'); 114 $this->dbSerializer->insert(new MockNoEntityAnnotationEntity()); 115 } 116 117 /** 118 * check that a non-object throws an exception 119 */ 120 public function testUpdateNonObject() 121 { 122 $this->expectException('stubIllegalArgumentException'); 123 $this->dbSerializer->update('foo'); 124 } 125 126 /** 127 * test that trying to find a class that does not have an entity annotation throws an exception 128 */ 129 public function testUpdateNonEntity() 130 { 131 $this->expectException('stubPersistenceException'); 132 $this->dbSerializer->update(new MockNoEntityAnnotationEntity()); 133 } 134 135 /** 136 * check that a non-object throws an exception 137 */ 102 138 public function testSerializeNonObject() 103 139 { … … 119 155 */ 120 156 public function testInsertWithSinglePrimaryKey() 157 { 158 $singlePrimaryKeyEntity = new MockSinglePrimaryKeyEntity(); 159 $this->mockConnection->setReturnValue('getLastInsertId', 'mockId'); 160 $this->mockConnection->expectCallcount('exec', 1); 161 $this->mockQueryBuilder->setInsertQueries(array('foo' => 'foo')); 162 $this->assertEqual($this->dbSerializer->insert($singlePrimaryKeyEntity), stubDatabaseSerializer::INSERT); 163 $this->assertEqual($this->mockQueryBuilder->getCallCount('createInsert'), 1); 164 $this->assertEqual($this->mockQueryBuilder->getCallCount('createUpdate'), 0); 165 $tableRows = $this->mockQueryBuilder->getInsertTableRows(); 166 $this->assertEqual(count($tableRows), 1); 167 $this->assertTrue(isset($tableRows['foo'])); 168 $this->assertEqual($singlePrimaryKeyEntity->getId(), 'mockId'); 169 $this->assertEqual($tableRows['foo']->getColumns(), array('bar' => 'this is bar', 'default' => 'example')); 170 $this->assertFalse($tableRows['foo']->hasCriterion()); 171 } 172 173 /** 174 * test insert with a single primary key 175 */ 176 public function testInsertWithSinglePrimaryKeyAlreadySet() 177 { 178 $singlePrimaryKeyEntity = new MockSinglePrimaryKeyEntity(); 179 $singlePrimaryKeyEntity->setId('mockId'); 180 $this->mockConnection->expectNever('getLastInsertId'); 181 $this->mockConnection->expectCallcount('exec', 1); 182 $this->mockQueryBuilder->setInsertQueries(array('foo' => 'foo')); 183 $this->assertEqual($this->dbSerializer->insert($singlePrimaryKeyEntity), stubDatabaseSerializer::INSERT); 184 $this->assertEqual($this->mockQueryBuilder->getCallCount('createInsert'), 1); 185 $this->assertEqual($this->mockQueryBuilder->getCallCount('createUpdate'), 0); 186 $tableRows = $this->mockQueryBuilder->getInsertTableRows(); 187 $this->assertEqual(count($tableRows), 1); 188 $this->assertTrue(isset($tableRows['foo'])); 189 $this->assertEqual($singlePrimaryKeyEntity->getId(), 'mockId'); 190 $this->assertEqual($tableRows['foo']->getColumns(), array('id' => 'mockId', 'bar' => 'this is bar', 'default' => 'example')); 191 $this->assertFalse($tableRows['foo']->hasCriterion()); 192 } 193 194 /** 195 * test update with a single primary key 196 */ 197 public function testUpdateWithSinglePrimaryKey() 198 { 199 $singlePrimaryKeyEntity = new MockSinglePrimaryKeyEntity(); 200 $singlePrimaryKeyEntity->setId('mockId'); 201 $singlePrimaryKeyEntity->setDefaultValue('anotherExample'); 202 $this->mockConnection->expectNever('getLastInsertId'); 203 $this->mockConnection->expectCallcount('exec', 1); 204 $this->mockQueryBuilder->setUpdateQueries(array('foo' => 'foo')); 205 $this->assertEqual($this->dbSerializer->update($singlePrimaryKeyEntity), stubDatabaseSerializer::UPDATE); 206 $this->assertEqual($this->mockQueryBuilder->getCallCount('createInsert'), 0); 207 $this->assertEqual($this->mockQueryBuilder->getCallCount('createUpdate'), 1); 208 $tableRows = $this->mockQueryBuilder->getUpdateTableRows(); 209 $this->assertEqual(count($tableRows), 1); 210 $this->assertTrue(isset($tableRows['foo'])); 211 $this->assertEqual($singlePrimaryKeyEntity->getId(), 'mockId'); 212 $this->assertEqual($tableRows['foo']->getColumns(), array('bar' => 'this is bar', 'default' => 'anotherExample')); 213 $this->assertTrue($tableRows['foo']->hasCriterion()); 214 $this->assertEqual($tableRows['foo']->getCriterion()->toSQL(), "(`foo`.`id` = 'mockId')"); 215 } 216 217 /** 218 * test insert with a single primary key 219 */ 220 public function testSerializeInsertWithSinglePrimaryKey() 121 221 { 122 222 $singlePrimaryKeyEntity = new MockSinglePrimaryKeyEntity(); … … 138 238 * test update with a single primary key 139 239 */ 140 public function test UpdateWithSinglePrimaryKey()240 public function testSerializeUpdateWithSinglePrimaryKey() 141 241 { 142 242 $singlePrimaryKeyEntity = new MockSinglePrimaryKeyEntity();
