0

I have a case where I have a user and the user had an EmailVerificationToken.

I would like to delete the EmailVerificationToken when the user gets deleted.

However, since the EmailVerificationToken is an object that is only needed for a short period of time (ie only used once and is irrelevant after), I don't want the User entity to contain the token. Instead, I want the EmailVerificationToken to reference the user it belongs to, but not the other way around.

How do I set it up so when I delete the user, it deletes the EmailToken even though it doesn't reference it in the User entity?

This is the code I have currently:

public class EmailVerificationToken implements IEntity, IDto {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "emailVerificationTokenId")
    private Long id;

    @OneToOne
    @JoinColumn(name = "userId", nullable = false)
    private User user;
}

and

public class User implements IEntity, IDto, UserDetails {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "userId")
    private Long id;
}
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
yasgur99
  • 756
  • 2
  • 11
  • 32
  • It seems you want to delete parent when child is deleted. Though, I would recommend to not to do this, and instead put EmailVerificationToken in the User class. You can set it to lazy load, and keep it as bidirectional mapping with mappedBy attribute there to specify that mapping will be present in the EmailVerificationAttribute table. But, again if you want to go ahead with this approach only, you can write a trigger in the database to handle this. You can also go for JPA listener, but getting entity manager in the listener again will be something not to do. – Akshay Khopkar Jul 15 '19 at 21:45
  • @AkshayKhopkar if it is best practice to keep it lazy loaded, I will do it this way and mark question as answered. Thanks – yasgur99 Jul 15 '19 at 21:57
  • It is less about best practice and more about better time performance, since you might not need EmailVerificationToken every time you are fetching a User. – Akshay Khopkar Jul 15 '19 at 22:03
  • @AkshayKhopkar the plan is to delete the token after the email is verified so i questioned why i need a reference to the token in the user object because the field will be null forever after verified (verification happens quickly) – yasgur99 Jul 15 '19 at 22:04
  • because user having token is more reflective of real world use case than it's reverse. – Akshay Khopkar Jul 15 '19 at 22:25
  • Possible duplicate of [JPA: unidirectional many-to-one and cascading delete](https://stackoverflow.com/questions/7197181/jpa-unidirectional-many-to-one-and-cascading-delete) – Johna Jul 16 '19 at 01:00

1 Answers1

0

I am guessing you have a transactional service which handles the deletion of a User.

You need to add a named query in your EmailVerificationToken class. Something like

@NamedQuery(name = EmailVerificationToken.FIND_BY_USER, query = "Select e from EmailVerificationToken e where e.user =:user"), while adding a constant in your class for the name of the query, like:

public static final String FIND_BY_USER = "EmailVerificationToken.FindByUser"; 

Then you need to define a service which finds a managed instance of your token class with the given User instance.

Then in the transactional method, where you would delete the user, first delete the token;

public void deleteUser(User user){
EmailVerificationToken token = someService.findByUser(user); //you get a 
//managed instance using the previously defined query
em.remove(token);
em.remove(user);

}

em is an instance of the Entity manager.

Hopefully this helps you. For any further questions, you are free to ask.

Stefan B.
  • 1
  • 1