Comments (7)
I have not encountered any issues with generators myself. Transactions or not.
However, you will have to use savepoints with Firebird. This is achieved by calling #Connection->setNestTransactionsWithSavepoints(true)
.
If you are using Symfony, you can add a compiler pass to ensure this. Something like:
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
class SetupDoctrinePass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
$entityManager = $container->get('doctrine.orm.default_entity_manager');
$entityManager->getConnection()->setNestTransactionsWithSavepoints(true);
}
}
It's old syntax/code. May be different in Symfony 4.x.
What version of kafoso/doctrine-firebird-driver are you using?
Things to consider
Annotations could be incorrect
If you are using PHP annotations, it should look something like this:
use Doctrine\ORM\Mapping as ORM;
class Message
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="SEQUENCE")
* @ORM\SequenceGenerator(sequenceName="message_seq", initialValue=1, allocationSize=100)
*/
protected $id = null;
//...
}
Could you please provide a sample snippet of your annotations?
Database trigger at fault
There may be a database trigger, which causes the conflict.
from doctrine-firebird-driver.
Thanks for atention;
I use:
Zendframework: 3.0
kafoso/doctrine-firebird-driver: 2.6.2
Firebird 2.5 x86
PHP 7.2
namespace Application\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Pedidoit
*
* @ORM\Table(name="pedidoit", uniqueConstraints={@ORM\UniqueConstraint(name="UN_PRODPED", columns={"COD_PED", "COD_PROD"})})
* @ORM\Entity
* @ORM\Entity(repositoryClass="Application\Entity\PedidoitRepository")
*/
class Pedidoit extends AbstractEntity{
/**
* @var integer
*
* @ORM\Column(name="COD_PEDIT", type="integer", nullable=false)
* @ORM\Id
* @ORM\GeneratedValue(strategy="SEQUENCE")
* @ORM\SequenceGenerator(sequenceName="GE_IDPEDIDOIT", initialValue=1, allocationSize=100000)
*/
private $codPedit;
But the problem remains
Code where start Transaction.
try {
$this->getEm()->getConnection()->setNestTransactionsWithSavepoints(true);
$this->getEm()->beginTransaction();
$trocarPedidoProdutoComplementoService = $this->getEvent()->getApplication()->getServiceManager()->get(TrocarPedidoProdutoComplementoService::class);
$pedido = $trocarPedidoProdutoComplementoService->save($data);
$this->getEm()->commit();
} catch (\Exception $exc) {
$this->getEm()->rollback();
echo $exc->getMessage();
}
from doctrine-firebird-driver.
I dont have trigger...in my database.
from doctrine-firebird-driver.
Thanks.
I can't really see what goes on inside your service class ($trocarPedidoProdutoComplementoService->save(...)
). Thus, I don't know if you are persisting and flushing things correctly.
I've made a quick test and it does work for me.
SQL:
RECREATE TABLE SEQUENCEGENERATORTABLE (
id INT NOT NULL,
PRIMARY KEY(id)
);
CREATE SEQUENCE GEN_SEQUENCEGENERATORTABLE_ID;
ALTER SEQUENCE GEN_SEQUENCEGENERATORTABLE_ID RESTART WITH 0;
Doctrine Entity:
<?php
namespace Kafoso\DoctrineFirebirdDriver\Test\Resource\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ORM\Table(name="SEQUENCEGENERATORTABLE")
*/
class SequenceGeneratorEntity
{
/**
* @ORM\Column(type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="SEQUENCE")
* @ORM\SequenceGenerator(sequenceName="GEN_SEQUENCEGENERATORTABLE_ID", initialValue=1, allocationSize=100000)
*/
private $id = null;
/**
* @return null|int
*/
public function getId()
{
return $this->id;
}
}
PHP test:
...
public function testCanPersistMultipleInTransaction()
{
$albumA = new Entity\SequenceGeneratorEntity;
$albumB = new Entity\SequenceGeneratorEntity;
$albumC = new Entity\SequenceGeneratorEntity;
$this->_entityManager->beginTransaction();
$this->_entityManager->persist($albumA);
$this->_entityManager->persist($albumB);
$this->_entityManager->persist($albumC);
$this->_entityManager->flush();
$this->_entityManager->commit();
$rows = $this->_entityManager->getConnection()->fetchAll("SELECT * FROM SEQUENCEGENERATORTABLE");
$expected = [
['ID' => 1],
['ID' => 2],
['ID' => 3],
];
$this->assertSame($expected, $rows);
$this->assertSame(1, $albumA->getId());
$this->assertSame(2, $albumB->getId());
$this->assertSame(3, $albumC->getId());
}
...
Test passes.
A side note
$this->getEm()->beginTransaction();
should go before the try
. If the transaction somehow fails to start, and you end up in the catch
, you are now either:
- Causing another failure, because
rollback
has no transaction to working with. This means the exception, you catch, is for naught, because therollback
will cause a third, unintended exception. - Rolling back a parent transaction, in case they are nested. This could be very bad.
from doctrine-firebird-driver.
Dear friend,
First of all I would like to thank you for "A side note" because you are absolutely right.
I made the correction as measured.
With the test you presented me, I identified where the problem happens.
public function saveItens() {
if (isset($this->dados['pedidosItem']) && (sizeof($this->dados['pedidosItem']) > 0)) {
$savePedidoItService = new SavePedidoItService($this->getEm());
foreach ($this->dados['pedidosItem'] as $arrayPedidoIt){
$savePedidoItService->save($arrayPedidoIt);
}
}
}
Persistence Method
public function save(Array $data = array()){
$entity = new $this->entity($data);
$this->em->persist($entity);
$this->em->flush();
return $entity;
}
Watching, I realized that I'm flushing every time I save. What is wrong.
Then the correct would be.
public function saveItens() {
if (isset($this->dados['pedidosItem']) && (sizeof($this->dados['pedidosItem']) > 0)) {
$savePedidoItService = new SavePedidoItService($this->getEm());
foreach ($this->dados['pedidosItem'] as $arrayPedidoIt){
$savePedidoItService->save($arrayPedidoIt);
}
$this->getEm()->flush();
}
}
Remove the flush from the persistence method.
public function save(Array $data = array()){
$entity = new $this->entity($data);
$this->em->persist($entity);
return $entity;
}
Amazing that the problem repeats with the generator.
I used
$this->em = $this->getEvent()->getApplication()->getServiceManager()->get(\Doctrine\ORM\EntityManager::class);
To inject EntityManager in my controlller.
What is the best practice to Inject?
from doctrine-firebird-driver.
I see that you are flushing everything. I.e. no argument in the ->flush()
call. I'm not sure that's what you want to do.
Could you try either of these two things and report back what you find:
1: Flush each entity separately
...
$entity = new MyEntity;
$em->persist($entity);
$em->flush($entity);
...
2: Flush all newly created entities by passing array
...
$entityA = new MyEntity;
$em->persist($entityA);
$entityB = new MyEntity;
$em->persist($entityB);
$em->flush([$entityA, $entityB]);
...
from doctrine-firebird-driver.
Dear Friend;
I appreciate your time and all the tips. But as for the generator problem I couldn't solve it. So I made a trigger to check the generator, and correct if necessary.
This was the solution.
Thank you very mutch.
from doctrine-firebird-driver.
Related Issues (11)
- Composer extension requirement HOT 2
- Problem on some serveur: General error: -303 Dynamic SQL Error SQL error code = -303 arithmetic exception, numeric overflow, or string truncation HOT 2
- Firebird v3.* support HOT 4
- pdo_firebird HOT 2
- Upgrading to latest doctrine version HOT 7
- hex syntax support HOT 4
- Missing checkLastApiCall() HOT 3
- Dialect parameter HOT 2
- Error in transactions (update, insert) HOT 5
- The driver is incompatible with PHP 7.4 HOT 15
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from doctrine-firebird-driver.