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

import com.vladmihalcea.book.hpjp.util.AbstractPostgreSQLIntegrationTest;
import org.hibernate.Session;
import org.hibernate.annotations.NaturalId;
import org.junit.Test;

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

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;

/**
 * @author Vlad Mihalcea
 */
public class NaturalIdTest extends AbstractPostgreSQLIntegrationTest {

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


    @Override
    public void init() {
        super.init();
        doInJPA(entityManager -> {
            Post post = new Post();
            post.setTitle(String.format("Post nr. %d", 1));
            post.setSlug("high-performance-java-persistence");
            entityManager.persist(post);
        });
    }

    @Test
    public void testFindByNaturalId() {
        doInJPA(entityManager -> {
            String slug = "high-performance-java-persistence";
            Session session = entityManager.unwrap(Session.class);
            Post post = session.bySimpleNaturalId(Post.class).load(slug);
            assertNotNull(post);
        });
    }

    @Test
    public void testFindWithQuery() {
        doInJPA(entityManager -> {
            List<Post> posts = entityManager.createQuery(
                "select p " +
                "from Post p " +
                "where p.slug is not null", Post.class)
            .getResultList();
            assertFalse(posts.isEmpty());
        });
    }

    @Test
    public void testGetReferenceByNaturalId() {
        doInJPA(entityManager -> {
            String slug = "high-performance-java-persistence";
            Session session = entityManager.unwrap(Session.class);
            LOGGER.info("Loading a post by natural identifier");
            Post post = session.bySimpleNaturalId(Post.class).getReference(slug);
            LOGGER.info("Proxy is loaded");
            LOGGER.info("Post title is {}", post.getTitle());
            assertNotNull(post);
        });
    }

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

        @Id
        @GeneratedValue
        private Long id;

        private String title;

        @NaturalId
        @Column(nullable = false, unique = true)
        private String slug;

        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 String getSlug() {
            return slug;
        }

        public void setSlug(String slug) {
            this.slug = slug;
        }
    }
}

@@ -190,18 +190,11 @@
 ons.
-NaturalId;
+*;%0A
 %0Aimp
@@ -257,18 +257,112 @@
 java
-.util.List
+x.persistence.Entity;%0Aimport javax.persistence.Table;%0Aimport java.util.List;%0Aimport java.util.Properties
 ;%0A%0Ai
@@ -684,16 +684,362 @@
 %0A    %7D%0A%0A
+    @Override%0A    protected Properties properties() %7B%0A        Properties properties = super.properties();%0A        properties.put(%22hibernate.cache.use_second_level_cache%22, Boolean.TRUE.toString());%0A        properties.put(%22hibernate.cache.region.factory_class%22, %22org.hibernate.cache.ehcache.EhCacheRegionFactory%22);%0A        return properties;%0A    %7D%0A
 %0A    @Ov
@@ -2592,16 +2592,20 @@
  %22Post%22)
+%0A   
  @Table(
@@ -2615,24 +2615,130 @@
 e = %22post%22)%0A
+    //@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE)%0A    //@NaturalIdCache%0A
     public s

Add caching support