Transaction in multiple model repositories

Notice: This thread is very old.
pseudonym
Member | 57
+
0
-

Hi,
I wonder if there is a way to operate with transactions in multiple model repositories. I have my repositories inherited from Repository class like in this tutorial https://doc.nette.org/cs/quickstart.

I have for example three tables user, announcement and linking table userAnnouncement which contains id, userID and announcementID and flag read. I want to begin transaction, insert announcement to announcement table and fill linking table userAnnouncement with pairs userID and announcementID of inserted announcement. If all rows are inserted successfully I want to commit transaction, otherwise I want to rollback changes.

I am thinking that I create wrapper methods for beginTransaction(), commitTransaction() and rollback() in class Repository which all other repositories extends.

My question is whether it will be working on all instances of repositories if I for example will call transaction methods on instance of UserRepository. Example:

// autowired AnnouncementRepository
private $announcementRepository;

// autowired userAnnouncementRepository
private $userAnnouncementRepository;


public function addAnnouncement($data, $users)
{
	$this->announcementRepository->beginTransaction();
	$row = $this->announcementRepository->add($data);

	if ($row === false)
	{
		$result = false;
	}
	else
	{
		foreach ($users as $user)
		{
			$result = $this->userAnnouncementRepository->add($row->id, $user->id);

			if ($result === false)
			{
				break;
			}
		}
	}

	if ($result === false)
	{
		$announcementRepository->rollbackTransaction();
	}
	else
	{
		$announcementRepository->commitTransaction();
	}
}

Example is trimmed on purpose. It will be this snipped working? It will rollback only table announcement or also userAnnouncement?

I tried to begin transaction on both repositories but Nette said ‘There is already an active transaction’ on the line of second beginTransaction().

Edit:
I am sorry for unnecessary topic, I tried it and it working. But maybe someone could explain it to me. It is because transaction are trigerred over database and it has nothing to do with repositories? Could someone please provide exact explanation?

Last edited by pseudonym (2013-10-14 17:08)

Majkl578
Moderator | 1364
+
0
-

It's sad Nette Database doesn't support emulate nested transactions. E.g. Doctrine does.

It is because transaction are trigerred over database and it has nothing to do with repositories?

Yes, transactions are directly sent to database. I guess you use MySQL, which does not support transactions nesting, so it ends up with an error.

pseudonym
Member | 57
+
0
-

Yes, I am using MySQL.

duke
Member | 650
+
0
-

In MySQL there is a support for savepoints. To see how it's possible to emulate nested transactions using savepoints, you can take a look here.