2010-06-16 11 views
19

Ich möchte verwaiste Objekte mit Hibernate und JPA in einer Viele-zu-viele-Beziehung löschen, aber alles, was ich gefunden habe, war dieses Attribut das Attribut. org.hibernate.annotations.CascadeType.DELETE_ORPHAN (d. h. @Cascade (value = {org.hibernate.annotations.CascadeType.DELETE_ORPHAN)), das nur für Eins-zu-Viele-Beziehungen funktioniert.Wie lösche ich verwaiste Entitäten mit Hibernate und JPA in einer Viele-zu-Viele-Beziehung?

Ich möchte wissen, ob ich die Waisen in meiner Viele-zu-Viele-Beziehung löschen kann.

Antwort

-9

Verwenden Sie nicht den Ruhezustand, schreiben Sie SQL-Code und führen Sie ihn satzbasiert direkt in der Datenbank aus. Und dann behebe das strukturelle Datenbankproblem, das dir erlaubt hat verwaiste Datensätze an erster Stelle zu bekommen. Es ist ein Zeichen für eine sehr schlecht gestaltete Datenbank, wenn Sie verwaiste Datensätze haben. Dies sollte ein einmaliger Fix sein, nicht etwas, das vom Anwendungscode ausgeführt wird. Schäm dich, dass du keine richtigen PK/FK-Beziehungen aufgebaut hast.

+0

Sie haben den Punkt völlig verpasst (wie Sie es bereits getan haben, als Sie meine Antwort über das optimistische Sperren abgelehnt haben). –

+0

@Pascal Thivent - Sie haben den Punkt verpasst. Dies sollte nicht von der Anwendungsoberfläche aus erfolgen. Dies ist ein Datenbankproblem und sollte von einer korrekt entworfenen Datenbank behandelt werden. Und wenn ich eine Ihrer Antworten abwähle (was ich ehrlich gesagt nicht weiß, wenn ich es tue, schlägt es keine Glocke), dann erwähnt, dass in Ihrem Kommentar, wenn es irrelevant war, mir scheint, dass Sie auf einer Vendetta mehr sind als zu versuchen, das Richtige zu tun. – HLGEM

+0

Mein Kommentar bezieht sich auf das imaginäre "strukturelle Problem", auf das du dich beziehst (du hast den Punkt verpasst, ich bestehe darauf, dass das OP richtige PK/FK hat, du denkst nur nicht auf Objektebene).Dann, ob Sie es glauben oder nicht, ich habe Ihre obige Antwort nicht abgelehnt (zögern Sie nicht, sich mit einem Diamanten-Moderator in Verbindung zu setzen), auch wenn ich denke, dass diese Antwort irrelevant ist (wie der Downvote auf [meine Antwort] (http://stackoverflow.com/) Fragen/2949039/curcency-problem-with-isolation-read-committed/2949534 # 2949534)). Also nein, ich bin nicht auf einer Vendetta (aber Feedback wäre geschätzt worden). –

5

Eigentlich habe ich einen Test mit den folgenden Einheiten:

@Entity 
public class Person { 
    @Id 
    @GeneratedValue 
    private Long id; 
    private String firstName; 
    private String lastName; 

    @ManyToMany 
    @Cascade(value = org.hibernate.annotations.CascadeType.DELETE_ORPHAN) 
    private Set<Role> roles = new HashSet<Role>(); 

    //... 
} 

@Entity 
public class Role { 
    @Id 
    @GeneratedValue 
    private Long id; 

    private String name; 

    @ManyToMany(mappedBy = "roles") 
    private Set<Person> persons = new HashSet<Person>(); 

    //... 
} 

Und mit der folgenden Datenmenge:

<dataset> 
    <PERSON id="1" firstname="john" lastname="doe"/> 
    <PERSON id="2" firstname="clark" lastname="kent"/> 
    <PERSON id="3" firstname="james" lastname="bond"/> 
    <ROLE id="1" name="foo"/> 
    <ROLE id="2" name="bar"/> 
    <ROLE id="3" name="boo"/> 
    <ROLE id="4" name="baz"/> 
    <PERSON_ROLE persons_id="1" roles_id="1"/> 
    <PERSON_ROLE persons_id="1" roles_id="2"/> 
    <PERSON_ROLE persons_id="2" roles_id="2"/> 
    <PERSON_ROLE persons_id="2" roles_id="3"/> 
    <PERSON_ROLE persons_id="3" roles_id="1"/> 
    <PERSON_ROLE persons_id="3" roles_id="4"/> 
</dataset> 

Das folgende Testverfahren:

@Test 
public void testCascadeDeleteOrphanOnDelete() { 
    Person person = entityManager.find(Person.class, 1L); 
    entityManager.remove(person); 
    ReflectionAssert.assertPropertyLenientEquals("id", Arrays.asList(2, 3), findAllPersons()); 
    ReflectionAssert.assertPropertyLenientEquals("id", Arrays.asList(3, 4), findAllRoles()); 

} 

private List<Person> findAllPersons() { 
    return entityManager.createQuery("from Person").getResultList(); 
} 

private List<Role> findAllRoles() { 
    return entityManager.createQuery("from Role").getResultList(); 
} 

gerade passiert. Unterhalb der Ausgabe erzeugt:

 
Hibernate: select personx0_.id as id17_0_, personx0_.firstName as firstName17_0_, personx0_.lastName as lastName17_0_ from Person personx0_ where personx0_.id=? 
Hibernate: select roles0_.persons_id as persons1_1_, roles0_.roles_id as roles2_1_, rolex1_.id as id18_0_, rolex1_.name as name18_0_ from Person_Role roles0_ left outer join Role rolex1_ on roles0_.roles_id=rolex1_.id where roles0_.persons_id=? 
Hibernate: delete from Person_Role where persons_id=? 
Hibernate: delete from Role where id=? 
Hibernate: delete from Role where id=? 
Hibernate: delete from Person where id=? 
Hibernate: select personx0_.id as id17_, personx0_.firstName as firstName17_, personx0_.lastName as lastName17_ from Person personx0_ 
Hibernate: select rolex0_.id as id18_, rolex0_.name as name18_ from Role rolex0_ 
+1

Ja! Ich habe das auch getestet. Es löscht wirklich alle abhängigen Rollen (in diesem Fall), aber ich kann das nicht tun. Ich muss nur die Waisen löschen ... Danke für Ihre Hilfe! – Alucard

+0

@ user368453: In der Tat ist es wie Hibernate kaskadierte die DELETE (und ich verstehe jetzt, dass dies nicht das ist, was Sie wollen). Ich frage mich, ob Hibernate es besser machen kann. –

+0

Ja! Ich wünschte, es könnte ... aber es scheint, ich muss einen Trigger auf der Datenbank dafür zu erstellen, dass das tun =/ – Alucard

-12

try this:

@ManyToMany(cascade = CascadeType.ALL, orphanRemoval=true, fetch = FetchType.LAZY, mappedBy = "yourObject") 
+0

Wie der Kommentar unten sagt, gibt es kein solches Attribut in der ManyToMany-Annotation. – cproinger

2

Bisher ist nicht dort orphanRemoval Attribut für die ManyToMany Anmerkung. Ich habe das gleiche Problem auch. Und der Vorschlag, es in der Datenbank zu implementieren, ist keine Antwort auf das Problem. Die ganze Philosophie von JPA ist gegen Implementierungslogik auf der Datenbank, aber durch die Zuordnungen.

7

Aus dem Buch „Pro JPA 2“:

Nur Beziehungen mit einzelner Mächtigkeit auf der Quellenseite können Waise Entfernung ermöglichen, weshalb Option der orphanRemoval ist auf der @OneToOne und @OneToMany definiert ist Beziehungsanmerkungen, aber auf keiner der @ManyToOne oder @ManyToMany Annotationen.

Es ist ein doofer, aber es gibt keine JPA automatisierte Waise Entfernung für ManyToMany.

Verwandte Themen