X-Git-Url: http://wamblee.org/gitweb/?a=blobdiff_plain;f=test%2Fenterprise%2Fsrc%2Fmain%2Fjava%2Forg%2Fwamblee%2Fsupport%2Fpersistence%2Fpackage-info.java;h=1ea78e255d6e9e6bb1c712431c4dac3085637de0;hb=bd197313c85d3ee6336e7e7cbf7ff706247df9b4;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..1ea78e25 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,244 @@ +/* + * 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: + *
*JpaTester
that provides a callback based
- * style of working with transaction-scoped entity managers.
+ * JpaTester
for working with databases in general. Test code will not use this
- * utility often.
+ * JpaTester
+ * JpaTester
+ * + * See the design overview for a an overview of the design. + *
+ * + * + *+ * 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. + * Stopping the database + *
+ * db.stop(); + *+ * + * + *
+ * 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 {@link DatabaseBuilder#DB_CAPABILITIES_PROP} + *
+ * + * + * + *+ * 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. + * + * + *
To work with DBUnit, {@link 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
+ * 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; + * } + * }); + *
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(); + * dbtester = jpaTester.getDbUtils().createDbTester(new MyTables()); + * dbutils = jpaTester.getDbUtils(); + *+ * + * + *
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.
+ *
+ * {@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.
+ *
JPATester
is responsible for: