![]() | ![]() | ![]() | ![]() | ![]() | ![]() | |||||||||||||||||||||||||||||||||||||||||||||||
![]() | ![]() | ![]() | ![]() | |||||||||||||||||||||||||||||||||||||||||||||||||
![]() | ![]() | ![]() | ![]() | ![]() | ![]() | |||||||||||||||||||||||||||||||||||||||||||||||
![]() | ![]()
|
Reference: Client Application J2EE Application Using A JDO Database Transient And Persistent Objects OQLQuery Create/remove/update Using JDO And XML Opening A JDO DatabaseCastor JDO supports two type of environments, client applications and J2EE servers. Client applications are responsible for configuraing the database connection and managing transactions explicitly. J2EE applications use JNDI to obtain a pre-configured database connection, and use UserTransaction or container managed transactions (CMT) to manage transactions. If you have been using JDBC in these two environments, you will be readily familiar with the two models and the differences between them. Client ApplicationClient applications are responsible for defining the JDO database configuration, and managing the transaction explicitly. The database is configured through a separate XML file which links to the mapping file. In the example code I refer to the database file as database.xml, but any name can be used. See Castor JDO Database Configuration for more information. The The following code snippet opens a database, performs a transaction, and closes the database, as it will typically appear in client applications: J2EE ApplicationNote: We are now working on supporting Castor inside a J2EE container. Stay tuned for more information. J2EE applications depend on the J2EE container (Servlet, EJB, etc) to configure the database connection and use JNDI to look it up. This model allows the application deployer to configure the database properties from a central place, and gives the J2EE container the ability to manage distributed transactions across multiple data sources. Instead of constructing a The following code snippet uses JNDI to lookup a database, and uses UserTransaction to manage the transaction: When the transaction is managed by the container, a common case with EJB beans and in particular entity beans, there is no need to being/commit the transaction explicitly. Instead the application server takes care of enlisting the database in the ongoing transaction and commiting/rollingback at the proper time. The following code snippet relies on the container to manage the transaction: Using A JDO DatabaseTransient And Persistent ObjectsAll JDO operations occur within the context of a transaction. JDO works by loading data form the database into an object in memory, allowing the application to modify the object, and then storing the object's new state when the transaction commits. All objects can be in one of two states: transient or persistent. Transient: Any object whose state will not be saved to the database when the transaction commits. Changes to transient objects will not be reflected in the database. Persistent: Any object whose state will be saved to the database when the transaction commits. Changes to persistent objects will be reflected in the database. An object becomes persistent in one of two ways: it is the result of a query, (and the query is not performed in read-only mode) or it is added to the database using create(java.lang.Object) or update(java.lang.Object). All objects that are not persistent are transient. When the transaction commits or rolls back, all persistent objects become transient. In a client application, use begin(), commit() and rollback() to manage transactions. In a J2EE application, JDO relies on the container to manage transactions either implicitly (based on the transaction attribute of a bean) or explicitly using the javax.transaction.UserTransaction interface. If a persistent object was modified during the transaction, at commit time the modifications are stored back to the database. If the transaction rolls back, no modifications will be made to the database. Once the transaction completes, the object is once again transient. To use the same object in two different transactions, you must query it again. An object is transient or persistent from the view point of the database to which the transaction belongs. An object is generally persistent in a single database, and calling isPersistent(java.lang.Object) from another database will return false. It is possible to make an object persistent in two database, e.g. by querying it in one, and creating it in the other. OQLQueryOQL queries are used to lookup and query objects from the database. OQL queries are similar to SQL queries, but use object names instead of SQL names and do not require join clauses. For example, if the object being loaded is of type TestObject, the OQL query will load FROM TestObject, whether the actual table name in the database is test, test_object, or any other name. If a join is required to load related objects, Castor will automatically perform the join. The following code snippet uses an OQL query to load all the objects in a given group. Note that product and group are related objects, the JDBC query involves a join: The following code snippet uses the previous query to obtain products, mark down their price by 25%, and store them back to the database (in this case using a client application transaction): As illustrated above, a query is executed in three steps. First a query object is created from the database using an OQL statement. If there are any parameters, the second step involves binding these paramaters. Parameters are bound in the same order as they appear in the OQL statement. The third step involves executing the query and obtaining a result set of type A query can be created once and executed multiple times. Each time it is executed the bound parameters are lost, and must be supplied a second time. The result of a query can be used while the query is being executed a second time. The is also a special form of query that gives a possibility to call stored procedures: Create/remove/updateThe method create(java.lang.Object) creates a new object in the database, or in JDO terminology makes a transient object persistent. An object created with the create method will remain in the database if the transaction commits; if the transaction rolls back the object will be removed from the database. An exception is thrown if an object with the same identity already exists in the database. The following code snippet creates a new product with a group that was previously queried: The method remove(java.lang.Object) has the reverse affect, deleting a persistent object. Once removed the object is no longer visible to any transaction. If the transaction commits, the object will be removed from the database, however, if the transaction rolls back the object will remain in the database. An exception is thrown when attempting to remove an object that is not persistent. Using JDO And XMLCastor JDO and Castor XML can be combined to perform transactional database operations that use XML as the form of input and output. The following code snippet uses a combination of persistent and transient objects to describe a financial operation. This example retrieves two account objects and moves an amount from one account to the other. The transfer is described using a transient object (i.e. no record in the database), which is then used to generate an XML document describing the transfer. An extra step (not shown here), uses XSLT to transform the XML document into an HTML page. Transfer tran; Account from; Account to; OQLQuery oql; tran = new Transfer(); // Construct a query and load the two accounts oql = db.getOQLQuery( "SELECT a FROM Account a WHERE Id=$" ); oql.bind( fromId ); from = oql.execute().nextElement(); oql.bind( toId ); to = oql.execute().nextElement(); // Move money from one account to the other if ( from.getBalance() >= amount ) { from.decBalance( amount ); to.incBalance( amount ); trans.setStatus( Transfer.COMPLETE ); trans.setAccount( from ); trans.setAmount( amount ); } else { // Report an overdraft trans.setStatus( Transfer.OVERDRAFT ); } // Produce an XML describing the transfer Marshaller.marshal( trans, outputStream ); The XML produced by the above code might look like: | ||||||||||||||||||||||||||||||||||||||||||||||||||
![]() ![]() | ||||||||||||||||||||||||||||||||||||||||||||||||||||
![]() | ![]() | |||||||||||||||||||||||||||||||||||||||||||||||||||
![]() | ![]() | |||||||||||||||||||||||||||||||||||||||||||||||||||
![]() |