Home > Back-end >  Spring Data JPA transient field returns wrong value
Spring Data JPA transient field returns wrong value

Time:10-08

I have two models: Deck and Word with a one-to-many relationship. The Deck model has a transient field showWordsToRevise. I am trying to initialize that field with the amount of words in List<Words> with a statusRepeating == true field.

public class Deck {
    @Id
    @Column(name = "deck_id")
    private Long id;

    @Transient
    private Boolean showWordsToRevise;

    @JsonManagedReference
    @OneToMany(mappedBy = "deck", cascade = CascadeType.ALL)
    private List<Word> words;

    public Boolean getShowWordsToRevise() {
        System.out.println(this.words.stream().map(w -> w.getStatusRepeating()).count()   "  words to revise"   java.time.LocalDateTime.now().toString());
        return this.words.stream().map(w -> w.getStatusRepeating()).count() > 0;
    }

    public void setShowWordsToRevise(Boolean showWordsToRevise) {
        this.showWordsToRevise = showWordsToRevise;
    }
}

and

public class Word {
    @Id
    @Column(name = "word_id")
    private Long id;
    private LocalDate last_checked;
    @Enumerated(EnumType.STRING)
    private WordGroup wordGroup = WordGroup.newUnseen;
    @Transient
    private Boolean statusRepeating = false;
    @ManyToOne
    @JsonBackReference
    @JoinColumn(name="deck_id",referencedColumnName="deck_id")
    private Deck deck;
    

    public Boolean getStatusRepeating() {
        if (this.wordGroup == WordGroup.first && Period.between(this.last_checked,LocalDate.now()).getDays() > 1) return true;
        if (this.wordGroup == WordGroup.second && Period.between(this.last_checked,LocalDate.now()).getDays() > 2) return true;
        return this.wordGroup == WordGroup.third && Period.between(this.last_checked, LocalDate.now()).getDays() > 7;
    }
    public void setStatusRepeating(Boolean statusRepeating) {
        this.statusRepeating = statusRepeating;
    }
}

The problem is that when there are no words in List<Words> with statusRepeating == true the showWordsToRevise in Word still returns true.

JSON

Hibernate logs twice for the same request, first prints the wrong number, then prints the right number. upd it shows 0 at second print because there is no words in List<Words>

Hibernate: 
    select
        words0_.deck_id as deck_id8_3_0_,
        words0_.word_id as word_id1_3_0_,
        words0_.word_id as word_id1_3_1_,
        words0_.body as body2_3_1_,
        words0_.deck_id as deck_id8_3_1_,
        words0_.definition as definiti3_3_1_,
        words0_.example as example4_3_1_,
        words0_.last_checked as last_che5_3_1_,
        words0_.transcription as transcri6_3_1_,
        words0_.word_group as word_gro7_3_1_ 
    from
        word words0_ 
    where
        words0_.deck_id=?
1  words to revise2021-10-07T10:28:30.059128400
Hibernate: 
    select
        words0_.deck_id as deck_id8_3_0_,
        words0_.word_id as word_id1_3_0_,
        words0_.word_id as word_id1_3_1_,
        words0_.body as body2_3_1_,
        words0_.deck_id as deck_id8_3_1_,
        words0_.definition as definiti3_3_1_,
        words0_.example as example4_3_1_,
        words0_.last_checked as last_che5_3_1_,
        words0_.transcription as transcri6_3_1_,
        words0_.word_group as word_gro7_3_1_ 
    from
        word words0_ 
    where
        words0_.deck_id=?
0  words to revise2021-10-07T10:28:30.060126900

CodePudding user response:

You need to update your Deck class and change getShowWordsToRevise() method so that you count the words that have statusRepeating == true:

public class Deck {
    @Id
    @Column(name = "deck_id")
    private Long id;

    @Transient
    private Boolean showWordsToRevise;

    @JsonManagedReference
    @OneToMany(mappedBy = "deck", cascade = CascadeType.ALL)
    private List<Word> words;

    public Boolean getShowWordsToRevise() {
        long wordsToReviseCount = this.words.stream().filter(WordLadder::getStatusRepeating).count();
        System.out.println(wordsToReviseCount   " words to revise "   java.time.LocalDateTime.now());
        return wordsToReviseCount > 0;
    }

    public void setShowWordsToRevise(Boolean showWordsToRevise) {
        this.showWordsToRevise = showWordsToRevise;
    }
}
  • Related