Home > front end >  How to remove foreign key without deleting the whole entity
How to remove foreign key without deleting the whole entity

Time:02-21

I am new to Spring boot and I want to be able to delete the value of a forgein key if its entity is removed without deleting the whole entity linked to it; I explain in my case a single person who has an Account can be at the same time an Author and a Player, so if delete an author I want to delete its refrence in table Account without deleting the whole account because this account can still point on player I searched on the internet I found cascadetype but it will delete the whole account!

Thank you in advance! here is my entities

@Table(name = "account")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Account implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
    @SequenceGenerator(name = "sequenceGenerator")
    @Column(name = "ID")
    private Long id;

    @ManyToOne
    @JoinColumn(name = "Author")
    private Author author;
    
    @ManyToOne
    @JoinColumn(name = "Player")
    private Player player;

    //attributs, getters & setters
}

@Table(name = "player")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Player implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
    @SequenceGenerator(name = "sequenceGenerator")
    @Column(name = "ID")
    private Long id;

   //attributs, getters & setters
}


//ma.myapp.usersgestion.domain.Author

@Table(name = "author")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Author implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
    @SequenceGenerator(name = "sequenceGenerator")
    @Column(name = "ID")
    private Long id;

    @OneToMany(mappedBy = "author")
    @Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
    @JsonIgnoreProperties(value = { "player", "author"}, allowSetters = true)
    private Set<Account> accounts = new HashSet<>();

   //attributs, getters & setters
}

UPDATE

Im using jhipster (spring boot with React) and h2 database (with disk-based persistence)

//AuthorResource.java
@RestController
@RequestMapping("/api")
@Transactional
public class AuthorResource {

    private final Logger log = LoggerFactory.getLogger(AuthorResource.class);

    private static final String ENTITY_NAME = "author";

    @Value("${jhipster.clientApp.name}")
    private String applicationName;

    private final AuthorRepository authorRepository;

    public AuthorResource(AuthorRepository authorRepository) {
        this.authorRepository = authorRepository;
    }
/**
     * {@code DELETE  /authors/:id} : delete the "id" author.
     *
     * @param id the id of the author to delete.
     * @return the {@link ResponseEntity} with status {@code 204 (NO_CONTENT)}.
     */
    @DeleteMapping("/authors/{id}")
    public ResponseEntity<Void> deleteAuthor(@PathVariable Long id) {
        log.debug("REST request to delete Author : {}", id);
        authorRepository.deleteById(id);
        return ResponseEntity
            .noContent()
            .headers(HeaderUtil.createEntityDeletionAlert(applicationName, true, ENTITY_NAME, id.toString()))
            .build();
    }
   
//...
}

//AuthorRepository

@SuppressWarnings("unused")
@Repository
public interface AuthorRepository extends JpaRepository<Author, Long> {}

CodePudding user response:

In your entity class author add the following:

@OneToMany(fetch = FetchType.LAZY, mappedBy = "author", cascade = { CascadeType.DETACH, CascadeType.MERGE, CascadeType.REFRESH, CascadeType.PERSIST })
private Set<Account> accounts;

I've omitted the cascadetype CascadeType.REMOVE from the list. This will prevent Account from also being deleted when the related Author entity is deleted.

EDIT:

If the above solution somehow doesn't work then you can also try adding @OnDelete(action = OnDeleteAction.NO_ACTION) above the accounts field.

@OnDelete is a hibernate specific annotation.

EDIT 2:

If none of the solutions provided above work then you can also consider making a javax.persistence.@PreRemove annotated method that manually sets the author field for each related Account to null. You place this method inside the Author class. A method that is annotated with @PreRemove will always run before the entity is deleted. So for Author you could use the following method to set all author_id fields to null.

@PreRemove
public void deleteAuthor(){
   this.getAccounts().forEach(account -> account.setAuthor(null));
}
  • Related