SimpleStore is customizable persistence framework. It defines interfaces for Transparent Persistence and provides reference implementation. It designed to store objects in Transactional resource like RDMS, but can be used with any kind of storage. It is two storage types in reference implementation: RDMS and BTree file from JDBM project. "Transparent" means no Query Language, Code Generation or Storage Specific API. Persistent Object doe's not extend any specific class and doe's not implement some interface from SimpleStore API. Users code can use it, but must not depend on it( Downcast ). It is recommended to "hide" PersistentManager and internal Transactions too. Use Facade and Factory design patterns to make your code clean. It is useful if you will decide to make your objects Distributed. See Apache's AltRMI for more information on Transparent Distribution implementation.
You can use it to implement persistency aspect in your web application, or object model, you can use it as service for your server like EOB or EJB (CMP,BMP). You can extend it and implement your persistence framework or for some like JDO. SimpleStore is Open Source and you can use it in commercial projects, see Apache license for details.
This interface is used to implement well known Factory design pattern it used to setup singleton
PersitenceManager
instanse.PersitenceManager
is the most specific
interface in your code:
DBPersistenceManagerFactory factory = new DBPersistenceManagerFactory(); factory.setDriver("org.hsqldb.jdbcDriver"); factory.setUrl("jdbc:hsqldb:sample"); factory.setUser("sa"); factory.setPassword(""); factory.setMaxConnections(1); factory.setMetaResource("org/apache/commons/simplestore/storage.xml"); PersitenceManager pm = factory.getPersistenceManager();this example setups
PersitenceManager
to use RDMS as storage.
PersitenceManager
is factory for your beans and transactions, Transaction
is the
last interface you need to know from SimpleStore if you not going to extend SimpleStore.
You don't need to extend any specific Class or implement internal persistence interfaces, y
ou don't need any code generator. Just design your object model, use interfaces and classes,
SimpleStore will implement persistence aspect for you, but you still need some "Metadata"
it is very trivial xml file, but it can be written using optional tags or
generated later. Start to design beans:
public abstract class Message{ public MessageImpl(){} public void addReply( Message m ) { m.setSubmitted(new java.util.Date()); m.setParent(this); } public int numberOfReplies() { return getReplies().size(); } public abstract java.util.Collection getReplies(); public abstract Date getSubmitted(); public abstract void setSubmitted(Date v); public abstract String getContents(); public abstract void setContents(String v); public abstract String getEmail(); public abstract void setEmail(String v); public abstract String getName(); public abstract void setName(String v); public abstract String getSubject(); public abstract void setSubject(String v); public abstract void setParent( Message parent ); }This is persistent bean from Jakarta Velocity demo, it is recommended framework for web applications. All abstract methods are implemented by SimpleStore,
PersitenceManager
returns this implementation:
PersitenceManager pm = factory.getPersistenceManager(); Transaction transaction = pm.getTransaction(); transaction.begin(); Message parent = pm.findInstance(Message.class,parentOid); Message msg = pm.createInstance(Message.class); msg.setSubject(subject); msg.setEmail(email); msg.setName(name); msg.setContents(contents); parent.addReplay(msg); transaction.commit();At last you will need some metadata it helps simplestore to implement your beans:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE storage> <storage> <mclass id="Message" name="MESSAGE"> <field id="parent" name="parent"> <reference mclass="Message"/> </field> <field id="replies"> <reference mclass="Message" field="parent"/> </field> </mclass> </storage>
SimpleStore supports only atomic persistence operations, All operations must be in transaction context:
Transaction transaction = pm.getTransaction(); transaction.begin(); //.......................... // operations //.......................... transaction.commit();// or transaction.rollback();It is fragment from SimpleStore test, it demonstrates rollback:
transaction.begin(); TestPersistentClassType object = (TestPersistentClassType) i.next(); String val = object.getStrVal(); object.setStrVal( i + ""); transaction.rollback(); transaction.begin(); assertEquals("After rollback ", val, object.getStrVal()); transaction.commit();
All persistent objects have OID, it is recomended to use Serializable
Object for OID,
reference implementaion uses java.lang.Long and default (Random) generator.
It is single persistent instance in SimpleStore with concreate OID.
Next always evaluates to true :
if( pm.findInstance(Message.class, pm.getOID( msg ) ) == msg ){ .................................. }OID is managed by framework and it is no way to change it for persistent object. SimpleStore overrides
int hashCode()
and boolean equals(Object obj)
methods in class Object. if( pm.findInstance(Message.class, pm.getOID( msg ) ).equals( msg ) ){ .................................. }
It is to methods in PersistenceManager for persitent object state.
boolean isNew(Object p)
returns true
if object is returned from
Object createInstance(Class cls)
in current transaction.
boolean isDeleted(Object p)
returns
true
if object is deleted in any transacton. Use void removeInstance(Object p)
to delete persistent object. Managed methods throws
java.lang.IllegalStateException
if deleted object is accessed inside or outside transaction.
Cache is transparent for SimpleStore user. It used for optimizations and reachability management, but it is "invisible" in code. It is recomended to use default implementation.
Metadada is used to define validation rules.
Validator
is custom object see javadoc for more information on
Validator
interface,
and sample NotNull
validator implementation. Persistent object implementation throws
ValidationException
if registread validator returns false for managed property value.
<field id='propertyName' name='fieldName'> <validator id='ClassName'/> </field>
Custom interceptors used for security checks. SimpleStore doe's not define any specific Permissions and doe's no security checks. Read more about customizations see Developers Guide .