2016-02-10 1 views
1

J'ai deux entités:Spring JPA: Empêcher la suppression si les relations existent encore

Tableau activité:

|id|milestone_id|..| 
| 1|3   |..| 
| 2|3   |..| 

Classe:

@Entity 
@Table(name="activity") 
public class Activity implements Serializable { 

    private static final long serialVersionUID = 1L; 

    @Id 
    @Column(nullable = false) 
    @GeneratedValue(strategy = GenerationType.SEQUENCE) 
    private long id; 

    @ManyToOne(optional = false) 
    private Milestone milestone; 
} 

et une table étape:

|id|..| 
| 3|..| 

Classe:

@Entity 
@Table(name="milestone") 
public class Milestone implements Serializable{ 

    private static final long serialVersionUID = 1L; 

    @Id 
    @Column(nullable = false) 
    @GeneratedValue(strategy = GenerationType.SEQUENCE) 
    private long id; 

    @JsonIgnore 
    @OneToMany(fetch = FetchType.LAZY, mappedBy = "milestone") 
    private List<Activity> activities = new ArrayList<>(); 
} 

Maintenant, lorsque je supprime une étape 3, mon activité de sont conservés intacts. Toutefois, le paramètre milestone_id pointe toujours vers le jalon associé qui a déjà été supprimé.

Maintenant, lorsque je récupère les activités à nouveau je reçois cette erreur:

javax.persistence.EntityNotFoundException: Unable to find nl.geodan.vergunningen.manager.domain.Milestone with id 3 

me semble logique. Ce que je veux cependant c'est que le jalon ne peut pas être supprimé, car le milestone_id sur la table d'activité est optional = false.

Qu'est-ce que j'ai manqué? Dois-je recharger les activités? Dois-je utiliser une sorte de CascadeType?

+0

Le point est que vous ne voulez pas laisser supprimer objet 'Milestone' en cas de' Activity' montrant, oui? –

+0

@MaciejDobrowolski oui, je veux l'empêcher de se produire – codesmith

+2

Utiliser une clé étrangère entre les tables ne fonctionnerait pas? – Paolof76

Répondre

2

Votre problème est lié à votre schéma de base de données - J'ai essayé reproducing your problem et je suis sûr que vous n'utilisez pas le schéma généré d'application, mais déjà existant sans clés étrangères définies. Voir le fichier output.txt où ConstraintViolationException se produit.

Vous pouvez ajouter clé étrangère à votre base de données en exécutant la commande appropriée SQL:

ALTER TABLE Activity 
ADD FOREIGN KEY (milestone_id) 
REFERENCES Milestone(id) 

Ou tout simplement changer spring.jpa.hibernate.ddl-auto propriété (in case of spring boot) à create. Si vous utilisez brut Printemps alors ce serait la propriété de Hibernate lui-même - hibernate.hbm2ddl.auto=create. Si vous n'avez pas d'accès ou de privilèges au schéma, vous pouvez le gérer par programme, mais cela est certainement une solution de contournement et une mauvaise odeur - une solution serait de vérifier les dépendances chaque fois que vous supprimez l'entité Milestone, l'autre implique de mettre @PreDelete auditeur dans Milestone entité:

@PreRemove 
private void preRemove() { 
    if (!activities.isEmpty()) { 
     throw new LinkedActivityExistsException(); 
    } 
} 
+0

Maciej, votre analyse est correcte !! J'ai exécuté le test contextLoads au niveau Debug et j'ai recherché le ddl dans le journal. Cela, en effet, différait de mon ddl manuscrite. C'est juste quelque chose que j'ai oublié. Merci! – codesmith