代码之家  ›  专栏  ›  技术社区  ›  Rasool Ghafari

hibernate为保存实体后用@formula注释的实体属性返回null

  •  4
  • Rasool Ghafari  · 技术社区  · 8 年前

    我有一个简单的课程,如你所见:

    @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<>();
    }
    

    并希望更新服务中的此实体:

    @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;
        }
    }
    

    当我检查hibernate日志时,它首先 select 所有字段 Post 实体但当我打电话 post.getCurrentDate() (它用 @Formula )回报 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
    

    为什么它返回并记录 commentList 但没有回来 currentDate 是吗?是冬眠虫吗?

    注意

    我在github中推送了完整的示例项目 here 是的。

    1 回复  |  直到 8 年前
        1
  •  2
  •   Vlad Mihalcea    8 年前

    我写的 a test case on my high-performance-java-persistence GitHub repository 就像一种魅力。

    实体如下所示:

    @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;
        }
    }
    

    请注意 Date 属性使用 @Temporal 注释也一样。

    现在为了模拟您的用例,我编写了以下数据访问逻辑:

    Event event = new Event();
    event.setId(1L);
    
    entityManager.persist(event);
    entityManager.flush();
    
    entityManager.refresh(event);
    
    assertNotNull(event.getCreatedOn());
    

    注意 refresh 由于实体被缓存而需要的调用 persist ,我们想从数据库重新提取它。

    并且,在执行时,hibernate会生成以下语句:

    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)]
    

    测试用例运行良好。只需在您的用例和我的用例之间做一个比较调试,看看为什么您的用例和我的用例不工作。