3

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=?
2
  • Maybe data for UUID type not properly serialized, you can try with string type Commented Jul 16, 2020 at 19:22
  • I updated my original post to state that I can get a value back, just not immediately after saving. Commented Jul 16, 2020 at 19:44

2 Answers 2

4
  • 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
Sign up to request clarification or add additional context in comments.

6 Comments

That did it. Now is there a way to indicate this via a JPA annotation or only hibernate?
There is no JPA annotation. you will have to use the above hibernate annotation
Really new thing to learn! Does that mean saveAndFlush should also work?
@Eklavya I am not actually sure about saveAndFlush(), because it's purpose is to flush what is so far queued in the session in uncommited state so the next query in the same transaction sees it. Here the purpose is opposite as something else changed the database while the transaction is in progress which hibernate is not aware of. So I suspect even if I do saveFlush , there is no reason for hibernate to issue a select for that column before the saveFlush method returns
Problem is when the results comeback, hibernate will probably ignore anything that has the same id as from the previous save saying hey i know this object, i have it in my session, I don't need to populate it again. saveAndFlush is more to help with a table level query incase the one in session satisfies that query too. But when the results comeback, hibernate will only create the objects that it does not have yet in session. But I would play with this and confirm you.
|
0

Below code changes worked for me at entity level

import org.hibernate.annotations.Generated;
import org.hibernate.generator.EventType;

@Generated(event = EventType.INSERT)
@Column(name = "STAFF_ID")
private String StaffId;

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.