Defining your own models

As soon as you have to implement business logic or objects which should be persisted, the implementation should be done in the model. Note that the default implementation of this layer is implemented in Play with the use of JPA, Hibernate, and an SQL database in the background. However, you can of course implement an arbitrary persistence layer if you want.

Getting ready

Any model you define should go into the models package, which resides in the app/models directory.

How to do it...

As in the recipes before, this was already a reference to a user entity. It is the right time to create one now. Store this in the file app/models/User.java:

package models;

import javax.persistence.Entity;
import play.data.validation.Email;
import play.data.validation.Required;
import play.db.jpa.Model;

@Entity
public class User extends Model {

        public String login;

        @Required @Email
        public String email;
}

How it works...

Although there are not many lines of code, lots of things are included here. First, there are JPA annotations marking this class to be stored in a database. Second, there are validation annotations, which can be used to ensure which data should be in the object from an application point of view and not dependent on any database.

Tip

Remember: If you do as many tasks as possible such as validation in the application instead of the database it is always easier to scale. Annotations can be mixed up without problems.

The next crucially important point is the fact that the User class inherits from Model. This is absolutely essential, because it allows you to use the so-called ActiveRecord pattern for querying of data.

Also, by inheriting from the Model class you can use the save() method to persist the object to the database. However, you should always make sure you are importing the correct Model class, as there exists another Model class in the Play framework, which is an interface.

The last important thing which again will be mainly noticed by the Java developers is the fact, that all fields in the example code are public. Though the preceding code does not explicitly define getters and setters, they are injected at runtime into the class. This has two advantages. First, you as a developer do not have to write them, which means that your entity classes are very short and concise and not filled with setters and getters irrelevant to your logic. Second, if you really want to put logic into setters such as adding some complex check or changing the result before really storing it to the database, then it is possible without any problem. If you want you can also reuse your existing JPA entities, which are likely to have getters and setters. It is all a matter of choice. But the shorter your models are the more concise and easy to understand they will be.

There's more...

Now let's talk about some other options, or possibly some pieces of general information that are relevant to this task.

Using finders

Finders are used to query for existing data. They are a wonderful syntactic sugar on top of the Model entity. You can easily query for an attribute and get back a single object or a list of objects. For example:

User user = User.find("byName", name).).).first();

Or you can get a list of users with an e-mail beginning with a certain string:

List<User> users = User.find("byEmailLike", "alexander@%").fetch();

You can easily add pagination:

List<User> users = User.find("byEmailLike", "alexander@%")
                                        .from(20).fetch(10);

Or just add counting:

long results = User.count("byEmailLike", "alexander@%");

Never be anemic

Play has a generic infrastructure to support as many databases as possible. If you implement other persistence solutions, for example, JPA, GAE, or MongoDB, then always try to use the ActiveRecord pattern, because most of the Play developers will be used to it and it is very easy to grasp and understand. If you cannot do this for whatever reasons, like some completely different query language, then still do not use something like the DAO pattern in Play, as this is not natural for the framework and would pretty much break its flow. The anemic domain model—pulling logic from the object into data access objects—should be an absolute no-go when developing with Play.

Learning from the existing examples

Please check the Play examples and the Play documentation at http://www.playframework.org/documentation/1.2/jpa for an extensive introduction about models before reading further as this will be essential as well before going on with more complex topics. You will also find much more info about finders.

Regarding JPA and transactions

This is a short excursion into the JPA world but well worth it. Whenever you deal with databases you will be forced to implement some sort of commit/rollback transaction mechanism. As the standard Play persistence is based on JPA and Hibernate, the problem of course exists as well.

However, in order to simplify things, the HTTP request has been chosen as the transaction boundary. You should keep that in mind when having problems with data you thought should have been committed but is not persisted, because the request is not yet finished. A minor solution to this problem is to call JPA.em().flush(), which synchronizes changes to the database. If you want to make sure that you do not change data which has just been created in another request, you should read a Hibernate documentation about optimistic and pessimistic locking found at http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html/transactions.html.

See also

For more information on the active record pattern you might want to check the Wikipedia entry http://en.wikipedia.org/wiki/Active_record or the more Ruby on Rails specific active record API at http://ar.rubyonrails.org/. There is also an active record implementation in pure Java at http://code.google.com/p/activejdbc.

There is a recipe for encrypting passwords before storing them on the database which makes use of creating an own setter.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.139.97.53