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

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

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

import static org.junit.Assert.assertNotNull;

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

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

    @Test
    public void test() {
        doInJPA(entityManager -> {
            for (int i = 0; i < 3; i++) {
                Post post = new Post(String.format("Post nr. %d", i));
                post.setDetails(new PostDetails("Excellent!"));

                entityManager.persist(post);
            }
        });

        doInJPA(entityManager -> {
            List<Post> posts = entityManager.createQuery(
                "select p from Post p " +
                "where p.title like 'Post nr.%'", Post.class)
            .getResultList();
        });
    }

    @Entity(name = "Post")
    @Table(name = "post")
    public static class Post {

        @Id
        @GeneratedValue
        private Long id;

        private String title;

        @OneToOne(mappedBy = "post", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
        private PostDetails details;

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

        public PostDetails getDetails() {
            return details;
        }

        public void setDetails(PostDetails details) {
            if (details == null) {
                if (this.details != null) {
                    this.details.setPost(null);
                }
            }
            else {
                details.setPost(this);
            }
            this.details = details;
        }
    }

    @Entity(name = "PostDetails")
    @Table(name = "post_details")
    public static class PostDetails {

        @Id
        private Long id;

        @Column(name = "created_on")
        private Date createdOn;

        @Column(name = "created_by")
        private String createdBy;

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

        public PostDetails() {}

        public PostDetails(String createdBy) {
            createdOn = new Date();
            this.createdBy = createdBy;
        }

        public Long getId() {
            return id;
        }

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

        public Date getCreatedOn() {
            return createdOn;
        }

        public String getCreatedBy() {
            return createdBy;
        }

        public Post getPost() {
            return post;
        }

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

@@ -506,47 +506,89 @@
     
-%7D;%0A    %7D%0A%0A    @Test%0A    public void tes
+    PostSummary.class%0A        %7D;%0A    %7D%0A%0A    @Override%0A    protected void afterIni
 t() 
@@ -660,9 +660,11 @@
 i %3C 
-3
+100
 ; i+
@@ -875,16 +875,65 @@
     %7D);%0A
+    %7D%0A%0A    @Test%0A    public void testNPlusOne() %7B
 %0A       
@@ -1017,16 +1017,19 @@
 teQuery(
+%22%22%22
 %0A       
@@ -1041,17 +1041,16 @@
     
-%22
 select p
  fro
@@ -1049,79 +1049,458 @@
 ct p
- from Post p %22 +%0A                %22where p.title like 'Post nr.%25'%22, Post
+%0A                from Post p%0A                where p.title like 'Post nr.%25'%0A                %22%22%22, Post.class)%0A            .getResultList();%0A        %7D);%0A    %7D%0A%0A    @Test%0A    public void testWithoutNPlusOne() %7B%0A        doInJPA(entityManager -%3E %7B%0A            List%3CPostSummary%3E posts = entityManager.createQuery(%22%22%22%0A                select p%0A                from PostSummary p%0A                where p.title like 'Post nr.%25'%0A                %22%22%22, PostSummary
 .cla
@@ -2670,32 +2670,528 @@
        %7D%0A    %7D%0A%0A
+    @Entity(name = %22PostSummary%22)%0A    @Table(name = %22post%22)%0A    public static class PostSummary %7B%0A%0A        @Id%0A        @GeneratedValue%0A        private Long id;%0A%0A        private String title;%0A%0A        public Long getId() %7B%0A            return id;%0A        %7D%0A%0A        public void setId(Long id) %7B%0A            this.id = id;%0A        %7D%0A%0A        public String getTitle() %7B%0A            return title;%0A        %7D%0A%0A        public void setTitle(String title) %7B%0A            this.title = title;%0A        %7D%0A    %7D%0A%0A
     @Entity(name

Add alternative to one-to-one N+1