X-Git-Url: http://wamblee.org/gitweb/?a=blobdiff_plain;f=test%2Fenterprise%2Fsrc%2Fmain%2Fjava%2Forg%2Fwamblee%2Fsupport%2Fpersistence%2Fpackage-info.java;h=979dde6f7c0189c5d4a53f709d610403218de996;hb=b57cbdcefda8db670154b97615af84bcada13349;hp=7739749d02a7505f73a7d00abc257eed667da277;hpb=8de36ff0206c996baf3ee4adc3e2293b12ff5f39;p=utils diff --git a/test/enterprise/src/main/java/org/wamblee/support/persistence/package-info.java b/test/enterprise/src/main/java/org/wamblee/support/persistence/package-info.java index 7739749d..979dde6f 100644 --- a/test/enterprise/src/main/java/org/wamblee/support/persistence/package-info.java +++ b/test/enterprise/src/main/java/org/wamblee/support/persistence/package-info.java @@ -1,24 +1,249 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ /** - * This package provide a number of utilities for database testing and in particular with - * JPA. + *

+ * This package provides test library for database testing in general and JPA testing + * specifically. As part of this it provides a means to transparently start an inmemory + * database from a junit test or connect to an external database. Also, given a persistence + * unit it is easy to start testing it in a junit test with only a few lines of code. + *

* - * The following utilities are available: + *

+ * The main use cases are explained below: + *

* + * + *

+ * See also the design overview. + *

+ * + * + *

Basic database testing, transparently connecting to a database

+ *
+ * Starting the database: + *
+ *      Database db = DatabaseBuilder.getDatabase();
+ *      DataSource dataSource = db.start();
+ * 
+ *

+ * If nothing is specified in the user's environment, an inmemory database is started (derby). + * Using the datasource is just standard JDBC now. + *

+ *

+ * After a test it is good practice to stop the database: + *

+ *
+ *      db.stop();
+ * 
+ * + * + *

Connecting to an external database

+ *
+ * + * Connecting to an external database can be done by requiring the 'external' capability on + * the database provider. + *
+ *      Database db = DatabaseBuilder.getDatabase(DatabaseProvider.CAPABILITY_EXTERNAL); 
+ * 
+ * This also requires a number of environment variables or system properties to be set, + * see {@link ExternalDatabase}. + * + *

+ * However, the most convenient way to set the capabilities is usually to set a system property or environment + * variable see the javadocs of {@link DatabaseBuilder}. and + * specifically DatabaseBuilder.DB_CAPABILITIES_PROP + *

+ * + * + * + *

Executing code within a JDBC transaction

+ *
+ *

+ * To execute code withing a JDBC transaction, use the {@link DatabaseUtils} and + * use the {@link DatabaseUtils#executeInTransaction(org.wamblee.support.persistence.DatabaseUtils.JdbcUnitOfWork)} + * method. + *

+ *
+ *       DatabaseUtils dbutils = new DatabaseUtils(dataSource);
+ *       boolean result = dbutils.executeInTransaction(
+ *           new JdbcUnitOfWork<Boolean>() {
+ *               @Override
+ *               public Boolean execute(Connection aConnection) throws Exception {
+ *                   ResultSet res = jpaTester.getDbUtils().executeQuery(
+ *                       aConnection, GROUP_QUERY, aGroup);
+ *                   return res.next();
+ *               }
+ *           });
+ * 
+ * {@link DatabaseUtils} also provides various other utility methods to work with JDBC queries. + * + * + *

Using DB Unit in your tests

+ *
+ * + *

To work with DBUnit, + * DatabaseUtils#createDbTester(org.dbunit.dataset.filter.ITableFilterSimple) + * must be used passing it in the tables to use in the form of a {@link org.dbunit.dataset.filter.ITableFilterSimple} + * object.

+ * + *
+ *      IDatabaseTester dbtester = dbutils.createDbTester(new ITableFilterSimple() {
+ *          public boolean accept(String aTableName) throws DataSetException {
+ *              return aTableName.startsWith("XYZ_");
+ *          }
+ *      });
+ * 
+ * + *

The reason for using a DatabaseUtils instead of DBUnit directly is that + * DatabseUtils will keep track of connections and close them when DatabaseUtils + * is closed

+ * + * + *

Basic JPA testing

+ *
+ *

+ * First step is to create a {@link PersistenceUnitDescription} that matches the persistence unit you + * want to test. + *

+ *

Second step is to make sure that all entities are listed explicitly in your + * persistence.xml. Currently, class path scanning appears to fail when + * run from junit. + * Specifying all entities explicitly is not necessarily a bad thing as it is also more efficient. + *

+ * + *

+ * Now create a JpaTester in your test code: + *

+ *
+ *      @Before
+ *      public void setUp() throws Exception {
+ * 
+ *          // First we create the JpaTester by telling us which persistence unit we
+ *          // are going to test
+ *          jpaTester = new JpaTester(new MyPersistenceUnit());
+ *          jpaTester.start();     
+ *      }
+ * 
+ * + *

+ * Then in test code execute some JPA code within a unit of work: + *

+ *
+ *      jpaTester.getJpaBuilder().execute(new JpaUnitOfWork() {
+ *          public Void execute(EntityManager aEm) {
+ *              MyEntity entity = new MyEntity("a", "b");
+ *              aEm.persist(entity);
+ *              return null;
+ *          }
+ *      });
+ * 
+ * + * + *

JPA testing combined with JDBC and DBUnit

+ *
+ *

The JPATester provides access to all required object. It is usually convenient to + * get them directly from the JPATester after initializing it: + *

+ *      builder = jpaTester.getJpaBuilder();
+ *      dbutils = jpaTester.getDbUtils();
+ *      dbtester = dbutils.createDbTester(new MyTables());
+ * 
+ * + * + *

Testing a service that requires a transaction

+ *
+ * + *

Using {@link TransactionProxyFactory} it is possible to create a proxy for a given + * service interface to provide the semantics of 'requires new' transaction semantics. + *

+ *      TransactionProxyFactory factory = new TransactionProxyFactory(
+ *           jpaTester.getJpaBuilder(), Service.class);
+ *      Service service = new ServiceImpl(factory.getTransactionScopedEntityManager()); 
+ *      Service proxy = factory.getProxy(service);
+ *      proxy.execute(...);
+ * 
+ * + *

+ * In the above example, the Service POJO requires an {@link EntityManager} in its + * constructor and it is passed a transaction scoped entitymanager from the factory. This entitymanager + * is in fact a so-called contextual reference. + * Next, the proxy is obtained from the factory. Invoking any method on it will make sure a new + * transaction is started and a new entity manager is created for the scope of that transaction. + *

+ * + * + *

Design overview

+ *
+ * + *

Database transparency

+ * + *
+ * database + *
+ *

+ * {@link DatabaseProvider} uses java.util.ServiceLoader to find all implementations + * of {@link DatabaseProvider} on the classpath. It then asks the database providers whether + * they support the required capabilities (by default inmemory), and the first provider that + * supports the capabilities is used to create the database. + *

+ *

+ * Note that the Database interface is not intended to always create a database. + * It will do so for {@link DerbyDatabase} (inmemory), but with {@link ExternalDatabase} + * it simply connects to an external database based on system properties or environment + * variables. + *

+ * + *

JPA tester overview

+ * + *
+ * database + *
+ * + *

JPATester is responsible for:

+ * + * + * */ package org.wamblee.support.persistence; +