Unable to create table in MySQL using Doctrine and Symfony2 - mysql

I am working with Symfony2 and Doctrine ORM using MySql .
After creating an Entity, I am not able to create the table. It throws an exception.
anu#anu-bridge:/var/www/Symfony$ php app/console doctrine:schema:update --force --dump-sql
[Doctrine\DBAL\Schema\SchemaException]
The table with name 'product' already exists.
doctrine:schema:update [--complete] [--dump-sql] [--force] [--em[="..."]]
I tried to drop it , but still it throws the error.
anu#anu-bridge:/var/www/Symfony$ php app/console doctrine:schema:drop --force
Dropping database schema...
[Doctrine\DBAL\Schema\SchemaException]
The table with name 'product' already exists.
doctrine:schema:drop [--dump-sql] [--force] [--full-database] [--em[="..."]]
[Doctrine\DBAL\Schema\SchemaException]
The table with name 'product' already exists.
There is no tables in the database. Cleared all the cache for symfony and doctrine, but still the error is throwing.
Symfony2 version is 2.0.1 .

I've had a similar problem. Most likely you have two entities named Category inside different Bundles. For instance:
src/Acme/SomeBundle/Entity/Product.php
src/Acme/OtherBundle/Entity/Product.php
Comment one of these files and retry the console command.

I was getting this problem from a conflict with join table defined in an association class annotation and a join table defined in a ManyToMany annotation.
The mapping definitions in two entities with a direct ManytoMany relationship appeared to result in the automatic creation of the join table using the 'joinTable' annotation. However the join table was already defined by an annotation in its underlying entity class and I wanted it to use this association entity class's own field definitions so as to extend the join table with additional custom fields.
The explanation and solution was thanks to this post in the forum 'Doctrine Annotation Question'. This post draws attention to the Doctrine documentation regarding ManyToMany Uni-directional relationships. Look at the note regarding the approach of using an 'association entity class' thus replacing the many-to-many annotation mapping directly between two main entity classes with a one-to-many annotation in the main entity classes and two 'many-to-one' annotations in the Associative Entity class. There is an example provided in this forum post Association models with extra fields:
public class Person
{
/**
* #OneToMany(targetEntity="AssignedItems", mappedBy="person")
*/
private $assignedItems;
}
public class Items
{
/**
* #OneToMany(targetEntity="AssignedItems", mappedBy="item")
*/
private $assignedPeople;
}
public class AssignedItems
{
/**
* #ManyToOne(targetEntity="Person")
* #JoinColumn(name="person_id", referencedColumnName="id")
*/
private $person;
/**
* #ManyToOne(targetEntity="Item")
* #JoinColumn(name="item_id", referencedColumnName="id")
*/
private $item;
}

I got this error when editing my Product.orm.yml file.
I added a new manyToMany relation with a Category entity, and made a mistake on the joinTable line :
manyToMany:
categories:
targetEntity: Acme\ProductBundle\Entity\Category
inversedBy: products
joinTable:
name: Product # My mistake: joinTable should be something like ProductCategory
[...]
Indeed it's a silly error, I share anyway.

If you can, you can do this as this worked for me:
Drop the entire database:
app/console doctrine:schema:drop --force --full-database
Run all DB migrations:
app/console doctrine:migrations:migrate

I imagine It can happen quite often when copying entities. In my case it was a ORM table name annotation that was misfortunately duplicated.
/**
* #ORM\Entity()
* #ORM\Table(name="category")
* */
class Category {

I had this problem with an One-To-Many, Unidirectional with Join Table relation like (see doctrine doc). I did not find this error case with this relation type through the internet or stackoverflow, so i post here my solution for let help others with the same problem.
What caused this problem:
After reverse engineering the legacy db tables with ORM (see doc "How to Generate Entities from an Existing Database"), all tables also only join tables recieved an entity PHP class.
With annotations on a category entity i described the joining. Results this code:
/**
* #ORM\ManyToMany(targetEntity="Category")
* #ORM\JoinTable(name="category_child",
* joinColumns={#JoinColumn(name="category_id", referencedColumnName="id")},
* inverseJoinColumns={#JoinColumn(name="category_child_id", referencedColumnName="id")}
* )
*/
public $children;
The #ORM\JoinTable(name="category_child" caused that doctrine wants to create this table again. One time because of the already existing Category_Child entity, and then the #ORM\JoinTable expression that points to the same table.
Solution
Solution was to delete the Category_Child entity that was created from reverse engineering. If you used Category_Child entity in some $em queries, you have to select those datas othwerwise. E.g. Through the parent that holds those child datas in an ArrayCollection, or over DBAL.

Related

Table name turned to uppercase

I'm using JPA and Hibernate5.
My application.propperties have:
spring.jpa.hibernate.naming.implicit-strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
And my Entity:
#Entity
#Table(name = "document", schema = "test")
When I execute findAll, the following error is returned:
Table "DOCUMENT" not found; SQL statement: SELECT * FROM document
I'm unable to get entity names as described in name attribute. Always applies an 'uppercase'
EDIT:
The error has appeared when I'm trying to exclude HikariCP dependency. If I don't disable the dependency, properties works fine.
Define table name with backticks like shown below:
#Table(name="`document`")?
This should work in hibernate

Symfony doctrine migration rename table with relations

I`m trying to change a table name with doctrine migrations.
Example table name is model and I want to change it to new_model.
/**
* Class Model
*
* #package AppBundle\Entity
*
* #ORM\Table(name="new_model")
* #ORM\Entity(repositoryClass="AppBundle\Repository\ModelRepository")
* #ORM\HasLifecycleCallbacks()
*/
class Model
{
......
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\Product", inversedBy="products", fetch="EAGER", cascade={"persist"})
* #ORM\JoinColumn(name="product_id", referencedColumnName="id", nullable=false)
private $brand;
.......
To change to column name manually with migration script, I used:
$this->addSql('ALTER TABLE model RENAME new_model');
After running the migration the relations(join columns) are not changed and still reference to the old columnname. I also cleared the cache.
Does someone know how I can change a table name and the foreign key without loosing the relation data?
:(
The normal way of clearing cache was missing the mapping for doctrine.
After running:
php bin/console d:c:clear-metadata
It was working again.

Why CakePHP is not allowing to create MySQL table names without plural?

Putting "_ underscore" is old school. Why CakePHP is using it till now. And also why CakePHP is not allowing to create MySQL table names without plural. Is this mandatory ?
This is the default naming convention for cakephp. If you don't want to use default then use this method
For cakephp 3 details here
$this->setTable('my_table');
// Prior to 3.4.0
$this->table('my_table');
For cakephp 2 details here
class Example extends AppModel {
public $useTable = 'exmp'; // This model uses a database table 'exmp'
}

EclipseLink: "Updates are not allowed" on a native query INSERT INTO

since upgrading to EclipseLink 2.5 from EL 2.1 we get a PersistenceException on a previously running code.
The scenary is really simple: we have two identical tables, the only difference is that one is a "history" version of the other. Basically, when we are sure that a row won't change anymore, we move the row to the history table. This means that while the id is generated on the first table, it is "inherited" on the history table. Here are the entities:
#Entity
#Table(name = "DOCUMENT")
public class Document implements Serializable {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private long id;
// Some other fields
}
#Entity
#Table(name = "DOCUMENT_HISTORY")
public class DocumentHistory implements Serializable {
#Id
private long id;
// Some other fields
}
In order to move a row to the history table we use a native query (because some columns are not mapped as fields in the entity classes):
String query = "INSERT INTO DOCUMENT_HISTORY SELECT * FROM DOCUMENT t WHERE t.id=?1";
Query updateQuery = entityManager.createNativeQuery(query);
updateQuery.setParameter(1, document.getId());
updateQuery.executeUpdate();
When executing this query, sometimes this exception is thrown:
javax.persistence.PersistenceException: Exception [EclipseLink-7251] (Eclipse Persistence Services - 2.5.1.v20130918-f2b9fc5):
org.eclipse.persistence.exceptions.ValidationException
Exception Description: The attribute [id] of class [org.myc.entities.jpa.company.DocumentHistory] is mapped to a primary key column in the database. Updates are not allowed.
at org.eclipse.persistence.internal.jpa.EntityManagerImpl.flush(EntityManagerImpl.java:868)
at org.eclipse.persistence.internal.jpa.QueryImpl.performPreQueryFlush(QueryImpl.java:963)
at org.eclipse.persistence.internal.jpa.QueryImpl.executeUpdate(QueryImpl.java:296)
at org.myc.utility.jpa.user.DocumentManager.toDocumentHistory(DocumentManager.java:141)
at java.lang.Thread.run(Thread.java:662)
Caused by: Exception [EclipseLink-7251] (Eclipse Persistence Services - 2.5.1.v20130918-f2b9fc5): org.eclipse.persistence.exceptions.ValidationException
Exception Description: The attribute [id] of class [org.myc.entities.jpa.company.DocumentHistory] is mapped to a primary key column in the database. Updates are not allowed.
at org.eclipse.persistence.exceptions.ValidationException.primaryKeyUpdateDisallowed(ValidationException.java:2548)
at org.eclipse.persistence.mappings.foundation.AbstractDirectMapping.writeFromObjectIntoRowWithChangeRecord(AbstractDirectMapping.java:1257)
at org.eclipse.persistence.internal.descriptors.ObjectBuilder.buildRowForUpdateWithChangeSet(ObjectBuilder.java:1768)
at org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.updateObjectForWriteWithChangeSet(DatabaseQueryMechanism.java:1030)
at org.eclipse.persistence.queries.UpdateObjectQuery.executeCommitWithChangeSet(UpdateObjectQuery.java:84)
at org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.executeWriteWithChangeSet(DatabaseQueryMechanism.java:301)
at org.eclipse.persistence.queries.WriteObjectQuery.executeDatabaseQuery(WriteObjectQuery.java:58)
at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:899)
at org.eclipse.persistence.queries.DatabaseQuery.executeInUnitOfWork(DatabaseQuery.java:798)
at org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWorkObjectLevelModifyQuery(ObjectLevelModifyQuery.java:108)
at org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWork(ObjectLevelModifyQuery.java:85)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2896)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1793)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1775)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1726)
at org.eclipse.persistence.internal.sessions.CommitManager.commitChangedObjectsForClassWithChangeSet(CommitManager.java:267)
at org.eclipse.persistence.internal.sessions.CommitManager.commitAllObjectsForClassWithChangeSet(CommitManager.java:192)
at org.eclipse.persistence.internal.sessions.CommitManager.commitAllObjectsWithChangeSet(CommitManager.java:138)
at org.eclipse.persistence.internal.sessions.AbstractSession.writeAllObjectsWithChangeSet(AbstractSession.java:4196)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabase(UnitOfWorkImpl.java:1441)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithPreBuiltChangeSet(UnitOfWorkImpl.java:1587)
at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.writeChanges(RepeatableWriteUnitOfWork.java:452)
at org.eclipse.persistence.internal.jpa.EntityManagerImpl.flush(EntityManagerImpl.java:863)
... 5 more
Did anyone have the same problem? Why do you think this doesn't happen on all rows but only some of them (with no apparent specific characteristics)?
Thanks in advance,
Luc
P.S.: Is it correct for EL to perform mapping/query validation on a native query?
As stated in JPA 2.0 specification, executeUpdate() executes an update or delete statement thus insert is not supported.
You can insert an entity into the underlying database by persisting and flushing it with use of EntityManager (within a transaction). An dummy example in your particular case might look as follows:
// transaction starts
Document doc = em.find(Document.class, id);
DocumentHistory docHistory = new DocumentHistory(doc);
em.persist(docHistory);
// transaction ends
NOTE: instead of a proprietary solution (which is fine) you may consider of using EclipseLink's auditing feature:
EclipseLink also support full history support, which allows a complete history of all changes made to the database to be tracked in a mirror history table.
Ok, I found the problem and it wasn't related at all with that query, so I still don't know why the exception is thrown there.
The problem was that instead of using entityManager.find() to get the newly inserted history row, we were creating a DocumentHistory instance (with same ID) which was not attached to a persistence context, then using that instance to perform other operations.
Hope it helps someone.

Unknown column type when generating schema

I am developing an application using Symfony2 and Doctrine, the problem comes when
I try to create tables for Role and User Entities using php app/console doctrine:schema:update --force, the relation is ManyToMany and although the mapping information, the annotations, seem to be correct it throws the following exception:
[Doctrine\DBAL\DBALException] Unknown column type role requested
What can I do? Thank you very much.
You probably have a annotation like this:
/**
* #Column(type="role")
*/
protected $role;
This is a problem, because Doctrine doesn't know of any type named role.
I have to say that this is an assumption because you haven't posted any code...