This is an example for future reference and I'm not going to comment futher on it than what's already in the comments.
package experiment.morphia; import org.bson.types.ObjectId; import com.google.code.morphia.annotations.Entity; import com.google.code.morphia.annotations.Id; @Entity public class Location { @Id private ObjectId id; private Integer stars; private String street; private String city; private String state; private String zipcode; private String country; public Location() {} public Location( Integer stars, String street, String city, String state, String zipcode, String county ) { this.stars = stars; this.street = street; this.city = city; this.state = state; this.zipcode = zipcode; this.country = county; } public ObjectId getId() { return this.id; } public void setId( ObjectId id ) { this.id = id; } public Integer getStars() { return this.stars; } public void setStars( Integer stars ) { this.stars = stars; } public String getStreet() { return this.street; } public void setStreet( String street ) { this.street = street; } public String getCity() { return this.city; } public void setCity( String city ) { this.city = city; } public String getState() { return this.state; } public void setState( String state ) { this.state = state; } public String getZipcode() { return this.zipcode; } public void setZipcode( String zipcode ) { this.zipcode = zipcode; } public String getCountry() { return this.country; } public void setCountry( String country ) { this.country = country; } public String toString() { String string = ""; if( this.id != null ) string = "[" + this.id + "] "; if( this.stars != 1 ) string += this.stars + " stars "; else string += this.stars + " star "; string += this.street + " " + this.city + " "; if( this.state != null ) string += this.state + " "; string += this.country + " " + this.zipcode; return string; } }
package experiment.morphia; import java.util.ArrayList; import org.bson.types.ObjectId; import com.google.code.morphia.annotations.Embedded; import com.google.code.morphia.annotations.Entity; import com.google.code.morphia.annotations.Id; @Entity( noClassnameStored=true ) public class Hotel { @Id private ObjectId id; private String name; private int stars; public Hotel() {} public Hotel( String name, int stars ) { this.name = name; this.stars = stars; } @Embedded private ArrayList< Location > locations; public ObjectId getId() { return id; } public void setId( ObjectId id ) { this.id = id; } public String getName() { return name; } public void setName( String name ) { this.name = name; } public int getStars() { return stars; } public void setStars( int stars ) { this.stars = stars; } public ArrayList< Location > getLocations() { return locations; } public void setLocations( ArrayList< Location > locations ) { this.locations = locations; } public String toString() { String string = this.name + ", " + this.stars + " stars " + "[" + this.id + "]\n"; for( Location location : this.locations ) string += " " + location.toString() + "\n"; return string; } }
package experiment.morphia; import java.util.List; import util.Implementor; import com.google.code.morphia.Datastore; import com.google.code.morphia.dao.BasicDAO; /** * Do database stuff here... */ @Implementor( HotelDao.class ) public class HotelDao extends BasicDAO< Hotel, String > { /* The Datastore is a wrapper around the MongoDB Java driver and is used to manage * entities in MongoDB. */ Datastore datastore; // inject this manually for now... public HotelDao() { super( HotelTest.getMongo(), HotelTest.getMorphia(), "hotels" ); this.datastore = HotelTest.getDatastore(); } public Hotel create( Hotel hotel ) { this.datastore.save( hotel ); return hotel; } public List< Hotel > read() { return this.datastore.find( Hotel.class ).asList(); } public List< Hotel > read( String query, String value ) { if( query == null && value == null ) return this.datastore.find( Hotel.class ).asList(); return this.datastore.find( Hotel.class, query, value ).asList(); } public List< Hotel > read( String query, Integer value ) { if( query == null && value == null ) return this.datastore.find( Hotel.class ).asList(); return this.datastore.find( Hotel.class, query, value ).asList(); } public void update( Hotel hotel ) { this.datastore.merge( hotel ); } public void remove( Hotel hotel ) { this.datastore.delete( hotel ); } }
package experiment.morphia; import java.util.List; import util.Implementor; import util.ServiceLocator; /** * Do business logic here... */ @Implementor( HotelManager.class ) public class HotelManager { private HotelDao hotelDao = ServiceLocator.get( HotelDao.class ); public Hotel create( Hotel hotel ) { return hotelDao.create( hotel ); } public List< Hotel > read() { return hotelDao.read(); } public List< Hotel > read( String query, String value ) { return hotelDao.read( query, value ); } public List< Hotel > read( String query, Integer value ) { return hotelDao.read( query, value ); } public void update( Hotel hotel ) { hotelDao.update( hotel ); } public void delete( Hotel hotel ) { hotelDao.remove( hotel ); } }
package experiment.morphia; import java.util.List; import util.ServiceLocator; /** * Do web service here (except that this isn't a web service, but a squirrel cage)... */ public class HotelService { private HotelManager hotelManager = ServiceLocator.get( HotelManager.class ); public Hotel create( Hotel hotel ) { return this.hotelManager.create( hotel ); } public List< Hotel > read() { return this.hotelManager.read(); } public List< Hotel > read( String query, String value ) { return this.hotelManager.read( query, value ); } public List< Hotel > read( String query, Integer value ) { return this.hotelManager.read( query, value ); } public void update( Hotel hotel ) { this.hotelManager.update( hotel ); } public void delete( Hotel hotel ) { this.hotelManager.delete( hotel ); } }
package experiment.morphia; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; import java.util.Random; import org.apache.log4j.Logger; import util.ServiceLocator; import com.google.code.morphia.Datastore; import com.google.code.morphia.Morphia; import com.mongodb.BasicDBObject; import com.mongodb.DB; import com.mongodb.DBCollection; import com.mongodb.Mongo; import com.mongodb.MongoException; @SuppressWarnings( "unused" ) public class HotelTest { public static Logger log = Logger.getLogger( HotelTest.class ); private static Mongo mongodb; private static DB database; private static Morphia morphia; private static Datastore datastore; private static final String DATABASE_NAME = "hotels"; private static final String HOTEL_NAME = "Hotel Hyatt"; private static final String COLLECTION_NAME = Hotel.class.getSimpleName(); public static Mongo getMongo() { return mongodb; } public static Morphia getMorphia() { return morphia; } public static Datastore getDatastore() { return datastore; } /** * Initialize MongoDB and Morphia for our purposes. */ private static void initializeMongoAndMorphia() { try { mongodb = new Mongo( "localhost", 27017 ); } catch( UnknownHostException e ) { log.error( "MongoDB host not found" ); } catch( MongoException e ) { log.error( "Error attempting MongoDB connection for hotels", e ); } database = mongodb.getDB( DATABASE_NAME ); morphia = new Morphia(); datastore = morphia.createDatastore( mongodb, DATABASE_NAME ); database.dropDatabase(); // drop any fodder left in from last time... morphia.map( Hotel.class ).map( Location.class ); } /** * Clean up the document we put in here last time (works assuming the hotel name hasn't * changed) so that we start fresh. * * @param key field name ("name"). * @param value hotel name. */ private static void deleteDocumentFromCollection( String key, String value ) { DBCollection collection = database.getCollection( COLLECTION_NAME ); try { BasicDBObject dbo = new BasicDBObject(); dbo.append( key, value ); collection.remove( dbo ); } catch( MongoException e ) { log.debug( "Ignored: " + e.getMessage() ); } } public static void main( String[] args ) { initializeMongoAndMorphia(); HotelService service = new HotelService(); // CREATE /* Create a random number of hotel chains and put them into the database. */ Long milliseconds = System.currentTimeMillis(); Random generator = new Random( milliseconds ); int hotelsCount = HotelFodder.getHotelCount(); // always ensure we've got at least one hotel chain... int which = generator.nextInt( hotelsCount ); if( which == 0 ) which = 1; if( which == 1 ) System.out.println( "Creating a hotel chain..." ); else System.out.println( "Creating " + which + " hotel chains..." ); while( which > 0 ) { Hotel h = service.create( HotelFodder.newHotel() ); which--; } /* If I move the stars to the individual locations, I query this way: * > db.Hotel.find( { "locations" : { $elemMatch : { "stars" : { $gt : 2 } } } } ).count(); * However, this still gives me back the whole Hotel document including the lesser-star * hotel locations. * * This came up as I was assigning stars to locations instead of hotel chains. I stopped * short of extending this change to what's going on here since it's isn't relevant and I * don't want to continue to play with it. */ // READ List< Hotel > fourStarChains = service.read( "stars >", 2 ); System.out.println( "Looking for 3-star or better hotels..." ); Hotel h_c = null; int count = 0; for( Hotel hc : fourStarChains ) { System.out.println( hc ); count++; } if( count == 0 ) System.out.println( "(There were no 3-star or better hotels.)" ); } }
package experiment.morphia; public class HotelTuple { String hotelName; Integer stars; public HotelTuple( String name, Integer stars ) { this.hotelName = name; this.stars = stars; } }
package experiment.morphia; import java.util.ArrayList; import java.util.Random; public class HotelFodder { private static boolean once = false; private static Random generator1; private static Random generator2; private static Random generator3; private static ArrayList< Location > locations; private static ArrayList< HotelTuple > hotelNamesAndStars; private static void initializeAddresses() { locations = new ArrayList< Location >(); locations.add( new Location( 2, "3222 South 525 West", "Bountiful", "UT", "84101", "US" ) ); locations.add( new Location( 2, "59, rue Albert Premier", "Bezons", null, "95057", "FR" ) ); locations.add( new Location( 4, "Miquelallee Straß, 23", "Frankfurt", null, "65936", "DE" ) ); locations.add( new Location( 1, "1313 Mockingbird Lane", "Mockingbird Heights", "CA", "06660", "US" ) ); locations.add( new Location( 5, "12345 Bedford Drive", "Beverly Hills", "CA", "90210", "US" ) ); locations.add( new Location( 4, "1778 Oregon Avenue", "Provo", "UT", "84606", "US" ) ); locations.add( new Location( 4, "23, rue du Puits", "Pagny-la-Blanche-Côte", null, "55010", "FR" ) ); locations.add( new Location( 4, "48 Cicada Drive", "Boise", "ID", "83702", "US" ) ); locations.add( new Location( 5, "5, Boulevard des Capucines", "Paris", null, "75008", "FR" ) ); } private static void initializeHotelNamesAndStars() { hotelNamesAndStars = new ArrayList< HotelTuple >(); hotelNamesAndStars.add( new HotelTuple( "Hyatt Hotel", generator3.nextInt( 5 ) + 1 ) ); hotelNamesAndStars.add( new HotelTuple( "Bayside Arms", generator3.nextInt( 5 ) + 1 ) ); hotelNamesAndStars.add( new HotelTuple( "Hotel California", generator3.nextInt( 5 ) + 1 ) ); hotelNamesAndStars.add( new HotelTuple( "Bates Motel", 0 ) ); hotelNamesAndStars.add( new HotelTuple( "Purple Hives", generator3.nextInt( 5 ) + 1 ) ); hotelNamesAndStars.add( new HotelTuple( "Sofitel", generator3.nextInt( 5 ) + 1 ) ); hotelNamesAndStars.add( new HotelTuple( "Novotel", generator3.nextInt( 5 ) + 1 ) ); hotelNamesAndStars.add( new HotelTuple( "Marriott Courtyard", generator3.nextInt( 5 ) + 1 ) ); hotelNamesAndStars.add( new HotelTuple( "Holiday Inn", generator3.nextInt( 5 ) + 1 ) ); hotelNamesAndStars.add( new HotelTuple( "Embassey Suites", generator3.nextInt( 5 ) + 1 ) ); } public static void initializeFodder() { Long milliseconds = System.currentTimeMillis(); if( once ) return; generator1 = new Random( milliseconds ); generator2 = new Random( milliseconds + 89 ); generator3 = new Random( milliseconds + 76 ); initializeAddresses(); initializeHotelNamesAndStars(); once = true; } public static int getLocationCount() { initializeFodder(); return locations.size(); } public static int getHotelCount() { initializeFodder(); return hotelNamesAndStars.size(); } /** * Generate a new hotel chain with a random name, stars and set of locations. * * @return one new Hotel chain. */ public static Hotel newHotel() { initializeFodder(); int locationCount = getLocationCount(); int hotelCount = getHotelCount(); HotelTuple tuple = hotelNamesAndStars.get( generator1.nextInt( hotelCount ) ); Hotel hotel = new Hotel( tuple.hotelName, tuple.stars ); ArrayList< Location > as = new ArrayList< Location >(); // always ensure we've got at least one location in a hotel chain... int howMany = generator2.nextInt( locationCount ); if( howMany == 0 ) howMany = 1; int next = generator3.nextInt( locationCount ); while( howMany > 0 ) { if( next < 0 ) next = locationCount - 1; Location location = locations.get( next ); as.add( location ); howMany--; next--; } hotel.setLocations( as ); return hotel; } public static void main( String[] args ) { Hotel hotel = newHotel(); System.out.println( hotel.toString() ); } }