What I've been developing is a high performance, easy-to-use Java interface to NDB that bypasses the MySQL Server and instead goes directly to the native NDB API. I've used a Domain Object Model similar to Hibernate, JDO, and JPA.
I'd like to work on this in Apache and would like to discuss the opportunities with folks at ApacheCon. If this looks interesting, please let me know. I'll post a proposal to the incubator wiki if there is positive feedback.
All work is done through a Session instance, which is the primary application interface between the user and the database. The user acquires a Session instance from a SessionFactory, which in turn is obtained via Services lookup. The factory is configured via Properties, such as:
com.mysql.clusterj.connectstring=127.0.0.1:9311 com.mysql.clusterj.mysqld=localhost com.mysql.clusterj.username=root com.mysql.clusterj.password= com.mysql.clusterj.testDatabase=testThe Session interface provides methods for insert, delete, query, and update. A separate Transaction interface provides methods for transaction completion. The Transaction provides isActive(), begin(), commit(), rollback(), setRollbackOnly(), and getRollbackOnly() methods.
Two modes of operation are implemented: autocommit on/off. • With autocommit off:• when a mutating operation is invoked on the Session, the Transaction must be active, or an exception is thrown; and • when a non-mutating operation is invoked when a Transaction is not active, a transaction is begun and committed for the purpose of executing the operation.
• With autocommit on:• when a mutating operation is invoked on the Session, the Transaction is begun and committed for the operation; and • when a non-mutating operation is invoked, a transaction is begun and committed for the purpose of executing the operation.
Deferred operation is proposed. By setting the flag com.mysql.clusterj.defer.changes, mutating operations are deferred until the Transaction is committed or the state is flushed via Session.flush(). With defer changes, find() operations return a proxy instance whose persistent properties are not initialized until the user asks for one of them. Inserted instances are not actually sent to the back end until the session is flushed. Deleted instances are not deleted until the session is flushed. Queries return a Results instance that is not instantiated until the user asks for a property of an instance.
For ease of use, users can define JavaBeans-pattern interfaces to represent data, with annotations to declare database metadata:
@PersistenceCapable(table="t_basic") interface Employee { @PrimaryKey int getId(); void setId(int id); String getName(); void setName(String name); }The Session.newInstance(Class cls) is a factory for instances that implement the user interface as well as a high-performance data access path for the implementation. For JPA/JDO StorageManager, the high- performance data access path is used.
// Sample code to create a SessionFactory from a properties instance protected void createSessionFactory() { loadProperties(); if (sessionFactory == null) { sessionFactory = ClusterJHelper.getSessionFactory(props); } loadSchema(); } // Sample code to delete and create instances public void localSetUp() { createSessionFactory(); session = sessionFactory.getSession(); createEmployeeInstances(NUMBER_TO_INSERT); tx = session.currentTransaction(); int count = 0; for (int i = 0; i < NUMBER_TO_INSERT; ++i) { tx.begin(); session.deletePersistent(employees.get(i)); try { tx.commit(); ++count; } catch (Exception ex) {// ignore exceptions -- might not be any instances to delete
} } addTearDownClasses(Employee.class); // System.out.println("Deleted " + count + " instances."); } public void testInsert() { tx = session.currentTransaction(); tx.begin(); for (int i = 0; i < NUMBER_TO_INSERT; ++i) { // must be done with an active transaction session.makePersistent(employees.get(i)); } tx.commit(); } } // Sample query code public void primaryKeyGreaterThanQuery() { tx.begin(); // QueryBuilder is the sessionFactory for queries QueryBuilder builder = session.getQueryBuilder(); // DomainObject is the main interfaceDomainObject dobj = builder.createQueryDefinition(Employee.class);
// parameter name PredicateOperand param = dobj.param("id"); // property name PredicateOperand column = dobj.get("id"); // compare the column with the parameter Predicate compare = column.greaterThan(param); // set the where clause into the query dobj.where(compare); // create a query instance Query query = session.createQuery(dobj); // set the parameter values query.setParameter("id", 6); // get the results List<Employee> results = query.getResultList(); // consistency check the results consistencyCheck(results); // verify we got the right instances Set<Integer> expected = new HashSet<Integer>(); expected.add(7); expected.add(8); expected.add(9); Set<Integer> actual = new HashSet<Integer>(); for (Employee emp: results) { actual.add(emp.getId()); } errorIfNotEqual("Wrong employee ids returned from query: ", expected, actual); tx.commit(); } Craig L Russell Architect, Sun Java Enterprise System http://db.apache.org/jdo 408 276-5638 mailto:craig.russ...@sun.com P.S. A good JDO? O, Gasp!
smime.p7s
Description: S/MIME cryptographic signature