# cascade funzt nicht



## Angel4585 (20. Jan 2008)

Hallo,

ich hab einige Tabellen mit 1:n beziehungen.
Dabei jeweils 
    @OneToMany(cascade={CascadeType.ALL},mappedBy = "world")
stehen, bzw mappedBy eben das feld.

Aber wenn ich jetzt miene "World" lösche, tut sich bei den Countries die eben damit verknüpft sind garnichts.
Sollten die dann nciht automatisch auch gelöscht werden?

Ich bin noch ziemlicher Anfänger was jpa angeht. Kann mir vllt jemand kurz sagen wo ich was genau hinschrieben muss um Tabellen richtig zu kaskadieren?
MOmentan habe ich überall wo OneToMany, ManyToOne usw steht ein cascade={CascadeType.ALL} mit drin.


----------



## byte (20. Jan 2008)

Sicher dass das Mapping stimmt? Da Du mappedBy benutzt, handelt es sich offenbar um eine bidirektionale Assoziation und das Mapping muss entsprechend auf der "anderen Seite" definiert sein (dort gehört auch das Cascade.ALL hin).

Beispiel:


```
@Entity
public class Customer implements Serializable {
    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name="passport_fk")
    public Passport getPassport() {
        ...
    }

@Entity
public class Passport implements Serializable {
    @OneToOne(mappedBy = "passport")
    public Customer getOwner() {
    ...
}
```


----------



## Angel4585 (20. Jan 2008)

```
@OneToMany(cascade={CascadeType.ALL},mappedBy = "world")
    public Collection<Country> getCountries() {
        return countries;
    }

    @ManyToOne(cascade={CascadeType.ALL})
    public World getWorld() {
        return world;
    }
```

steht bei mir momentan.

Wann muss ich genau dieses mappedBy rein machen? Ist es egal auf welcher Seite das steht?
Das cascade mach ich jetz mal überall wo ein mappedBy steht raus.


----------



## Angel4585 (20. Jan 2008)

Was ich im endeffekt haben will:

Ich habe verschiedene Welten mit jeweils mehreren Ländern, die wiederum mehrere Städte haben.

Jetzt möchte ich einfach eine Welt löschen und es sollen sich automatisch alle dazugehörigen Länder und Städte mitlöschen.


----------



## Angel4585 (20. Jan 2008)

mir fällt grad auf dass zB das on delete cascade bei mysql garnicht eingetragen wird?? Macht das die Software dann von sich aus?


----------



## Angel4585 (20. Jan 2008)

```
@OneToMany(mappedBy = "world")
    public Collection<Country> getCountries() {
        return countries;
    }

    @ManyToOne(cascade={CascadeType.ALL})
    public World getWorld() {
        return world;
    }
```

So sollte das doch gehen oder?
Tut leider nicht. Bekomm folgende Meldung:

javax.persistence.RollbackException: Exception [TOPLINK-4002] (Oracle TopLink Essentials - 2.0 (Build b58g-fcs (09/07/2007))): oracle.toplink.essentials.exceptions.DatabaseException
Internal Exception: com.mysql.jdbc.exceptions.MySQLIntegrityConstraintViolationException: Cannot delete or update a parent row: a foreign key constraint fails (`srpg/country`, CONSTRAINT `FK_COUNTRY_WORLD_ID` FOREIGN KEY (`WORLD_ID`) REFERENCES `world` (`ID`))
Error Code: 1451
Call: DELETE FROM WORLD WHERE (ID = ?)
        bind => [1]
Query: DeleteObjectQuery(jpatest.World[id=1])
        at oracle.toplink.essentials.internal.ejb.cmp3.transaction.base.EntityTransactionImpl.commit(EntityTransactionImpl.java:120)
        at oracle.toplink.essentials.internal.ejb.cmp3.transaction.EntityTransactionImpl.commit(EntityTransactionImpl.java:60)
        at main.EntManager.clearDB(EntManager.java:49)
        at main.EntManager.<init>(EntManager.java:35)
        at main.Main.main(Main.java:22)
Caused by: Exception [TOPLINK-4002] (Oracle TopLink Essentials - 2.0 (Build b58g-fcs (09/07/2007))): oracle.toplink.essentials.exceptions.DatabaseException
Internal Exception: com.mysql.jdbc.exceptions.MySQLIntegrityConstraintViolationException: Cannot delete or update a parent row: a foreign key constraint fails (`srpg/country`, CONSTRAINT `FK_COUNTRY_WORLD_ID` FOREIGN KEY (`WORLD_ID`) REFERENCES `world` (`ID`))
Error Code: 1451
Call: DELETE FROM WORLD WHERE (ID = ?)
        bind => [1]
Query: DeleteObjectQuery(jpatest.World[id=1])
        at oracle.toplink.essentials.exceptions.DatabaseException.sqlException(DatabaseException.java:311)
        at oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:654)
        at oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor.executeNoSelect(DatabaseAccessor.java:703)
        at oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:492)
        at oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:452)
        at oracle.toplink.essentials.internal.sessions.AbstractSession.executeCall(AbstractSession.java:690)
        at oracle.toplink.essentials.internal.queryframework.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:228)
        at oracle.toplink.essentials.internal.queryframework.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:214)
        at oracle.toplink.essentials.internal.queryframework.DatasourceCallQueryMechanism.deleteObject(DatasourceCallQueryMechanism.java:205)
        at oracle.toplink.essentials.internal.queryframework.StatementQueryMechanism.deleteObject(StatementQueryMechanism.java:130)
        at oracle.toplink.essentials.internal.queryframework.DatabaseQueryMechanism.deleteObjectForWrite(DatabaseQueryMechanism.java:258)
        at oracle.toplink.essentials.queryframework.DeleteObjectQuery.executeCommit(DeleteObjectQuery.java:98)
        at oracle.toplink.essentials.internal.queryframework.DatabaseQueryMechanism.executeWrite(DatabaseQueryMechanism.java:335)
        at oracle.toplink.essentials.queryframework.WriteObjectQuery.executeDatabaseQuery(WriteObjectQuery.java:111)
        at oracle.toplink.essentials.queryframework.DatabaseQuery.execute(DatabaseQuery.java:628)
        at oracle.toplink.essentials.queryframework.DatabaseQuery.executeInUnitOfWork(DatabaseQuery.java:555)
        at oracle.toplink.essentials.queryframework.ObjectLevelModifyQuery.executeInUnitOfWorkObjectLevelModifyQuery(ObjectLevelModifyQuery.java:138)
        at oracle.toplink.essentials.queryframework.DeleteObjectQuery.executeInUnitOfWorkObjectLevelModifyQuery(DeleteObjectQuery.java:125)
        at oracle.toplink.essentials.queryframework.ObjectLevelModifyQuery.executeInUnitOfWork(ObjectLevelModifyQuery.java:110)
        at oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2233)
        at oracle.toplink.essentials.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:952)
        at oracle.toplink.essentials.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:909)
        at oracle.toplink.essentials.internal.sessions.CommitManager.deleteAllObjects(CommitManager.java:338)
        at oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.commitToDatabase(UnitOfWorkImpl.java:1047)
        at oracle.toplink.essentials.internal.ejb.cmp3.base.RepeatableWriteUnitOfWork.commitToDatabase(RepeatableWriteUnitOfWork.java:403)
        at oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithChangeSet(UnitOfWorkImpl.java:1126)
        at oracle.toplink.essentials.internal.ejb.cmp3.base.RepeatableWriteUnitOfWork.commitRootUnitOfWork(RepeatableWriteUnitOfWork.java:107)
        at oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.commitAndResume(UnitOfWorkImpl.java:856)
        at oracle.toplink.essentials.internal.ejb.cmp3.transaction.base.EntityTransactionImpl.commit(EntityTransactionImpl.java:102)
        ... 4 more
Caused by: com.mysql.jdbc.exceptions.MySQLIntegrityConstraintViolationException: Cannot delete or update a parent row: a foreign key constraint fails (`srpg/country`, CONSTRAINT `FK_COUNTRY_WORLD_ID` FOREIGN KEY (`WORLD_ID`) REFERENCES `world` (`ID`))
        at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:931)
        at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:2985)
        at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1631)
        at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:1723)
        at com.mysql.jdbc.Connection.execSQL(Connection.java:3256)
        at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1313)
        at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1585)
        at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1500)
        at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1485)
        at oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:647)
        ... 31 more


----------



## byte (20. Jan 2008)

also du musst ihm schon sagen, wie das mapping genau aussieht, also z.b. eine join column angeben. wie genau du das machen musst kann man dir nicht sagen, solange man nix über deine tabellenstrukturen weiss.


----------



## maki (20. Jan 2008)

Der Loggingausgabe nach, versuchst du eine Entity(Datensatz) zu löschen, der von einer anderen Entity(Tabelle) referenziert wird und diese Referenz darf nicht null sein.

Genauer gesagt muss country eine Referenz auf World haben (not nul), wenn du eine World löschen möchtest die von einer Country referenziert wird, bekommst du einen Fehler.


----------



## Angel4585 (21. Jan 2008)

ok byto. es geht mehr um das prinzipielle, nicht wie es in meinem speziellen Fall ist.

Also ich hab zwei Tabellen:

Tabelle1

id integer
name varchar

Tabelle2

id integer
tab1id integer
name varchar

In Tabelle 2 habe ich x Einträge die bei tab1id zB die "1" drin haben. Wenn ich jetzt in Tabelle1 den Eintrag mit der id "1" lösche, sollen in Tabelle2 auch alle Einträge mit der tab1id "1" gelöscht werden.

Was machen diese JoinColumns eigentlich genau?
Im phpMyAdmin seh ich keinen Unterschied. 
Bisher hab ich die weggelassen, kann aber mit denen auch keinen Unterschied feststellen.


----------

