I have been struggling with defining cascade behavior in Doctrine ORM.
According to the documentation, one is supposed to use onDelete: CASCADE for database-level cascade (which is what I am trying to achieve here).
A complete example may be seen on the Symfony tutorial.
However, all such cascade specifications are ignored in my schema.
Here is the relevant excerpt:
Advancement:
columns:
association_id:
type: integer(4)
notnull: true
task_id:
type: integer(4)
notnull: true
state:
type: enum
values: ['todo', 'current', 'done', 'cancelled']
notnull: true
relations:
Association:
class: Association
local: association_id
foreignType: one
onDelete: CASCADE
Task:
class: Task
local: task_id
foreignType: one
onDelete: CASCADE
Of course, the Task and Association tables are defined correctly. I won't post them here in the first place to avoid a too long question, but please ask if that seems necessary.
Here is the generated SQL (linebreaks mine):
CREATE TABLE advancement
(id INTEGER PRIMARY KEY AUTOINCREMENT,
association_id INTEGER NOT NULL,
task_id INTEGER NOT NULL,
state VARCHAR(255) NOT NULL);
Not a trace of a CASCADE (nor a REFERENCES, by the way…). Of course, cascading does not work, and I had to implement it manually by altering the default backend actions.
Does anyone know what I am doing wrong here?
I think doctrine will shut up about the fact that your RDBMS (is it MySQL?) does not support cascades if it doesn't. This is the case if you use MySQL with the MyISAM storage engine (which does not support REFERENCES either, by the way...). If I were you, I'd try to create a cascade directly with your RDBMS client, just to check whether it is possible or not.
Related
I'm running into an issue when running my SpringBootTests.
The tests are using an H2 database, so they recreate the schema every time they run. For one of my entities, Hibernate doesn't add auto_increment to the id column.
I can't find any relevant differences between the failing entity (Payment) and others that work correctly (e.g. Invoice). They all have the following annotations on the id field:
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
I set spring.jpa.show-sql=true, and this is what I see:
The Payment entity shows create table payment (id bigint not null,
The Invoice entity shows create table invoice (id bigint not null
auto_increment,
In fact, I tried copying the Payment class to Payment2, and Payment2 did not have the issue:
The Payment entity shows create table payment (id bigint not null,
The Payment2 entity shows create table invoice (id bigint not null
auto_increment,
Given this, I believe I should be looking for an overriding configuration that's not in the Payment class, but that somehow removes auto_increment from just that one class.
Does anyone know what could be causing this?
These are the versions of the libraries involved:
Spring Boot version 2.1.8
Hibernate 5.3.11
H2 Database 1.4.200
I finally figured it out. This assumption was correct:
I should be looking for an overriding configuration that's not in the Payment class, but that somehow removes auto_increment from just that one class.
Turned out that a colleague had added a "light" read-only version of the Payment entity called PaymentLight. It read from the same payment table but without any of the joins. The id field in the PaymentLight class did not have the #GeneratedValue annotation.
I haven't checked this, but I assume Hibernate merged the two entities (the light class was a subset anyway) and used the #GeneratedValue configuration from one of them (likely alphabetical order).
I'm working on migrating all the tables in my schema to be partitioned tables. Since I'm on 11g instead of 12.2 I have to use DBMS_REDEFINITION. I've automated this with some Ruby code that executes the redefinition procedures for each table in my schema.
My issue is that after migrating, all of my non-nullable columns show NULLABLE - YES. This isn't actually true however, as I can check the constraints and there are check constraints defined for each of the columns that used to be NOT NULL, still enforcing the NOT NULL status. It seems like DBMS_REDEFINITION successfully copied the constraints, but it didn't reflect the NULLABLE status.
Is there a way to tell Oracle to get this back in sync?
I found the answer elsewhere:
https://dba.stackexchange.com/questions/55081/why-is-sqlplus-desc-table-not-showing-not-null-constraints-after-using-dbms-re
Oracle copies the constraints but never turns validate back on. You have to manually do that with:
ALTER TABLE <table_name> ENABLE VALIDATE CONSTRAINT <constraint_name>;
Can I use an hibernate entity with #Id on a unique constraint instead of a primary key on oracle databases? Also will it be JPA compliant?
Sounds a bit strange, but seems possible:
http://www.objectdb.com/api/java/jpa/Id:
The field or property to which the Id annotation is applied should be one of the following types: any Java primitive type; any primitive wrapper type; String; java.util.Date; java.sql.Date; java.math.BigDecimal; java.math.BigInteger.
But be aware:
(1) E.g. in Oracle UNIQUE does not imply NOT NULL, you have to ensure this by your own.
(2) You can't use a FOREIGN KEY constraint in your DB.
(3) You have to be careful with Id generation (http://www.objectdb.com/api/java/jpa/GeneratedValue) if you want to insert new entities (not only read existing ones).
(4) If you insert a new entity, you have to generate a value for the DB id.
And that are only a few disadvantages that came quickly to my mind ...
I'm using hibernate-entitymanager in a Spring application. I'm in the process of upgrading my Hibernate version. Narrowed it down to the exact version: when I upgrade from 4.2.1.Final to 4.2.2.Final (or anything higher than that), I'm getting the following error when my unit tests starts up and try to create the database schema:
2014-03-02 18:02:51,559 ERROR [SchemaExport] [main] HHH000389: Unsuccessful: alter table Incident add constraint FK_d91dua6gkdp1jn826adqss3aq foreign key (uuid) references Incident
2014-03-02 18:02:51,559 ERROR [SchemaExport] [main] Constraint "FK_D91DUA6GKDP1JN826ADQSS3AQ" already exists; SQL statement:
alter table Incident
add constraint FK_d91dua6gkdp1jn826adqss3aq
foreign key (uuid)
references Incident [90045-170]
The error does not prevent the system from working just fine, but clearly I can't go to production with such a nasty error in my system and no explanation of it.
This looks a lot like the Incident table has a foreign key relationship to itself, which is absolutely not the case.
I'll try to copy the essence here of the Incident entity:
#Entity
#Audited
#EntityListeners(value = {IncidentIdentifierPrePersistListener.class })
#FilterDefs( ... )
#Filters( ... )
public class Incident extends SomeBaseClass {
#Id
private String uuid = UUID.randomUUID().toString();
#Column(nullable = false, unique = true)
private long identifier;
... a bunch more fields ...
}
Please let me know if I can provide anything else to help ya'all to shed a light on this. I've played around with it for hours, fruitless, and your help would be much appreciated.
Here is what happened:
Incident defined a #ManyToOne to an entity Project
Project incorrectly defined a #ManyToMany back to the entity Incident (should have been a #OneToMany)
As a result Hibernate generated the awkward following constraint:
CONSTRAINT fk909a8f241708a1e FOREIGN KEY (uuid)
REFERENCES incident (uuid) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
Incident inherits SomeBaseClass which has #Inheritance(strategy = InheritanceType.JOINED)
As a result Hibernate generated the following constraint:
CONSTRAINT fk909a8f2ddd08e84 FOREIGN KEY (uuid)
REFERENCES somebaseclass (uuid) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
As a result of HHH-8217 (Make generated constraint names short and non-random) in Hibernate 4.2.2 the above two constraint definitions suddenly got the same name (Hibernate did only consider the entity and the columns of the foreign key constraint, not the target entity of the foreign key; note how generateName only takes one Table as a parameter)
And there was the corresponding clash: Constraint ... already exists
Changing the #ManyToMany to #OneToMany fixes this entirely.
By the way, the offending field definition (the one with the #ManyToMany) also previously caused me problems with Hibernate Envers' #Audited, the reason of which I never understood, and that got resolved now as well. It's a good day. (Not sure if #Audited means much for a mapped field, but at least I can have #Audited on the class without needing to deal with this field.)
I am new to symfony and doctrine and would appreciate some help ...
I am connecting doctrine to an oracle 11g database.
I have created an table/entity which contains nullable date fields.
The fields are described in YAML thus
metar_time:
type: date
nullable: true
column: METAR_TIME
taf_time:
type: date
nullable: true
column: TAF_TIME
ltaf_time:
type: date
nullable: true
column: LTAF_TIME
storage_date:
type: date
nullable: true
column: STORAGE_DATE
The database schema reflects the status of the fields as nullable dates with a default value of null.
The issue that I am having is that I can not get doctrine to recognise that the database and meta description are in sync.
php app/console doctrine:schema:update --dump-sql
ALTER TABLE MET MODIFY (LTAF_TIME DATE DEFAULT NULL, METAR_TIME DATE DEFAULT NULL, STORAGE_DATE DATE DEFAULT NULL, TAF_TIME DATE DEFAULT NULL);
php app/console doctrine:schema:update --force
Updating database schema...
Database schema updated successfully! "1" queries were executed
Yet if I run the sql dump again the update is still outstanding.
I have cleared all the caches to rule that out as an issue.
Any suggestions welcome !
This is known issue. Check Incorrect type mapping on Oracle Platform
Some ref:
The problem is that Oracle has a "DATE" type, which is actually a DATETIME. That is why we map it to Doctrine's Datetime type.
As a workaround, you can set this information yourself using:
$conn->getDatabasePlatform()->registerDoctrineTypeMapping('date', 'date');
Be aware this is a global change for all columns. If you map DateTimes to a TIMESTAMP field you are good to go though.