From: Erik Brakkee
+ * 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 main use cases are explained below:
+ *
+ * See the design overview for a an overview of the design.
+ *
+ * To execute code withing a JDBC transaction, use the {@link DatabaseUtils} and
+ * use the {@link DatabaseUtils#executeInTransaction(org.wamblee.support.persistence.DatabaseUtils.JdbcUnitOfWork)}
+ * method.
+ * 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. The reason for using a
+ * 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
+ *
+ *
+ *
+ * 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.
+ * Stopping 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}.
+ *
+ *
+ *
+ * Executing code within a JDBC transaction
+ *
+ *
+ * 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
+ *
+ *
+ *
+ * IDatabaseTester dbtester = dbutils.createDbTester(new ITableFilterSimple() {
+ * public boolean accept(String aTableName) throws DataSetException {
+ * return aTableName.startsWith("XYZ_");
+ * }
+ * });
+ *
+ *
+ * DatabaseUtils
instead of DBUnit directly is that
+ * DatabseUtils
will keep track of connections and close them when DatabaseUtils
+ * is closedBasic JPA testing
+ *
+ * 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.
+ *