package com.vladmihalcea.book.hpjp.hibernate.association;

import com.vladmihalcea.book.hpjp.util.AbstractTest;
import org.hibernate.LazyInitializationException;
import org.junit.Test;

import javax.persistence.*;
import java.util.List;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;

/**
 * @author Vlad Mihalcea
 */
public class FindVsGetReferenceTest extends AbstractTest {

    @Override
    protected Class<?>[] entities() {
        return new Class<?>[] {
            Post.class,
            PostComment.class,
        };
    }

    @Override
    protected void afterInit() {
        doInJPA(entityManager -> {
            Post post = new Post();
            post.setId(1L);
            post.setTitle("High-Performance Java Persistence");

            entityManager.persist(post);
        });
    }

    @Test
    public void testFind() {
        doInJPA(entityManager -> {
            PostComment comment = new PostComment();
            comment.setReview("Just awesome!");

            Post post = entityManager.find(Post.class, 1L);
            comment.setPost(post);

            entityManager.persist(comment);
        });

        Post post = doInJPA(entityManager -> {
            return entityManager.find(Post.class, 1L);
        });

        assertEquals("High-Performance Java Persistence", post.getTitle());
    }

    @Test
    public void testGetReference() {
        doInJPA(entityManager -> {
            PostComment comment = new PostComment();
            comment.setReview("Just awesome!");

            Post post = entityManager.getReference(Post.class, 1L);
            comment.setPost(post);

            entityManager.persist(comment);
        });

        Post post = doInJPA(entityManager -> {
            return entityManager.getReference(Post.class, 1L);
        });

        try {
            post.getTitle();

            fail("Should throw LazyInitializationException");
        } catch (LazyInitializationException e) {
            LOGGER.info("Failure expected", e);
        }
    }
    
    @Entity(name = "Post")
    @Table(name = "post")
    public static class Post {

        @Id
        private Long id;

        private String title;

        public Post() {}

        public Post(String title) {
            this.title = title;
        }

        public Long getId() {
            return id;
        }

        public void setId(Long id) {
            this.id = id;
        }

        public String getTitle() {
            return title;
        }

        public void setTitle(String title) {
            this.title = title;
        }
    }

    @Entity(name = "PostComment")
    @Table(name = "post_comment")
    public static class PostComment {

        @Id
        @GeneratedValue
        private Long id;

        private String review;

        @ManyToOne(fetch = FetchType.LAZY)
        private Post post;

        public PostComment() {}

        public PostComment(String review) {
            this.review = review;
        }

        public Long getId() {
            return id;
        }

        public void setId(Long id) {
            this.id = id;
        }

        public String getReview() {
            return review;
        }

        public void setReview(String review) {
            this.review = review;
        }

        public Post getPost() {
            return post;
        }

        public void setPost(Post post) {
            this.post = post;
        }
    }
}

@@ -658,27 +658,54 @@
         
-Post post =
+entityManager.persist(%0A               
  new Pos
@@ -707,18 +707,24 @@
 w Post()
-;
 %0A
+       
         
@@ -723,28 +723,25 @@
             
-post
+ 
 .setId(1L);%0A
@@ -738,18 +738,23 @@
 etId(1L)
-;
 %0A
+      
         
@@ -757,20 +757,18 @@
         
-post
+  
 .setTitl
@@ -805,18 +805,16 @@
 stence%22)
-;%0A
 %0A       
@@ -822,34 +822,8 @@
     
-entityManager.persist(post
 );%0A 
@@ -2218,113 +2218,8 @@
 e;%0A%0A
-        public Post() %7B%7D%0A%0A        public Post(String title) %7B%0A            this.title = title;%0A        %7D%0A%0A
     
@@ -2285,36 +2285,36 @@
 %0A        public 
-void
+Post
  setId(Long id) 
@@ -2333,32 +2333,57 @@
   this.id = id;%0A
+            return this;%0A
         %7D%0A%0A     
@@ -2460,28 +2460,28 @@
      public 
-void
+Post
  setTitle(St
@@ -2518,32 +2518,57 @@
 .title = title;%0A
+            return this;%0A
         %7D%0A    %7D%0A
@@ -2844,130 +2844,8 @@
 t;%0A%0A
-        public PostComment() %7B%7D%0A%0A        public PostComment(String review) %7B%0A            this.review = review;%0A        %7D%0A%0A
     
@@ -2915,28 +2915,35 @@
      public 
-void
+PostComment
  setId(Long 
@@ -2966,32 +2966,57 @@
   this.id = id;%0A
+            return this;%0A
         %7D%0A%0A     
@@ -3095,28 +3095,35 @@
      public 
-void
+PostComment
  setReview(S
@@ -3164,32 +3164,57 @@
 eview = review;%0A
+            return this;%0A
         %7D%0A%0A     
@@ -3291,20 +3291,27 @@
  public 
-void
+PostComment
  setPost
@@ -3350,24 +3350,49 @@
 ost = post;%0A
+            return this;%0A
         %7D%0A  

Add Fluent-style API