JPA 2.0 Foreign Key Constraint - jpa

I have simple OneToOne relationship:
Data <-> TherapyResult
I would like to express the following constraints
with JPA.
If a Data entity gets removed the associated TherapyResult should be delete,too
If a TherapyResult entity gets removed the associated Data entity should remain in the db
The first constraint is really easy with JPA as I can add CascadingType.REMOVE
#OneToOne(cascade = { CascadeType.REMOVE, CascadeType.REFRESH })
private TherapyResult therapyResult;
For the second constraint I would like to add something like
#JoinColumn(columnDefinition = "DATA_ID BIGINT CONSTRAINT THERAPYRESULTDTAID FOREIGN KEY (DATA_ID) REFERENCES DATA (ID) ON DELETE SET NULL")
However this does not work. OpenJPA seems to have something similiar, but I want to use JPA 2.0 and EclipseLink. OpenJPA ForeignKey.
Another solution would be using #PreRemove described here, which works but looks a bit "none-best-practices" to me. However just a feeling.
My setup is:
Eclipse 3.7.1
EclipseLink 2.3
Apache Derby 10.8.3 and/or HSQLDB
any help is appreciated,
Muki

You can't use pure JPA to specify foreign keys ... that spec doesn't include the ability. JDO is the only standard with the ability to define FKs. You have to use implementation specifics, or just define the schema yourself and let the JPA impl run on it.

If you have a foreign key from Data to TherapyResult, and Data is the owner of the association, then
removing the Data will delete the TherapyResult automatically if cascade is set to REMOVE
you just need to set the therapyResult field to null and then delete the TherapyResult to have what you need. Another option is to set orphanRemoval to true, in which case setting the therapyResult field to null is sufficient to remove it from the database
If you have a foreign key from TherapyResult to Data, and TherapyResult is the owner of the association, then
removing the Data will delete the TherapyResult automatically if cascade is set to REMOVE on the Data.therapyResult field.
removing the TherapyResult will leave the Data in the DB provided the cascade is not set to REMOVE on the TherapyResult.data field

Related

Entity Framework 6 Casscade Deletes and DropForeignKey fails on auto generated constraint name

Entity Framework 6 Casscading Deletes and DropForeignKey fails on auto generated constraint name
I've been running into a bit of an issue with Entity Framework and cascade deletes between two tables on several one-to-many relationships.
Initially it looked like the correct path to take was to configure the table mappings with the OnModelCreating method of DbContext turning off cascade delete in a manner such as
modelBuilder.Entity<SourceTable>()
.HasOptional(x => x.NavigationProperty)
.WithOptionalDependent()
.WillCascadeOnDelete(false);
This however did not work throwing an exception stating
Cannot delete or update a parent row: a foreign key constraint fails...
More research lead me to believe that this is because all affected entities must be loaded into the context (eager fetched) so that entity framework may set the FK references to null as part of the transaction. This is not practical for my needs based on the size of the relational graph I'd be dealing with.
My next approach was to modify the Seed method of the Configuration class and run some arbitrary SQL to drop the Foreign Key constraint and re-add it as a ON DELETE SET NULL constaint. This worked in most cases, however one of the consraints has what appears to be an auto generated unpredicatable name that is diffrent on each call of Update-Database. Given that the name can't be predicted the ALTER statments aren't particualr helpful
context.Database.ExecuteSqlCommand(#"ALTER TABLE SourceTable DROP FOREIGN KEY FK_9405957d032142c3a1227821a9ed1fdf;
ALTER TABLE SourceTable
ADD CONSTRAINT FK_ReasonableName
FOREIGN KEY (NavigationProperty_Id) REFERENCES NavigationProperty (Id) ON DELETE SET NULL;");
Finally, I've taken the apprach to use the migration functionality (DbMigration) and override Up method and leveraging the DropForeignKey method along side more explicit SQL to re-add the constraint (EF does not appear to provide a factility to create a ON DELETE SET NULL constraint).
DropForeignKey("SourceTable", "NavigationProperty_Id", "DestinationTable");
Sql("ALTER TABLE SourceTable ADD CONSTRAINT FK_ReasonableName FOREIGN KEY (NavigationProperty_Id) REFERENCES DestinationTable (Id) ON DELETE SET NULL;");
This works great, up until I encounter the constraint with the auto generate name. At this point the DropForeignKey method fails with an exception that is swallowed up by
System.Runtime.Serialization.SerializationException: Type is not resolved for member 'MySql.Data.MySqlClient.MySqlException,MySql.Data...
When dumping the migration to a SQL script file it becomes clear that the DropForeignKey simply generates a FK with a more predictable, non-ambiguous byte stream array.
Is there a proper EF Code First approach to solve the problem of setting FK column values to null when deleting the refrenced row, or am I stuck having to hand code SQL in order to gain this functionality?

implement foreign Key in JPA side( in database this relation is nt implemented)

how to implement Foreign key relation in JPA side ( There is no foreign key for this relation in db, Db owned by another application , i cant able to change db structure( SW vendor not allowing me to do it)
Is there just no foreign key constraint, or nothing referencing the id at all?
If there is just no constraint, then it does not matter, JPA does not care if there is a constraint or not, just use the column that references the id.
If there is nothing referencing the id, then you cannot have a relationship with nothing store it. If you cannot alter the table, then perhaps you can add a new table that defines the join between the two tables (similar to a many to many, but JPA also allows a join table to be used for a one to one).

JPA: Give a name to a Foreign Key on DB?

I have a simple questions. How can I give a name to the Foreign Key relations that arise from the # ManyToOne annotation ?
With JPA 2.1 you can just do this with the foreignKey annotation:
import javax.persistence.ForeignKey;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
#ManyToOne
#JoinColumn(name = "company_id", nullable = false, foreignKey = #ForeignKey(name="FK_COMPANY__ROUTE"))
private Company company;
Do not confuse with the deprecated hibernate equivalent
As of JPA 2.1 it is possible to define foreign keys via #ForeignKey annotation.
Unfortunately, it is not very useful if you only need to change the name. If you specify custom name of the FK, you also have to specify SQL definition of the FK. That is at least the way it works in EclipseLink 2.5.0.
If you are interested in naming the column used in the foreign key, one may specify the name of the column used to create the foreign key, using the #JoinColumn annotation along with the #ManyToOne annotation. The value of the name attribute of the #JoinColumn annotation is used by the JPA provider to map the column name in the table to the entity's attribute.
However, the name of the foreign key constraint created itself cannot be configured. At the time of writing this, it is not possible to specify the name of the foreign key constraint using a JPA annotation or configuration parameter in the OR mapping files. If you need to change the name of the foreign key constraint, then you must create the DDL statement yourself, instead of relying on the JPA provider to do this.
I think #ForeignKey doesn't work with #JoinTables or I don't know how to set custom names by this, I have tried it on #JoinTable->foreignKey and #JoinColumn->foreignKey

Violation of PRIMARY KEY constraint on linked record when add a record using the entity framework

I have a table called farmers. Each farmer has a country specified that is mandatory.
When I add a new farmer to the database using antity framework, I get a violation on the country table. It looks like the entity framework wants to add the country to the country table, but I only want the guid in my farmer table:
Violation of PRIMARY KEY constraint 'PK_Country'. Cannot insert
duplicate key in object 'dbo.Country'. The statement has been
terminated.
Can somebody advise me on what I'm doing wrong? here the code for the insert:
newFarmer.Guid = Guid.NewGuid();
ents.Farmer.AddObject(newFarmer);
ents.SaveChanges();
return newFarmer;
I even checked the state of the country and it says unchanged.
One possible solution is that Entity Framework doesn't understand that your entity primary key is also the identity and should be auto-incremented. I had the same problem in an application using EF 4.1 with database first. To solve the problem, I had to::
Make sure my entities primary key had a name "ID" (to avoid putting a decorator [Key] above my Model class.
Make sure the property option "Identity" of your database system (SQL Server in my case) is set to "Yes".
Then, my EF4.1 was able to do the insert and update of my entities.
Hope this helps!

Entity Framework Association with Non Key fields

Is it possible to create associates b/t 2 non-key fields in the Entity Framework?
Example: Take the 2 tables in a legacy application (i.e. keys/structure cannot change)
Order (
OrderId : int : PK
OrderNo : varchar
)
OrderDetails (
DetailRecordId : int : PK
OrderNo : varchar
)
In the Entity Framework, I want to create an association b/t Order and OrderDetails by the OrderNo field, which is not a primary key on either table or a FK relationship in the database.
This seems to me as not only should it be easy to do, but one reasons to use something like EF. However, it seems to only want to allow me to create associations using entity keys.
The Entity Framework allows you to claim that columns are keys and that FK constraints exist where none actually exist in the database.
That is because the SSDL (StorageModel part of the EDMX) can if necessary be manipulated by you and lie about the database.
The EF will then interact with the database as if the keys and foreign keys really do exist.
This should work, but all the normal caveats about referential integrity apply.
See my Entity Framework Tips
Hope this helps.
The problem with using non-key fields to define relationships is that the keys are not guaranteed to be properly navigatable. That could lead to a situation where you have a one to one relationship between two entities where there are more than one possible rows that fufill the relationship.
...when relating data from a database, the relationships should always be based on keys. The keys enforce the referential integrity.
One more workaround:
create view vOrder which will not include PK and create Entity from it.
Set PK in this entity to OrderNo
Now you will be able create association