Search code examples
springpostgresqlhibernatejpa

JPA query after save doesn't return database generated field


I'm trying to save this model to a database, and then retrieve what I just saved. Every field is retrieved except for the database generated UUID field.

@Entity
@Table(name = "usertoken")
public class UserToken implements Serializable
{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    
    @Column(name = "token", insertable = false, updatable = false, nullable = false)
    private UUID token;
    
    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name="usersid", nullable=false)
    private User user;
    
    @Column(name = "expiration", updatable = false, nullable = false)
    private LocalDateTime expiration;

I save the token from within the service

token = tokenRepository.save(token);

which generates this SQL

Hibernate: 
    insert 
    into
        usertoken
        (expiration, usersid) 
    values
        (?, ?)

The next statement gets the token

token = tokenRepository.findByUser(user);

I see the SQL select includes the token field

Hibernate: 
    select
        usertoken0_.id as id1_8_,
        usertoken0_.expiration as expirati2_8_,
        usertoken0_.token as token3_8_,
        usertoken0_.usersid as usersid4_8_ 
    from
        usertoken usertoken0_ 
    where
        usertoken0_.usersid=?

...but the returned object has every field populated BUT the token. The database does have a value in the token column. I'm at a loss as to why it would populate every field but one. Here's the table in question:

CREATE TABLE public.usertoken
(
    id integer NOT NULL GENERATED ALWAYS AS IDENTITY ( INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 2147483647 CACHE 1 ),
    usersid integer NOT NULL,
    token uuid NOT NULL DEFAULT uuid_generate_v1(),
    expiration timestamp without time zone NOT NULL,
    CONSTRAINT "usertoken_pkey" PRIMARY KEY (id)
)

I forgot to add that when I query later on the token is found and the UUID field is properly populated. So something weird with JPA caching? Are database DEFAULT column values ignored by hibernate after the insert?

tokenRepository.findByToken(UUID.fromString(userToken));

Hibernate: 
    select
        usertoken0_.id as id1_8_,
        usertoken0_.expiration as expirati2_8_,
        usertoken0_.token as token3_8_,
        usertoken0_.usersid as usersid4_8_ 
    from
        usertoken usertoken0_ 
    where
        usertoken0_.token=?

Solution

    • You have to signal hibernate that field is being generated by database. So add the following:
        @org.hibernate.annotations.Generated(value = GenerationTime.INSERT)
        @Column(name = "token", insertable = false, 
                updatable = false, nullable = false)
        private UUID token;
    
    • You will also see hibernate issues a select just for that column after insert