InfoQ

News

Polyforms - Reduce DAO Code Duplication

Posted by R.J. Lorimer on Oct 25, 2008 05:20 PM

Community
Java
Topics
Data Access
Tags
Spring ,
Hibernate

The goal of the Polyforms project is to remove the heavily duplicated glue code to tie data access objects to the underlying persistence API. The approach used in the framework is to automatically implement service methods on a Repository interface defined by the developer. Methods defined on the interface are, by default, linked to database operations via naming conventions. For example, the wiki discusses how to implement a repository for a User entity object. First, the API for the repository must be defined:

public interface UserRepository extends EntityRepository<User, String> {
       
    @Finder
    List<User> findByCreator(User creator);
}

The @Finder annotation marks the method for Polyforms. Rather than creating an implementation for the UserRepostiory, however, a matching Hibernate query needs to be provided on the User entity via another annotation.

@NamedQueries({
    @NamedQuery(name = "User.findByCreator", query = "select u from User u where u.creator = :creator"),
})
public class User {
   
...
}

As per the documentation, the convention used to find queries is based on the method name, as well as the name of the entity itself:


The rule for mapping method with Named Query is [name of Named Query] = [name of Entity].[name of method]. you can specify the name of Named Query in @Finder as @Finder("findUserByName"), then the name of Named Query will be "User.findUserByName".

In addition to the @Finder annotation, there is also an @Updater and a @Counter annotations to provide support for mass updates and counting queries respectively. The

EntityRepository

parent interface already provides support for saving single entities, deleting, and retrieving by identifier.



All of this wiring is done via the

Spring framework

and relies on Spring aspects to be able to provide runtime implementations of the APIs.



Other functionality supported by Polyforms includes:


  • Automatic management of tracking information (created by, created date, modified by, modified date)
  • Transparent pagination support
  • Definition of transaction boundaries via annotation
  • Domain event model to decouple persistence events from application functionality

More information is available on the

Polyforms wiki

.

18 comments

Watch Thread Reply

Huh? by Ilja Preuß Posted Oct 26, 2008 2:19 AM
Re: Huh? by George G Posted Oct 26, 2008 5:40 AM
Re: Huh? by jack ding Posted Oct 26, 2008 8:48 PM
Re: Huh? by Kuisong Tong Posted Oct 26, 2008 10:32 PM
Re: Huh? by Ilja Preuß Posted Oct 27, 2008 8:14 AM
Add this to Spring framework by Vineet Bhatia Posted Oct 26, 2008 12:30 PM
another annotation based DAO by Mert Can Akkan Posted Oct 26, 2008 2:49 PM
Take a look at Hades project by Oliver Gierke Posted Oct 27, 2008 2:12 AM
Re: Take a look at Hades project by Mario Gleichmann Posted Oct 27, 2008 4:03 AM
Re: Take a look at Hades project by Oliver Gierke Posted Oct 27, 2008 5:17 AM
Re: Take a look at Hades project by Kuisong Tong Posted Oct 27, 2008 9:04 PM
Re: Take a look at Hades project by Pete the Wheat Posted Oct 28, 2008 7:46 AM
Re: Take a look at Hades project by Oliver Gierke Posted Oct 28, 2008 8:45 AM
Arid POJOs provides generic DAOs with dynamic finders for Hibernate by Chris Richardson Posted Oct 27, 2008 4:02 PM
Similar things I have done by Adrian Shum Posted Oct 29, 2008 3:31 AM
Re: Similar things I have done by Oliver Gierke Posted Oct 29, 2008 6:48 AM
Re: Similar things I have done by Kuisong Tong Posted Oct 29, 2008 9:56 PM
Re: Similar things I have done by Adrian Shum Posted Oct 30, 2008 12:33 AM
  1. Back to top

    Huh?

    Oct 26, 2008 2:19 AM by Ilja Preuß

    I don't understand why the queries are declared on the user class - this seems to defeat the whole purpose of using DAOs/Repositories in the first place, namely decoupling the domain objects from persistence logic...

  2. Back to top

    Re: Huh?

    Oct 26, 2008 5:40 AM by George G

    The queries are declared on the user class, because this is the JPA specification. I like the idea.

  3. Back to top

    Add this to Spring framework

    Oct 26, 2008 12:30 PM by Vineet Bhatia

    Spring Framework ORM and DAO could use some ideas from this.

  4. Back to top

    another annotation based DAO

    Oct 26, 2008 2:49 PM by Mert Can Akkan

    I although there is no open implementation yet here is another ways of NOT implementing DAO layer http://www.altuure.com/2008/10/02/who-needs-implementations/ have fun

  5. Back to top

    Re: Huh?

    Oct 26, 2008 8:48 PM by jack ding

    JPA sucks!

  6. Back to top

    Re: Huh?

    Oct 26, 2008 10:32 PM by Kuisong Tong

    queries can be defined in other file. In user class, the benefit is all things in one place.

  7. Back to top

    Take a look at Hades project

    Oct 27, 2008 2:12 AM by Oliver Gierke

    There is an open source project called Hades that provides this facilit, too. Actually in our case it is neither necessary to mark the method with an annotation. Additionally we offer constructing the query from the finder method's name if no NamedQuery was found: findByUsername on a UserDao for a User class would result in from User u where u.username = ? Of course this is only suitable for very rudimentary queries but you can always override this with a namedquery. Furthermore Hades seems to offer more sophisticated support like auditing and a Spring namespace to easy configuration. http://trac.synyx.org/hades Regards, Ollie

  8. Back to top

    Re: Take a look at Hades project

    Oct 27, 2008 4:03 AM by Mario Gleichmann

    Hey Ollie, i just did some investigations on Hades over the weekend. God job! For all others, interested in that topic - i would definitely take a closer look! Greetings Mario

  9. Back to top

    Re: Take a look at Hades project

    Oct 27, 2008 5:17 AM by Oliver Gierke

    > God job! I'm not that overwhelming but appreciate your congratulations ;). Regards, Ollie

  10. Back to top

    Re: Huh?

    Oct 27, 2008 8:14 AM by Ilja Preuß

    Well, I guess I simply wouldn't call "all things in one place" a benefit. Anyway, it's good to know that there is an alternative. Obviously, I'm not very knowledgeable about JPA, so thanks for the input!

  11. Back in 2007, I blogged about Arid POJOs (http://code.google.com/p/aridpojos/), which provides generic DAOs for Hibernate. When an abstract finder is called, Arid will either invoke a named query with the same name or parse the method name using an approach similar to dynamic finders in Grails GORM and Active Record. We have used it on several projects over the past 18 months and found that it has significantly reduced the amount DAO code that we need to write. Chris

  12. Back to top

    Re: Take a look at Hades project

    Oct 27, 2008 9:04 PM by Kuisong Tong

    Generic DAO just one big feature in Polyforms, Others include Delegator(auto conversion between DTO and Model), Domain Event(@observer in method like in c#).

  13. Back to top

    Re: Take a look at Hades project

    Oct 28, 2008 7:46 AM by Pete the Wheat

    Hades looks interesting indeed, but version 0.2... :)

  14. Back to top

    Re: Take a look at Hades project

    Oct 28, 2008 8:45 AM by Oliver Gierke

    @Pete I agree, that you consider libraries in detail, especially if it touches the core of your application. But I guess you wouldn't blindly follow a "1.0" tag without testing it, would you? ;) So feel free to play with it a little, push the boundries and don't hesitate to comment on things you don't like :). @Kusiong Yes, I've browsed through the project repository a litte. I especially like the idea to map DTOs against domain object automatically. We seem to have some overlaps but guess we can surely find other projects out there that implemented this idea. So keep up the good work! Regards, Ollie

  15. Back to top

    Similar things I have done

    Oct 29, 2008 3:31 AM by Adrian Shum

    I think we are both inspired by http://www-128.ibm.com/developerworks/java/library/j-genericdao.html In my current project, we do adopted a similar framework, with a lot of things extra. In fact I am also planning to tidy it up and release a generic dao framework later if I have time. Base on what I did, there are some comments on what u described here: 1) You gotta have annotation for input argument to 'map' it to the named parameter place holder. By reflection I think there is no way to get the input argument name 2) Base on our experience, putting the query as named query, is hard to debug if there is syntax error. We use Hibernate + Spring and result of incorrect named query is just a bunch of non-understandable errors. Therefore in my own framework, I provided @Query(query="your query") to annotate the finder method, and as the query is really executed in runtime, we get the understandable error of telling us what's wrong on the query. 3) Sql query and self-implementing finder method should also be provided as there are always cases that is hard to represent by a single HQL. Interesting enough, we have also developed a primitive annotation base Model-DTO mapping tools. By certain annotations in the DTO side, it build DTO base on model object passed in, and incoming DTO back to model. Basic idea on the DAO framework is shared, though in Chinese, in my blog: http://adrianshum.blogspot.com/ (in case u have interest)

  16. Back to top

    Re: Similar things I have done

    Oct 29, 2008 6:48 AM by Oliver Gierke

    Considering 1). Actually you can if the code was compiled with debug flag enabled. Spring provides a LocalVariableTableParameterNameDiscoverer (http://static.springframework.org/spring/docs/2.5.x/api/org/springframework/core/LocalVariableTableParameterNameDiscoverer.html) to do this. Regards, Ollie

  17. Back to top

    Re: Similar things I have done

    Oct 29, 2008 9:56 PM by Kuisong Tong

    @Adrian 1)Polyforms use convention: The parameters in method should order by name in NamedQuery. 2)We always add NamedQuery to Entity, so hibernate (or other JPA implementation) help us check the syntax during startup. 3)Polyforms has a function named query like QBC, developer write HQL like = {createdTimeFrom} ~/ /~ and u.createdTime < {createdTimeDue} ~/ order by u.userName ]]> and system will remove clause between /~ and ~/ when the parameter is null.

  18. Back to top

    Re: Similar things I have done

    Oct 30, 2008 12:33 AM by Adrian Shum

    Hi Kuisong 1) we considered such convention before, but in real world development it is too restrictive and not that feasible. Developer may bind same param multiple times. And DAO's method signature shouldn't depends on the actual query. However in some case it is hard to move the named param around. 2) That's the main problem we faced. Yes, hibernate checked and tell us that it cannot be started up because there is problem, but as far as I remembered, it doesn't tell much on what cause the failure. Which is very troublesome, especially someone write a incorrect named query, and all DAO related unit tests failed. 3) Interesting enough, we also did similar things :) We called it dynamic query and is put in our @Query (similar to your @Finder). we do something like select balbalbla from User u where 1=1 {and:bindparam1 u.val = :bindparam1} (We make it works for both SQL and HQL too) However, still there are cases that finder method is unable to present by a single query. Therefore considering leaving flexibility to developer to let them write DAO finders in traditional way is a must if u want to make the framework use-able in real world development :)

Educational Content

Bindings, Platforms, and Innovation

This presentation focuses on the Internet and separating myth from fact, history from the future, and the mundane from the imaginative. Bob Frankston presents a vision of what could and should be.

Orchestrating Long Running Activities with JBoss / JBPM

This article explores the use of JBoss and jBPM to implement design solutions that effectively address the issue of orchestrating long running activities.

Neo4j - The Benefits of Graph Databases

This presentation covers the use of graph databases as an optimal solution for data that is difficult to fit in static tables, rapidly evolving data or data that has a lot of optional attributes.

Realistic about Risk: Software development with Real Options

This session introduces Real Options and shows how it can help in running your project. Real Options is a decision-making process that can be used to manage risk.

Communication Flexibility Using Bindings

This article discusses the use of bindings on services and references (including the instance of non-configured bindings) as the means to implement SCA communications in a Web and SOA environment.

Writing DSLs in Groovy

After a short introduction to DSLs, Scott Davis plays with the keyboard showing how to approach the creation of a DSL by typing working snippets of Groovy code that get executed.

Scaling Agile with C/ALM (Collaborative Application Lifecycle Management)

IBM Rational and InfoQ present, Scaling Agile with C/ALM, an eBook showing organizations how to become “finely tuned software delivery machines” by enabling team integration and scaling.

Concurrent Programming with Microsoft F#

Amanda Laucher presents a real life enterprise application written in F#. She shows actual code snippets, explaining design decisions and suggesting how to use some of the F# constructs.