Thanks, Simone.

You may be right about me misunderstanding ManyToMany, but I always thought
that without a cascade remove, the row in the cross table wouldn't be
deleted regardless of ManyToMany, ManyToOne, etc.  This is how it works
under Toplink. E.g,

em.getTransaction().begin(); 
em.remove(a);   //remove an Address that has a Person 
em.getTransaction().commit();  //Toplink won't allow this

I had a look at the tables OpenJPA created. After the Address is removed,
the row in the corss table is indeed deleted, thereby leaving a dirty Person
instance in RAM. However, if I attempt to manually delete an Address (having
Persons) from the DB with  "delete from TAMB.ADDRESS where ID = 51"  the
result is...

"DELETE on table 'ADDRESS' caused a violation of foreign key constraint
'SQL081014154643790' for key (51).  The statement has been rolled back."

So, it would seem that the DB is enforcing the foreign key constraint, but
OpenJPA isn't.

I can't seem to figure out how to get OpenJPA to export the schema, so I
dumped it myself.  I've tested this with Derby and HSQL and the same thing
occurs with both.

CREATE TABLE TAMB.OPENJPA_SEQUENCE_TABLE (
                ID SMALLINT NOT NULL,
                SEQUENCE_VALUE BIGINT
        );

CREATE TABLE TAMB.ADDRESS (
                ID BIGINT NOT NULL
        );

CREATE TABLE TAMB.PERSON (
                ID BIGINT NOT NULL
        );

CREATE TABLE TAMB.PERSON_ADDRESS (
                PERSON_ID BIGINT,
                ADDRESS_ID BIGINT
        );

CREATE UNIQUE INDEX TAMB.SQL081014154105010 ON TAMB.ADDRESS (ID ASC);

CREATE INDEX TAMB.SQL081014154105350 ON TAMB.PERSON_ADDRESS (PERSON_ID ASC);

CREATE INDEX TAMB.SQL081014154105430 ON TAMB.PERSON_ADDRESS (ADDRESS_ID
ASC);

CREATE UNIQUE INDEX TAMB.SQL081014154105220 ON TAMB.PERSON (ID ASC);

CREATE UNIQUE INDEX TAMB.SQL081014154105100 ON TAMB.OPENJPA_SEQUENCE_TABLE
(ID ASC);

ALTER TABLE TAMB.ADDRESS ADD CONSTRAINT SQL081014154105010 PRIMARY KEY (ID);

ALTER TABLE TAMB.PERSON ADD CONSTRAINT SQL081014154105220 PRIMARY KEY (ID);

ALTER TABLE TAMB.OPENJPA_SEQUENCE_TABLE ADD CONSTRAINT SQL081014154105100
PRIMARY KEY (ID);

ALTER TABLE TAMB.PERSON_ADDRESS ADD CONSTRAINT SQL081014154105350 FOREIGN
KEY (PERSON_ID)
        REFERENCES TAMB.PERSON (ID);

ALTER TABLE TAMB.PERSON_ADDRESS ADD CONSTRAINT SQL081014154105430 FOREIGN
KEY (ADDRESS_ID)
        REFERENCES TAMB.ADDRESS (ID);






Simone Gianni wrote:
> 
> Hi eggbert,
> maybe I'm missing something as well, but being a many to many, doesn't
> also the row on the cross table gets deleted? In that case, you are
> effectively removing the person from the address and the address from
> the person, except for the copy you have in RAM which remains dirty.
> 
> The violation would occur if you have a many to one (One person having
> many addresses, one address belonging to one Person), with reverse
> mapping and without a cascade, and you delete the Person, leaving the
> Address with a non existing PERSON_ID that would cause the error.
> 
> Could you also post the resulting schema and inspect the content of the
> cross table before and after the deletion?
> 
> Simone
> 
> 
> 
> eggbert wrote:
>> Hello,
>>
>> I am letting OpenJPA build the schema from the entities, and I have
>> enabled
>> "ForeignKeyDeleteAction=restrict, JoinForeignKeyDeleteAction=restrict"
>> for
>> the MappingDefaults in my persistence.xml file. However, the
>> JoinForeignKeyDeleteAction appears to have no effect.
>>
>> For example, if I have the following two entities...
>>
>> @Entity
>> public class Person {    
>>     @Id
>>     @GeneratedValue(strategy = GenerationType.AUTO)
>>     private Long id;
>>     
>>     @ManyToMany
>>     @JoinTable(name = "person_address",
>>     joinColumns = [EMAIL PROTECTED](name = "person_id",
>> referencedColumnName="ID")},
>>     inverseJoinColumns = [EMAIL PROTECTED](name = "address_id",
>> referencedColumnName="ID")})
>>     private Set<Address> addresses = new HashSet<Address>();
>>     
>>     public Person() {        
>>     }
>>     
>>     Collection<Address> getAddresses() {
>>         return addresses;
>>     }    
>> }
>>
>> and...
>>
>> @Entity
>> public class Address {    
>>     @Id
>>     @GeneratedValue(strategy = GenerationType.AUTO)
>>     private Long id;
>>     
>>     @ManyToMany(mappedBy="addresses")
>>     private Set<Person> people = new HashSet<Person>();
>>     
>>     public Address() {        
>>     }
>>     
>>     Collection<Person> getPeople() {
>>         return people;
>>     }    
>> }
>>
>> Then the following code will NOT throw an exception complaining about a
>> foreign key violation.
>>
>> Person p = new Person();
>> Address a = new Address();
>>         
>> em.getTransaction().begin();
>> em.persist(p);
>> em.persist(a);
>> p.getAddresses().add(a);
>> a.getPeople().add(p);
>> em.getTransaction().commit();
>>         
>> em.getTransaction().begin();
>> em.remove(a);   //remove an Address that has a Person
>> em.getTransaction().commit();  //why does this commit?
>>
>>
>> Shouldn't the JoinForignKeyDeleteAction=restrict prevent this, (i.e,
>> preventing an entity from being deleted that has an ID in a join table),
>> or
>> am I totally missing something here.  
>>
>> Thanks!
>>
>>
>>
>>
>>
>>   
> 
> 
> -- 
> Simone Gianni            CEO Semeru s.r.l.           Apache Committer
> MALE human being programming a computer   http://www.simonegianni.it/
> 
> 
> 

-- 
View this message in context: 
http://n2.nabble.com/JoinForeignKeyDeleteAction%3Drestrict-not-working-as-expected-tp1332128p1334103.html
Sent from the OpenJPA Users mailing list archive at Nabble.com.

Reply via email to