Classy Data

Classy Data Many-to-Many Example

Classy Data is best introduced using a working example such as the one presented here. The example takes the OrmLite ManyToMany sample and reworks it as a Classy Data application. Here is a summary of the changes, which highlight Classy Data usage:

  • Entity classes now use JPA annotations: @Entity, @Id, @Column, @JoinColumn, @OneToOne and @ManyToMany
  • A persistence.xml configuration file identifies entity classes and database name
  • The application is "wired" using Dagger dependency injection, utilizing annotations: @Component, @Subcomponent, @Module, @Provides and @Singleton
  • A PersistenceContext object hides the ORM implementation including database creation, opening connections and establising entity tables
  • A PersistenceWork interface for performing tasks with provided EntityManager in a transaction context
  • A DaoQueryFactory interface for performing named queries using OrmLite QueryBuilder as a substitute for absent JPA Query Language

Running the Example

There are two sample applications which only differ in which database is used: ManyToManyMain.java uses Sqlite in memory and H2ManyToManyMain.java uses H2 on file system. The difference is manifest by having distinct Dagger modules for each application: ManyToManyModule.java for Sqlite and H2ManyToManyModule.java for H2. If the modules are compared, the differences will be found to be minor. Note that Sqlite and H2 are the only currently supported databases, but others can be added by writing an adapter class which gets wired by dependency injection and is therefore not required to be integrated into the Classy Data library.

The many2many-example can be either run as a Java Application from the static main() method of the (H2)ManyToManyMain class or as a JUnit Test from the (H2)ManyToManyTest class test_many_to_many_jpa() method. When run as an application, the console output will contain informative information omitted from the JUnit test.

Console output
PostsByUser:
Bilbo Baggins posted "Wow is it cold outside!!" & "Now it's a bit warmer thank goodness."
UsersByPosts:
Only Bilbo Baggins posted "Wow is it cold outside!!"
Both Bilbo Baggins and Gandalf Gray posted "Now it's a bit warmer thank goodness."
Test completed successfully

Usage

Entity Classes

Entities are implemented as Java beans and Classy Data has no requirements regarding class inheritance or interface implementation. However, every entity class is required to have an identity (ID) field. as it provides a simple, consistent way to uniquely identify objects of the same type and build relationships. ManyToMany has 2 entity classes by design: User, Post and a join table entity, UserPost.

You will observe JPA annotations applied to these classes in a consistent manner:

  • @Entity to mark a class as an entity class and name the database table to persist entity objects
  • @Id and @GeneratedValue to create an auto-generated identity attribute named "id"
  • @Column for normal attributes and @JoinColumn to identify a foreign key
  • @OneToOne and @ManyToMany to signify relationships
persistence.xml

The persistence.xml defines, for each persistence unit, the entity classes and the database name. The file must be located on the application classpath. ManyToMany has it's perisistence.xml in the main resources folder and has the following content:

<persistence-unit name="manytomany">
<class>au.com.cybersearch2.example.User</class>
<class>au.com.cybersearch2.example.Post</class>
<class>au.com.cybersearch2.example.UserPost</class>
<property name="database-name" value="manytomany.db"/>
</persistence-unit>
Dependency Injection

Classy Data has been developed from the start using dependency injection as a tool to decouple the many parts which must be assembled to provide a persistence framework. You may want to look at Dagger for an introduction on how dependency injection is employed in Classy Data. ManyToMany has what is pretty much "boilerplate" code to wire up it's persistence context and task execution sub contexts. Have a look at classes (H2)ManyToManyModule and (H2)ManyToManyFactory. The factory class defines the persistent context as a Component which has application scope, and the task sub context as a Subcomponent with transaction scope.

Application Details

The most important topic is of course application design for which some principles apply. Classy Data provides a framework for performing persistence tasks. Each task must implement the PersistenceWork interface. This features the doTask method which has just one parameter, an EntityManager object as per the JPA API. Upon completion, doTask commits any outstanding changes. ManyToMany has 3 such tasks. One is an anonymous inner class to populate the database, and the other two are PostsByUserEntityTask and UsersByPostTask, which implement the application design.

Queries are an important part of persistence programming and ManyToMany creates a named query for each entity task to get the desired result. A factory class named ManyToManyGenerator creates a named query using entity attributes to form query parameters.