@@ -447,10 +447,14 @@ We might start with something like this, a mix of UI and persistence logic:
447447
448448[source,java]
449449---- 
450- @Path("/") @Produces("application/json") 
450+ @Path("/") 
451+ @Produces("application/json") 
451452public class BookResource { 
452453
453-     @GET @Path("book/{isbn}") 
454+     private final SessionFactory sessionfactory = .... ; 
455+ 
456+     @GET 
457+     @Path("book/{isbn}") 
454458    public Book getBook(String isbn) { 
455459        var book = sessionFactory.fromTransaction(session -> session.find(Book.class, isbn)); 
456460        return book == null ? Response.status(404).build() : book; 
@@ -473,18 +477,25 @@ Let's now consider a slightly more complicated case.
473477
474478[source,java]
475479---- 
476- @Path("/") @Produces("application/json") 
480+ @Path("/") 
481+ @Produces("application/json") 
477482public class BookResource { 
478483    private static final int RESULTS_PER_PAGE = 20; 
479484
480-     @GET @Path("books/{titlePattern}/{page:\\d+}") 
481-     public List<Book> findBooks(String titlePattern, int page) { 
482-         var books = sessionFactory.fromTransaction(session -> { 
483-             return session.createSelectionQuery("from Book where title like ?1 order by title", Book.class) 
484-                     .setParameter(1, titlePattern) 
485-                     .setPage(Page.page(RESULTS_PER_PAGE, page)) 
486-                     .getResultList(); 
487-         }); 
485+     private final SessionFactory sessionfactory = .... ; 
486+ 
487+     @GET 
488+     @Path("books/{titlePattern}/{pageNumber:\\d+}") 
489+     public List<Book> findBooks(String titlePattern, int pageNumber) { 
490+         var page = Page.page(RESULTS_PER_PAGE, pageNumber); 
491+         var books = 
492+                 sessionFactory.fromTransaction(session -> { 
493+                     var findBooksByTitle = "from Book where title like ?1 order by title"; 
494+                     return session.createSelectionQuery(findBooksByTitle, Book.class) 
495+                             .setParameter(1, titlePattern) 
496+                             .setPage(page) 
497+                             .getResultList(); 
498+                 }); 
488499        return books.isEmpty() ? Response.status(404).build() : books; 
489500    } 
490501
@@ -498,9 +509,9 @@ Let's hit the code with our favorite thing, the Extract Method refactoring. We o
498509
499510[source,java]
500511---- 
501- static List<Book> findBooksTitled(Session session, 
502-                                   String titlePattern, Page page) {  
503-     return session.createSelectionQuery("from Book where title like ?1 order by title" , Book.class) 
512+ static List<Book> findBooksTitled(Session session, String titlePattern, Page page) {  
513+     var findBooksByTitle = "from Book where title like ?1 order by title";  
514+     return session.createSelectionQuery(findBooksByTitle , Book.class) 
504515            .setParameter(1, titlePattern) 
505516            .setPage(page) 
506517            .getResultList(); 
@@ -522,13 +533,13 @@ We need a place to put the annotation, so let's move our query method to a new c
522533            query = "from Book where title like :title order by title") 
523534class Queries { 
524535
525-     static List<Book> findBooksTitled(Session session, 
526-                                       String titlePattern, Page page) { 
536+     static List<Book> findBooksTitled(Session session, String titlePattern, Page page) { 
527537        return session.createQuery(Queries_._findBooksByTitle_)  //type safe reference to the named query 
528538                .setParameter("title", titlePattern) 
529539                .setPage(page) 
530540                .getResultList(); 
531541    } 
542+ 
532543} 
533544---- 
534545
@@ -546,11 +557,13 @@ Whatever the case, the code which orchestrates a unit of work usually just calls
546557[source,java]
547558---- 
548559@GET 
549- @Path("books/{titlePattern}") 
550- public List<Book> findBooks(String titlePattern) { 
551-     var books = sessionFactory.fromTransaction(session -> 
552-             Queries.findBooksTitled(session, titlePattern, 
553-                     Page.page(RESULTS_PER_PAGE, page))); 
560+ @Path("books/{titlePattern}/{pageNumber:\\d+}") 
561+ public List<Book> findBooks(String titlePattern, int pageNumber) { 
562+     var page = Page.page(RESULTS_PER_PAGE, pageNumber); 
563+     var books = 
564+             sessionFactory.fromTransaction(session -> 
565+                     // call handwritten query method 
566+                     Queries.findBooksTitled(session, titlePattern, page)); 
554567    return books.isEmpty() ? Response.status(404).build() : books; 
555568} 
556569---- 
@@ -567,7 +580,9 @@ Suppose we simplify `Queries` to just the following:
567580
568581[source,java]
569582---- 
583+ // a sort of proto-repository, this interface is never implemented 
570584interface Queries { 
585+     // a HQL query method with a generated static "implementation" 
571586    @HQL("where title like :title order by title") 
572587    List<Book> findBooksTitled(String title, Page page); 
573588} 
@@ -579,11 +594,13 @@ We can call it just like we were previously calling our handwritten version:
579594[source,java]
580595---- 
581596@GET 
582- @Path("books/{titlePattern}") 
583- public List<Book> findBooks(String titlePattern) { 
584-     var books = sessionFactory.fromTransaction(session -> 
585-             Queries_.findBooksTitled(session, titlePattern, 
586-                     Page.page(RESULTS_PER_PAGE, page))); 
597+ @Path("books/{titlePattern}/{pageNumber:\\d+}") 
598+ public List<Book> findBooks(String titlePattern, int pageNumber) { 
599+     var page = Page.page(RESULTS_PER_PAGE, pageNumber); 
600+     var books = 
601+             sessionFactory.fromTransaction(session -> 
602+                     // call the generated query method "implementation" 
603+                     Queries_.findBooksTitled(session, titlePattern, page)); 
587604    return books.isEmpty() ? Response.status(404).build() : books; 
588605} 
589606---- 
@@ -592,32 +609,37 @@ In this case, the quantity of code eliminated is pretty trivial.
592609The real value is in improved type safety.
593610We now find out about errors in assignments of arguments to query parameters at compile time.
594611
595- This is all quite nice so far, but at this point you're probably wondering whether we could use dependency injection to obtain an _instance_ of the `Queries` interface.
612+ This is all quite nice so far, but at this point you're probably wondering whether we could use dependency injection to obtain an _instance_ of the `Queries` interface, and have this object take care of obtaining its own `Session` .
596613Well, indeed we can.
597614What we need to do is indicate the kind of session the `Queries` interface depends on, by adding a method to retrieve the session.
615+ Observe, again, that we're _still_ not attempting to hide the `Session` from the client code.
598616
599617[source,java]
600618---- 
619+ // a true repository interface with generated implementation 
601620interface Queries { 
602-     EntityManager entityManager(); 
621+     // declare the kind of session backing this repository 
622+     Session session(); 
603623
624+     // a HQL query method with a generated implementation 
604625    @HQL("where title like :title order by title") 
605626    List<Book> findBooksTitled(String title, Page page); 
606627} 
607628---- 
608629
609- The `Queries` interface is now considered a _repository_, and we may use CDI to inject the repository implementation generated by Hibernate Processor:
630+ The `Queries` interface is now considered a _repository_, and we may use CDI to inject the repository implementation generated by Hibernate Processor.
631+ Also, since I guess we're now working in some sort of container environment, we'll let the container manage transactions for us.
610632
611633[source,java]
612634---- 
613- @Inject Queries queries; 
635+ @Inject Queries queries;  // inject the repository  
614636
615637@GET 
616- @Path("books/{titlePattern}") 
638+ @Path("books/{titlePattern}/{pageNumber:\\d+} ") 
617639@Transactional 
618- public List<Book> findBooks(String titlePattern) { 
619-     var books  = queries.findBooksTitled(session, titlePattern,  
620-                     Page.page(RESULTS_PER_PAGE,  page));  
640+ public List<Book> findBooks(String titlePattern, int pageNumber ) { 
641+     var page  = Page.page(RESULTS_PER_PAGE, pageNumber);  
642+     var books = queries.findBooksTitled(session, titlePattern,  page); // call the repository method  
621643    return books.isEmpty() ? Response.status(404).build() : books; 
622644} 
623645---- 
0 commit comments