package com.alvazan.orm.api.base; import java.util.List; import com.alvazan.orm.api.z3api.NoSqlTypedSession; import com.alvazan.orm.api.z5api.NoSqlSession; import com.alvazan.orm.api.z8spi.KeyValue; import com.alvazan.orm.api.z8spi.iter.Cursor; import com.alvazan.orm.layer0.base.BaseEntityManagerImpl; import com.google.inject.ImplementedBy; @ImplementedBy(BaseEntityManagerImpl.class) public interface NoSqlEntityManager { /** * Retrieve underlying interface to write raw columns to. This works the same as the NoSqlEntityManager * in that you must call flush to execute all the calls to persist, but is the raw interface. * * @return The raw session that all the providers implement */ public NoSqlSession getSession(); /** * Retrieve a special interface that deals with rows and still does indexing when you persist/remove rows. This interface is * used when inserting unknown datasets into a nosql store where you want indexing to be automatic still. Generally used * for research datasets where a user uploading data is telling you the columns and what columns to index for him. */ public NoSqlTypedSession getTypedSession(); /** * Creates a 'Remove' action in the write cache that will be sent to nosql store when flush is called. This * method also creates RemoveIndex actions that will be sent when flush is called as well. * @param entity Entity to be removed */ public void remove(Object entity); /** * Creates a 'Persist' action in the write cache that will be sent to nosql store when flush is called. This method * also creates PersistIndex and RemoveIndex actions if you have indexed fields and the index needs to be modified * and those are sent when flush is called as well. * @param entity Entity to be added */ public void put(Object entity); /** * MUST be used for entity with MANUAL key generation. To prevent index corruption, you MUST tell us if this is an * insert OR an update. If it is an update, entity will be checked if it was read in first(it needs to be read in * first before updating so we can properly remove from index and add to it). * @param entity Entity to be added * @param isInsert */ public void put(Object entity, boolean isInsert); //public void putAll(List<Object> entities); /** * This is NOSql so do NOT use find in a loop!!!! Use findAll instead and then loop over the items. * If your network latency is 5 ms, looking up 1000 records will cost you 5 seconds in a loop(plus processing time) * where findAll will cost you 5 ms (plus processing time). ie. findAll is better for looking up lots of entities!! * * @param entityType Entity for which keys need to be find * @param key Rowkey of the Object * @return The object of that Entity for which a rowkey is found */ public <T> T find(Class<T> entityType, Object key); /** * An efficient operation in nosql for retrieving many entities at once. This is the operation * we use very frequently in the ORM for OneToMany operations so we can fetch all your relations * extremely fast(as they are fetched in parallel not series so 5ms network latency for 1000 objects * is not 5 seconds but just 5ms as it is done in parallel). * * @param entityType Entity for which keys need to be find * @param keys List of the rowkeys * @return List of the Objects of EntityType having those keys */ public <T> List<KeyValue<T>> findAllList(Class<T> entityType, List<? extends Object> keys); /** * @param entityType Entity for which keys need to be find * @param keys List of the rowkeys * @return Cursor of the Objects of EntityType having those keys */ public <T> Cursor<KeyValue<T>> findAll(Class<T> entityType, Iterable<? extends Object> keys); /** * Just like hibernate getReference call. Use this when you have an id of an object and * have another object like User and you want to call User.addAccount(Account account). First * get a fake account with Account account = mgr.getReference(Account.class, accountId) and * then set the fake account into the User object and save the user object. The User is now * related to the account with that accountId and you did not have to hit the database to * read in the account. Again, this is the same as JPA getReference method. * @param entityType Entity for which keys need to be find * @param key * @return The object of that EntityType having key as rowkey */ public <T> T getReference(Class<T> entityType, Object key); /** * Unlike RDBMS, there are no transactions, BUT all the calls to putAll and put are cached * in-memory until flush is called. This allows us to easily queue up all writes to * the datastore and * <ol> * <ul> Send all writes as one to incur less i/o over the network * <ul> not block your thread for every put/putAll that is called(only block on writing all during flush) * <ul> time how long all the writes take. * </ol> * * It is more likely to keep things more consistent */ public void flush(); /** * Clears the cache in situations where you just load way tooooooo much stuff and need to free up * some memory. */ public void clear(); public <T> Query<T> createNamedQuery(Class<T> forEntity, String namedQuery); /** * In certain cases where you have a bi-directional association, you need a primary key in * the children before you can save the parent. ie. If you have an Account that has a list * of Activity and an Activity with an Account, the proper way to code this is such * * <ol> * <li>Account acc = new Account() </li> * <li>entityManager.fillInWithKey(acc) </li> * <li>Activity act1 = new Activity() </li> * <li>act1.setAccount(acc) </li> * <li>entityManager.put(act1) //act1 key is generated and filled in here</li> * <li>acc.addActivity(act1) //here account has an act1 WITH a key</li> * <li>entityManager.put(acc) </li> * </ol> * * @param acc */ public void fillInWithKey(Object acc); public MetaLayer getMeta(); /** * This is a convenience method for in memory database and cassandra database * so that you can run unit tests against in-memory (and run the same unit tests * against cassandra live as well). * * @param recreateMeta - It is usually a good idea to recreate the meta objects in * the database after clearing it as the more raw layers depend on the meta. The ORM * itself created the original meta so it really doesn't care about the meta in the * database */ public void clearDatabase(boolean recreateMeta); /** * This method should only be used on small count CF's(less than 5 million or so). For large count CF's, use map/reduce. * Be away that millions of rows can take a while to read so this is usually reserved for longer operations. * * Returns all rows in a concrete CF. If your CF is inheritance(many entity types in one CF), then your baseEntty * should be the super class. If you have many virtual tables in a CF(and you have inheritance in some virtual tables or not), * then your baseEntity should be Object.class. This method will return the proper types of entitys. For inheritance base, * it will return the types based on each rows discriminator column. For virtual tables, it looks at each row and returns * the type based on that virtual table so each row coming back would be a different type. * * @param baseEntity * @param cf * @param batchSize * @return A Cursor */ public <T> Cursor<T> allRows(Class<T> baseEntity, String cf, int batchSize); }