2

I have 2 classes.Video and VideoLinks.VideoLinks related to Video by ManyToOne and LazyLoading.Lazy loading means when i need Video then Video will be fetched. i select VideoLinks and then sleep 10 seconds.i change Video title in database and after 10 seconds application prints related Video title.But this title is not changed title but old title.

Video:

@Entity
@Table(name = "video")
@XmlRootElement
public class Video implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "id")
private Integer id;
@Column(name = "title")
private String title;
@Column(name = "url")
private String url;
@Lob
@Column(name = "description")
private String description;
@Column(name = "date")
@Temporal(TemporalType.TIMESTAMP)
private Date date;
@Column(name = "focused_word")
private String focusedWord;
@Column(name = "tags")
private String tags;
@Column(name = "seo_title")
private String seoTitle;
@Column(name = "seo_description")
private String seoDescription;
@Column(name = "category_id")
private String categoryId;
@Column(name = "slug")
private String slug;
@Column(name = "body")
private String body;
@Column(name = "thumb")
private String thumb;
@Column(name = "body_html")
private String bodyHtml;

public Video() {
}

public Video(Integer id) {
    this.id = id;
}

 //getter-setters

}

VideoLinks:

    @Entity
    @Table(name = "video_links")
    @XmlRootElement
    public class VideoLinks implements Serializable {

        private static final long serialVersionUID = 1L;
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        @Basic(optional = false)
        @Column(name = "id")
        private Integer id;
        @Column(name = "url")
        private String url;
        @Column(name = "text")
        private String text;
        @Basic(optional = false)
        @Column(name = "working")
        private boolean working;
        @JoinColumn(name = "video_id", referencedColumnName = "id")
        @ManyToOne(optional = false, fetch = FetchType.LAZY)
        private Video videoId;

        public VideoLinks() {
        }

        public VideoLinks(Integer id) {
            this.id = id;
        }

        public VideoLinks(Integer id, boolean working) {
            this.id = id;
            this.working = working;
        }

       //getter-setters

    }

Main:

       public static void main(String[] args) {
           VideoServiceInter serviceVideo = new VideoService();
           VideoLinks videoLinks = serviceVideo.getVideoLinks(15);
           System.out.println("i fetched VideoLinks but not Video yet");
           try {
                Thread.sleep(10000);//at this waiting time i change title in database
           } catch (InterruptedException ex) {
                        LOG.log(Level.SEVERE, null, ex);
           }
           System.out.println(vl.getVideoId().getTitle());
         }
Sarkhan
  • 1,281
  • 1
  • 11
  • 33
  • 1
    You know you have a screwdriver but you only fetch it from the garage when you need it. Then you put it aside so you can grab it again. If you need a philipps head instead a flat one, you need to fetch another screwdriver, the one you fetched won't change magically. – Fildor Aug 02 '16 at 07:35
  • @Fildor Good metaphor but it does not explain OP's question. If Video objects are not completely fetched in serviceVideo.getAllVideos() [LazyLoading is supposed to generate only proxies that do not contains "title"] then the last sentence vl.getVideoId().getTitle() should not reflect the change in DB? – RubioRic Aug 02 '16 at 07:45
  • @RubioRic No, why should it? It has been fetched before. The proxy got the Video object form db as soon as the title was displayed the first time. The Controller should mark the entry dirty when changing data in the model (db) so it is fetched again. This is working kind of like a chache. Only that cachelines do not become dirty or deleted here. – Fildor Aug 02 '16 at 07:50
  • If db entries can face changes through another source as the app, then lazy loading as it is done here is not desirable - given changes shall be reflected. – Fildor Aug 02 '16 at 07:52
  • if you want to pull in data that may have been changed elsewhere then you use `em.refresh()` so not using stale data – Neil Stockton Aug 02 '16 at 08:21
  • 1
    i call only VideoLinks after 10 sec i call Video. if i need refresh and jpa fetch and caches result even i don't call related lazy field(i call it firstly after 10 secs) so what is for Lazy loading ?it will cause slow performance. – Sarkhan Aug 02 '16 at 08:36
  • @Fildor I mean the first time that a Video is completely fetched. Let me explain, If you got this sequence 1) Get all VideoLinks. 2) Sleep. 3) Change Video on db before timeout. 4) Print Video title. Should not Video title reflect the change made at point 3? I know that there are other scenarios, including following iterations in the same loop, that will behave as you stated. – RubioRic Aug 02 '16 at 08:50
  • @RubioRic "Should not Video title reflect the change made at point 3?" it should change but i doesn't.my problem it is – Sarkhan Aug 02 '16 at 08:52
  • I know, Serkhan, I know. I'm trying to explain your problem to @Fildor. – RubioRic Aug 02 '16 at 08:55
  • @RubioRic Ah, now I get it. Yes, you are right. That is if the reference to video is not fetched along with videolink. So a lot of assumptions we are making here. Maybe OP can clarify when the reference to video is actually fetched. – Fildor Aug 02 '16 at 08:55
  • 1
    See this answer: http://stackoverflow.com/a/18694015/982149 I guess it may explain the behavior. – Fildor Aug 02 '16 at 09:02
  • @Fidor reference to video is fetched along with videolink.There is no problem here.Problem is why it doesn't fetch last updated text in the title column even i fetch it firstly so it wasn't cached yet.And i am not working on web project so here we can't talk about EJB or app server – Sarkhan Aug 02 '16 at 09:10
  • @Serkhan yes, but you _are_ using JPA. Without having too much experience with it, I guess the solution could go in that direction. – Fildor Aug 02 '16 at 09:15
  • 1
    What implementation of JPA are you using? As Oracle docs says: "The LAZY strategy is a hint to the persistence provider runtime that data should be fetched lazily when it is first accessed. The implementation is permitted to eagerly fetch data for which the LAZY strategy hint has been specified.". Ref: http://docs.oracle.com/javaee/6/api/javax/persistence/FetchType.html – Marco A. Hernandez Aug 02 '16 at 09:56

0 Answers0