Reputation: 4258
I have simple class as you can see below:
@Entity
@Table(name = "post")
public class Post {
@Id
@GeneratedValue
Long id;
@Column(name = "title")
String title;
@Formula("(select current_date())")
Date currentDate;
@OneToMany(mappedBy = "post")
Set<PostComment> commentList = new HashSet<>();
}
and want to update this entity in the service:
@Service
@Transactional
public class PostService {
private final PostRepository postRepository;
public PostService(PostRepository postRepository) {
this.postRepository = postRepository;
}
@Transactional
public Post save(Post entity) {
Post post = postRepository.saveAndFlush(entity);
System.out.println("current_date: " + post.getCurrentDate());
post.getCommentList().forEach(pc -> System.out.println(pc.getReview()));
return post;
}
}
And when i check hibernate logs, it first select
all fields of Post
entity but when i call post.getCurrentDate()
(that it annotated with @Formula
) returns null
:
Hibernate: select post0_.id as id1_0_0_, post0_.title as title2_0_0_, (select current_date()) as formula0_0_ from post post0_ where post0_.id=?
Hibernate: update post set title=? where id=?
current_date: null
Hibernate: select commentlis0_.post_id as post_id3_1_0_, commentlis0_.id as id1_1_0_, commentlis0_.id as id1_1_1_, commentlis0_.post_id as post_id3_1_1_, commentlis0_.review as review2_1_1_ from post_comments commentlis0_ where commentlis0_.post_id=?
review
Why it returns and logs commentList
but doesn't return currentDate
? is it hibernate bug?
NOTE
I pushed the complete sample project in the github you can see here.
Upvotes: 7
Views: 4096
Reputation: 153730
I wrote a test case on my high-performance-java-persistence GitHub repository which works like a charm.
The entity looks as follows:
@Entity(name = "Event")
@Table(name = "event")
public static class Event {
@Id
private Long id;
@Formula("(SELECT current_date)")
@Temporal(TemporalType.TIMESTAMP)
private Date createdOn;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Date getCreatedOn() {
return createdOn;
}
public void setCreatedOn(Date createdOn) {
this.createdOn = createdOn;
}
}
Notice that the Date
property uses the @Temporal
annotation as well.
Now to emulate your use case, I wrote the following data access logic:
Event event = new Event();
event.setId(1L);
entityManager.persist(event);
entityManager.flush();
entityManager.refresh(event);
assertNotNull(event.getCreatedOn());
Notice the refresh
call which is needed since the entity is cached upon persist
, and we want to refetch it anew from the DB.
And, when executing it, Hibernate generates the following statements:
Query:["insert into event (id) values (?)"], Params:[(1)]
Query:["select formulacur0_.id as id1_0_0_, (SELECT current_date) as formula0_0_ from event formulacur0_ where formulacur0_.id=?"], Params:[(1)]
And the test case runs just fine. Just do a comparison debug between your use case and mine and see why yours doesn't work and mine does.
Upvotes: 4