Morphia DAOs

来源:互联网 发布:逆战网络波动异常 编辑:程序博客网 时间:2024/05/22 13:44

参考:

1、Morphia DAOs

2、https://github.com/mongodb/morphia/wiki

In most circumstances you will want to abstract your data access details into a data access layer, commonly referred to as the Data Access Object (DAO) design pattern. Now that you are equipped with an understanding of the inner workings of MongoDB and you know how to build Morphia objects to abstract documents and collections, you should be tempted to build a DAO object just as you would for a relational database. Fortunately Morphia makes that task easier for you by implementing much of the DAO pattern for you.

Morphia defines a DAO interface named com.google.code.morphia.dao.DAO and an implementation class for you to extend for your DAOs:com.google.code.morphia.dao.BasicDAO. The BasicDAO class implements that majority of the methods that you’re going to need to perform data access, including:

  • count(): returns the total count of documents in the collection
  • count(Query<T> q): returns the total count of documents in the collection that match the specified query criteria
  • delete(T entity): deletes a specified document from the collection
  • deleteById(K id): deletes the document with the specified id
  • deleteByQuery(Query<T> q): deletes all documents that match the specified query
  • ensureIndexes(): validates that an index exists for all fields annotated with the @Indexedannotation, and if not it creates them
  • exists(Query<T> q): returns true if there are documents in the collection that match the specified query, otherwise returns false
  • find(): returns all documents in the collection
  • find(Query<T> q): returns all documents that match the specified query
  • findIds(): returns the ids/keys of all documents in the collection
  • findIds(Query<T> q): returns the ids/keys of all documents in the collection that match the specified query
  • findOne(Query<T> q): returns the first document that matches the specified query; use this when you’re searching by a unique field (or if you know you just want the first document)
  • get(K id): returns the document with the specified key
  • getCollection(): returns the underlying DBCollection for the DAO
  • getDatastore(): returns the underlying Datastore for the DAO
  • save(T entity): saves the specified document to the collection
  • update(Query<T> q, UpdateOperations<T> ops): updates all documents in the collection that match the specified query with the operations specified in the UpdateOperations object
  • updateFirst(Query<T> q, UpdateOperations<T> ops): updates the first document in the collection that matches the specified query with the operations specified in the UpdateOperations object

There are other operations defined by the DAO interface, but these are representative of the basic CRUD type operations you want to do with your documents. The BasicDAO class implements all of these methods, which serves as a great starting point for your own DAO classes.

You may notice all of the generics in the method signatures. The DAO interface and BasicDAO class are both built against generics so that you will not need to cast method parameters or results. When you define your DAO class you would do so specifying the specific type, for example:

public class UserDao extends BasicDAO<User,String>

In this example, the UserDao class extends the BasicDAO class, passing it a User class as the type and String as the key type. By doing this we can execute operations like the following:

// Query for all usersList users = userDao.find().asList();// Save a useruserDao.save( dad );

The thing that you may observe about the DAO interface is that it is light on finders: you can find all objects and actually you can apply filters, which I’ll show later, but you have to do it with a knowledge of Morphia. The strategy, therefore, is to extend the BasicDAO class and implement our own custom finders.

Listings 1 and two show two simple DAO implementations, for the User class and Family class, respectively.

Listing 1. UserDao.java

package com.geekcap.informit.mongodb.morphiaexample.dao;import com.geekcap.informit.mongodb.morphiaexample.model.User;import com.google.code.morphia.Morphia;import com.google.code.morphia.dao.BasicDAO;import com.mongodb.Mongo;import java.util.List;public class UserDao extends BasicDAO<User,String>{    public UserDao(Mongo mongo, Morphia morphia)    {        super( mongo, morphia, "morphiaexample" );    }    public List findAll()    {        return ds.find( User.class ).asList();    }    public List findUnderAge( int age )    {        // Filter by age less than the specified age and then order by the age (youngest to oldest)        return ds.find( User.class ).filter( "age < ", age ).order( "age" ).asList();    }}

Listing 2. FamilyDao.java

package com.geekcap.informit.mongodb.morphiaexample.dao;import com.geekcap.informit.mongodb.morphiaexample.model.Family;import com.google.code.morphia.Morphia;import com.google.code.morphia.dao.BasicDAO;import com.mongodb.Mongo;import java.util.List;public class FamilyDao extends BasicDAO<Family,String>{    public FamilyDao(Mongo mongo, Morphia morphia)    {        super( mongo, morphia, "morphiaexample" );    }    public List<Family> findBySurname(String surname)    {        // Execute the query using the underlying datasource        return ds.find( Family.class ).field( "surname" ).equal( surname ).asList();    }}

Both the UserDao and FamilyDao classes extend BasicDAO, passing the appropriate specific type:User and Family, respectively. The constructors accept two objects:

  • Mongo: tells Morphia how to connect to MongoDB (the address and port); this is the same Mongo instance we have been using in this series
  • Morphia: main entry-point into Morphia, which includes the list of classes to map to MongoDB; this is the same Morphia instance we have been using for the past two articles

The BasicDAO class exposes its underlying Datasource, named ds, which you should use for your finders. The UserDao implements a findUnderAge() method that performs the following steps:

  1. Find all instances of the User class
  2. Filter that list of users to include only those users with an age less than the specified age
  3. Order the results by the age (ascending)
  4. Convert the result to a java.util.List
  5. Return the List

Likewise, the FamilyDao class provides a findBySurname() method that finds all Familyinstances whose surname is equal to the specified surname.

Listing 3 shows how to put this together into a working example, which is a rewrite of the example in the previous section that uses the new DAOs.

Listing 3. MorphiaExample.java

package com.geekcap.informit.mongodb.morphiaexample;import com.geekcap.informit.mongodb.morphiaexample.dao.FamilyDao;import com.geekcap.informit.mongodb.morphiaexample.dao.UserDao;import com.geekcap.informit.mongodb.morphiaexample.model.Address;import com.geekcap.informit.mongodb.morphiaexample.model.Family;import com.geekcap.informit.mongodb.morphiaexample.model.User;import com.google.code.morphia.Morphia;import com.mongodb.Mongo;import java.util.List;/** * * @author shaines */public class MorphiaExample{    public static void main( String[] args )    {        try        {            // Create a Mongo instance that points to the MongoDB running on local host            Mongo mongo = new Mongo( "localhost" );            // Create a Morphia object and map our model classes            Morphia morphia = new Morphia();            morphia.map( User.class ).map( Address.class ).map( Family.class );            // Create a DAOs            UserDao userDao = new UserDao( mongo, morphia );            FamilyDao familyDao = new FamilyDao( mongo, morphia );            // Query for all users in the database            System.out.println( "Users before we start:" );            List<User> users = userDao.find().asList();            for( User u : users )            {                System.out.println( "User: " + u );            }            // Create an object to persist to the database            Address address = new Address();            address.setStreet( "123 Some Street" );            address.setCity( "My City" );            address.setState( "ST" );            address.setZipcode( "12345" );            User dad = new User();            dad.setFirstName( "Steven" );            dad.setLastName( "Haines" );            dad.setAge( 39 );            dad.setAddress( address );            // Insert the user into the database            userDao.save( dad );            User mom = new User();            mom.setFirstName( "Linda" );            mom.setLastName( "Haines" );            mom.setAddress( address );            userDao.save( mom );            User son = new User();            son.setFirstName( "Michael" );            son.setLastName( "Haines" );            son.setAge( 9 );            son.setAddress( address );            userDao.save( son );            User daughter = new User();            daughter.setFirstName("Rebecca");            daughter.setLastName("Haines");            daughter.setAge(1);            daughter.setAddress(address);            userDao.save( daughter );            // Build the family            Family family = new Family();            family.setSurname("Haines");            family.setDad(dad);            family.setMom(mom);            family.getChildren().add( son );            family.getChildren().add(daughter);            familyDao.save( family );            // Query for all users in the database            System.out.println( "Users using generic find() method:" );            users = userDao.find().asList();            for( User u : users )            {                System.out.println( "User: " + u );            }            // Alternately:            System.out.println( "Users using custom findAll() method:" );            users = userDao.findAll();            for( User u : users )            {                System.out.println( "User: " + u );            }            // Find children (under 18)            System.out.println( "Children:" );            users = userDao.findUnderAge( 18 );            for( User u : users )            {                System.out.println( "User: " + u );            }            // Use the FamilyDao            System.out.println( "Families using DAO" );            List<Family> families = familyDao.findBySurname( "Haines" );            for( Family f : families )            {                System.out.println( "Family: " + f.getSurname() );                System.out.println( "- Dad: " + f.getDad() );                System.out.println( "- Mom: " + f.getMom() );                List<User> children = f.getChildren();                System.out.println( "Children (" + children.size() + ")" );                for( User child : children ) {                    System.out.println( "\t" + child );                }            }        }        catch( Exception e )        {            e.printStackTrace();        }    }}

Listing 3 first creates a Mongo instance that points to a MongoDB instance running on the localhost. Next it creates a Morphia instance and maps the User, Address, and Family classes to it for persistence.

It then creates UserDao and FamilyDao instances, passing it the Mongo and Morphia instances.

The first query, which shows all User documents in the collection, does so using the explicit Morphia find().asList() instead of the findAll() method, just as an example. The alternative is shown later in the source code.

Next, listing 3 creates the User instances and Family instance, and uses the DAOs save()methods to persist those documents. There are a couple examples of querying for all users, both using the Morphia-specific notation as well as the findAll() method. Next, you can see a query for all children (age under 18), which only has the bug that I did not set my wife’s age, so she gets the age “0” which includes her in the list (but I am not going to add her age to an example, I don’t want that kind of trouble!)

Finally, listing 3 uses the FamilyDao to query for all families with the surname “Haines”, which will include only one family the first time this is run [md] there is no clean up code so you’ll see more and more Haines families added each time you execute this example.


0 0
原创粉丝点击