Apache Cayenne for WO Devs
-
Upload
wo-community -
Category
Technology
-
view
2.714 -
download
5
Transcript of Apache Cayenne for WO Devs
Apache Cayenne for WO Devsby Andrus Adamchik, ObjectStyle LLC
• 2001 - inception
• 2002 - first “alpha” release and a large production deployment
• 2006 - Cayenne becomes “Apache Cayenne”
• still active and evolving...
History
• A top-level project at Apache Software Foundation
• 17 committers
• 9 PMC members
• Majority of PMC have WO/EOF background
• ... not all are active ...
Project Structure and Governance
Releases
• 3.0 - current stable
• 3.1 - Beta, recommended for all users
• 3.2 - in development; used for this presentation
Mapping Structure
Separate DB and Object Layers
DB layer: DbEntities containing DbAttributes and connected with DbRlationships
• DbEntity - models a table or a view
• DbAttribute - models a column
• DbRelationship - models PK/FK relationship going in one direction
Object layer: ObjEntities containing ObjAttributes and connected with ObjRlationships
• ObjEntity - models a persistent Java class
• ObjAttribute - models a “simple” property of a Java class
• ObjRelationship - models a “relationship” property, i.e. a property of type that is another ObjEntity (can be to-one or to-many). Going in one direction only.
Connecting Obj to Db Layer
• ObjEntity references a single DbEntity
Connecting Obj to Db Layer
• (simple attribute) ObjAttribute references a DbAttribute
• (flattened attribute) ObjAttribute references a “dbpath” across one or more DbRelationships ending with an attribute
Connecting Obj to Db Layer
• (simple relationship) ObjRelationship references a DbRelationship
• (flattened relationship) ObjRelationship references a “dbpath” across 2 or more DbRelationships
CayenneModeler
Cross-platform natively-packaged tool to work on Cayenne mapping projects
Tools > Reengineer Database Schema
Tools > Generate Database Schema
Tools > Migrate Schema
Tools > Generate Classes
Tools > Import EOModel
Modeling Workflow
Challenge - keeping these in sync:
Maven and Ant Tools
• cgen - generates classes from the ORM model
• cdbimport - generates model from DB
• cdbgen - generates DB from the model
Modeler Workflow... on project start:
Modeler Workflow... on each iteration:
Modeler-Free Workflow... on project start:
Modeler-Free Workflow... on each iteration:
Modeler-free Workflow - Maven
<plugin> <groupId>org.apache.cayenne.plugins</groupId> <artifactId>maven-cayenne-plugin</artifactId> <configuration> <map>${project.basedir}/src/main/resources/my.map.xml</map> <destDir>${project.basedir}/src/main/java</destDir> <defaultPackage>com.example.cayenne</defaultPackage> <superPkg>com.example.cayenne.auto</superPkg> <url>jdbc:mysql://127.0.0.1/mydb</url> <username>user</username> <password>secret</password> <driver>com.mysql.jdbc.Driver</driver> <excludeTables>migrations</excludeTables> </configuration> <executions> <execution> <id>default-cli</id> <goals> <goal>cdbimport</goal> <goal>cgen</goal> </goals> </execution> </executions></plugin>
When to use Modeler-free workflow?
• when DB objects have sane naming
• when DB has FK constraints defined
• when no per-entity model tweaking is needed (optimistic locking, PK generation, exclusion of attributes, etc.)
Writing Apps with Cayenne
Starting Cayenne
// create reusable ‘runtime’ instanceServerRuntime runtime = new ServerRuntime("cayenne-myproject.xml");
Stopping Cayenne
runtime.shutdown();
ObjectContext
Obtaining ObjectContext
// regular contextObjectContext context = runtime.newContext();
// nested contextObjectContext nestedContext = runtime.newContext(context);
ObjectContext
• An isolated “session” to access Cayenne
• Has its own copy of each object
• Doesn’t require explicit shutdown (can be simply thrown away when no longer in use)
• Can be serialized
• Can be scoped differently based on app requirements
Under the Hood ServerRuntime is a DI container
Overriding a DI service to create custom ObjectContexts
public class MyContextFactory implements ObjectContextFactory { @Inject private EventManager eventManager;
@Override public ObjectContext createContext() { return new MyContext(eventManager); } @Override public ObjectContext createContext(DataChannel parent) { return new MyContext(parent, eventManager); }}
Module myModule = new Module() { @Override public void configure(Binder binder) { binder.bind(ObjectContextFactory.class).to(MyContextFactory.class); }};
// override built-in services via a custom moduleServerRuntime runtime = new ServerRuntime("cayenne-myproject.xml", myModule);
DI Container Highlights
• Very small - 40K
• Intended to make Cayenne runtime modular and customizable
• Does not interfere with or care about application DI
• Can be used outside Cayenne, but this was not the goal
Queries
SelectQuery
• Most commonly used query
• Data rows option
• Fetch offset/limit
• Prefetching (separate strategies)
• Result caching, pagination
• Iterated result
SelectQuery
ObjectContext context = ...
SelectQuery<Artist> query = new SelectQuery<Artist>(Artist.class);List<Artist> allArtists = context.select(query);
SelectQuery with qualifier
ObjectContext context = ...
SelectQuery<Artist> query = new SelectQuery<Artist>(Artist.class);query.andQualifier(Artist.NAME.like("A%"));query.andQualifier(Artist.DATE_OF_BIRTH.lt(new Date()));
List<Artist> someArtists = context.select(query);
INFO: SELECT t0.NAME, t0.DATE_OF_BIRTH, t0.ID FROM ARTIST t0 WHERE (t0.NAME LIKE ?) AND (t0.DATE_OF_BIRTH < ?) [bind: 1->NAME:'A%', 2->DATE_OF_BIRTH:'2013-05-09 20:51:12.759']INFO: === returned 1 row. - took 2 ms.
Other Queries
• EJBQLQuery
• SQLTemplate
• ProcedureQuery
• ObjectIdQuery, RelationshipQuery, QueryChain
• Custom queries...
Caching Query Results
Can be used with any Query and is fairly transparent
SelectQuery<Artist> query = new SelectQuery<Artist>(Artist.class);query.andQualifier(Artist.ARTIST_NAME.like("A%"));
// This is all it takes to cache the result. // There’s no need to calculate a cache key. // Cayenne will do that for youquery.useLocalCache();
List<Artist> someArtists = context.select(query);
Lifecycle Events
• PostAdd, PrePersist, PreUpdate, PreRemove, PostPersist, PostUpdate, PostRemove, PostLoad
• Persistent objects can declare callback methods to be notified about own events
• Any non-persistent object can be a listener for various entity events.
Lifecycle Events
• Higher-level “workflows” are implemented by matching entities with listeners using custom annotations and providing operation context via DataChannelFilter
Remote Object Persistence (ROP)
ROP Highlights
• Same as nested ObjectContext, only child context lives in a remote JVM
• Full ORM API and behavior available on the client:
• Queries, lazy relationships, caching, pagination, etc.
• Client objects based on the same model as server
• Client objects are using a different superclass
Other ORM Choices
• Hibernate
• JPA
Cayenne Difference - Object Design
Others enhanced/proxied POJO ORM Annotations
Cayenne framework superclass annotations used for other things
Advantage
faster startup times “WYSIWYG” objects generic persistent objects less code clutter
Cayenne Difference - Runtime
Others explicit transactions
Cayenne on-demand implicit transactions
Advantage less code, cleaner code seamless relationship navigation
EOF Analogies
“All characters and events – even those based on real people – are entirely fictional.”
Persistent Objects
• EOEnterpriseObject : Persistent, DataObject, CayenneDataObject
• EOGlobalID : ObjectId
• EOGenericRecord : CayenneDataObject
Mapping
• EOModel : DataMap
• EOModelGroup : EntityResolver
• EOEntity: DbEntity / ObjEntity
Query
• EOFetchSpecification : SelectQuery
• EOQualifier : Expression
• EOSortOrdering : Ordering
Runtime
• EOEditingContext : ObjectContext
• EOAdapter : DataNode
• JDBCPlugin : DbAdapter
Cayenne != EOF
What You Might Miss from EOF
• Quirky Vertical Inheritance
• No Horizontal Inheritance
• No prototypes
• No Eclipse plugin
What You Get in Return• Multithreading
• IDE-independent Modeler
• Internal dependency injection
• Query abstraction beyond SelectQuery
• EJBQL and aggregated queries
• Iterated query
• Transparent Query result cache
• Transparent Query result pagination
• Auto-increment PK
• Automated DB type detection
• Prefetch strategies
• Lifecycle events
A chance to influence things!