YetOrm – získání id nově vytvořené entity

chikeet
Člen | 160
+
0
-

Zdravím,
používám YetOrm, jako id mám UUID4 a potřebuju získat id právě vloženého řádku. Z entity ho po persistu nevytáhnu, protože
The value of column 'id' not set.

Přes Nette\Database::getInsertId taky ne, protože Error in transaction: SQLSTATE[55000]: Object not in prerequisite state: 7 ERROR: lastval is not yet defined in this session.

Zkoušela jsem s transakcí i bez transakce, problém stejný. Jak na to?

CZechBoY
Člen | 3608
+
0
-

Proč potřebuješ zjistit vložený id když ho generuješ před vložením?

chikeet
Člen | 160
+
0
-

CZechBoY napsal(a):

Proč potřebuješ zjistit vložený id když ho generuješ před vložením?

Já ho negeneruju, generuje se automaticky v databázi, protože nechci při každém insertu kontrolovat jeho unikátnost. Používám PostgreSQL.

David Matějka
Moderator | 6445
+
+3
-

ohledně unikátnosti uuid bych si nedělal starosti :) If every person on the planet generates a new UUID4 every second, we’d expect a collision to occur after about 10 years.

a pokud by se tak opravdu velkou náhodou stalo, tak zkrátka selže unique constraint.

jednou z výhod uuid je právě to, že se nemusejí generovat databází, ale mohu je vygenerovat v aplikaci

uestla
Backer | 796
+
0
-

@chikeet To je zvláštní, jakou verzi YetORM používáš? Vložený řádek by se měl po persistu nastavovat:

https://github.com/…pository.php#L149

chikeet
Člen | 160
+
0
-

uestla napsal(a):

@chikeet To je zvláštní, jakou verzi YetORM používáš? Vložený řádek by se měl po persistu nastavovat:

https://github.com/…pository.php#L149

Používám 10.1.2. Měla jsem ve svém BaseRepository::persist nějaké legacy zbytečnosti z jiného projektu, takže jsem to maximálně zjednodušila podle Repository::persist. Háže mi to ale Error in transaction: Insert did not return instance of Nette\\Database\\IRow. Does table \"example\" have primary key defined? If so, try cleaning cache. PK mám definovaný, cache promazanou.

Můj persist teď vypadá takto:

public function persist(YetORM\Entity $entity, ?User $updatedByUser = null): bool
	{
		/* events before persist */
        $isUpdate = $entity->toRecord()->hasRow();
		if ($isUpdate) {
			$this->onBeforeUpdate($entity, $updatedByUser);
		} else {
			$this->onBeforeInsert($entity);
		}

		$this->checkEntity($entity);

		$result = $this->transaction(function () use ($entity) {

			$record = $entity->toRecord();
			if ($record->hasRow()) {
				return $record->update();
			}

			$inserted = $this->getTable()
				->insert($record->getModified());

			if (!$inserted instanceof \Nette\Database\IRow) {
				throw new YetOrm\Exception\InvalidStateException('Insert did not return instance of ' . \Nette\Database\IRow::class . '. '
					. 'Does table "' . $this->getTableName() . '" have primary key defined? If so, try cleaning cache.');
			}

			$record->setRow($inserted);
			return TRUE;
		});

		/* events after persist */
		if ($isUpdate) {
			$this->onAfterUpdate($entity, $updatedByUser);
		} else {
			$this->onAfterInsert($entity);
		}

		return $result;
}

Nějaký nápad, čím to může být? Když to nepůjde, tak budu holt generovat idčka v PHP, ale v db by mi to bylo milejší vzhledem k tomu, že už to mám všude definované.

Pavel Kravčík
Člen | 1180
+
-1
-

A je nastavený ten primární klíč v DB s AI?

uestla
Backer | 796
+
0
-

@chikeet Insert na úrovni Selection je poměrně robustní, co se detekce hodnoty primárního klíče týče:
https://github.com/…election.php#L863

Je to sice hrabání ve vnitřnostech, ale možná to je cesta.

chikeet
Člen | 160
+
+1
-

uestla napsal(a):

@chikeet Insert na úrovni Selection je poměrně robustní, co se detekce hodnoty primárního klíče týče:
https://github.com/…election.php#L863

Je to sice hrabání ve vnitřnostech, ale možná to je cesta.

Nakonec vyřešeno generováním ID v PHP – cesta nejmenšího odporu a i jinak celkem smysluplná.