I'm working (day job!) on a Java interface to the MySQL Cluster database (a.k.a. NDB). NDB is a high performance, high availability database used mostly in telecommunications applications. It can be the backing store for a MySQL server (accessed via any of the MySQL client APIs such as ODBC, JDBC) or can be used directly via primitive C++ or Java APIs.

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=test
The 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 interface
DomainObject 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!



Attachment: smime.p7s
Description: S/MIME cryptographic signature

Reply via email to