Reputation: 2500
So recently started on a new web app which will be using Play 2.4. I've been using JPA for a lot of projects, but I decided to give Ebean a shot this time.
However I'm wondering about the separation of concerns. With JPA I would typically create models, services and DAOs for persistence. With Ebean I understand that there's support for static methods on the models (see http://ebean-orm.github.io/quickstart "Create Model").
I've seen quite a few examples where everything seems to go into these static methods sitting in the models; business logic, persistence logic and what not. Is this best practice when using Ebean that I should just embrace? Or does it still make sense to separate the logic using services and DAOs, and who would I go about doing that in the best way?
Upvotes: 1
Views: 919
Reputation: 8202
You can do things exactly as you did with JPA, and create DAOs, etc.
If you check the static methods in the Ebean examples, you'll see they typically use a Finder
. For a table Country
whose primary key is a String
iso2
, you would have a model class like this:
@Entity
public class Country extends Model {
@Id
public String iso2;
// other stuff
}
In an Ebean example ActiveRecord-style of code, there would be some additional stuff.
@Entity
public class Country extends Model {
private static final Finder<String, Country> FIND = new Finder<>(String.class, Country.class);
@Id
public String iso2;
public static List<Country> findAll() {
return FIND.all();
}
// other stuff
}
If you wanted to change this to a DAO-style approach, you just need to move the Finder
-related code out of Country
.
public class CountryDao {
private static final Model.Finder<String, Country> FIND = new Model.Finder<>(String.class, Country.class);
// not static if you don't want it to be
public List<Country> findAll() {
return FIND.all();
}
}
Which approach you use is getting into opinion territory, but the DAO approach has a lot to recommend it, especially now Play supports DI out of the box. Instead of having a controller that makes hard-coded references to model classes, you can just inject your DAOs.
// direct reference to the Country class
public class ControllerWithActiveRecord extends Controller {
public F.Promise<Result> getAllCountries() {
return F.Promise.promise(() -> Country.findAll())
.map(Json::toJson)
.map(Results::ok);
}
}
Alternate using DI.
public class ControllerWithInjectedDAO extends Controller {
private final CountryDAO countryDAO;
@Inject
public ControllerWithInjectedDAO(final CountryDAO countryDAO) {
this.countryDAO = countryDAO;
}
public F.Promise<Result> getAllCountries() {
return F.Promise.promise(() -> countryDAO.findAll())
.map(Json::toJson)
.map(Results::ok);
}
}
Upvotes: 3