Search code examples
springspring-bootjpahibernate-annotations

JPA OneToOne UPDATE instead of INSERT


I am new to Spring/JPA and I am trying to use Database relationship @annotations to simplify my code.

I have two entities, a User and Token entity. When setToken() is called on the User, I want the Token to overwrite any old tokens associated with the user in the table.

At the moment, the new token (via user.setToken()) is being INSERT rather than UPDATE.

How do I go about achieving this relationship? In "Lame-mans"...A user can only even have one token and can be given another at any time, discarding the old. There are extra fields in these models that i have truncated for clarity.

@Entity
@Table(name = "Users")
public class User {

    @Column(name = "USER_ID")
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    @JsonInclude(JsonInclude.Include.NON_NULL)
    private Long userId;

    @OneToOne(fetch = FetchType.LAZY,cascade = CascadeType.ALL)
    @JoinColumn(name = "REFRESH_TOKEN_ID")
    private RefreshToken refreshToken;

...setters and getters

And the code for a token:

@Entity
@Table(name = "RefreshTokens")
public class RefreshToken {

    @Column(name = "REFRESH_TOKEN_ID")
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long tokenId;

Solution

  • If your RefreshToken has only 1 Field REFRESH_TOKEN_ID which is long. Why you need different table for this. You can just have something like this

    public class User {
    
        @Column(name = "USER_ID")
        @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
        @JsonInclude(JsonInclude.Include.NON_NULL)
        private Long userId;
    
        @Column(name = "REFRESH_TOKEN_ID")
        private Long refreshToken;
    
    ...
    

    When setToken() is called you must be setting any value. If yes thats it. Your logic will work fine,

    If no you can always generate a Unique value in Java based on Current time or something else.

    or

    If you want to continue with same patter use orphanRemoval = true

    @OneToOne(fetch = FetchType.LAZY,cascade = CascadeType.ALL, orphanRemoval = true)
    @JoinColumn(name = "REFRESH_TOKEN_ID")
    private RefreshToken refreshToken;