# EclipseLink persistence.xml Frage



## floetentheo (3. Sep 2009)

Hallo zusammen,

ich hab eine kleine Anwendung welche EclipseLink nutz. Dazu hab ich ein paar Test geschrieben. 
Was muß ich denn in der persistence.xml als Property angeben das er mir vor jedem test in eine testklasse die Datenbank neu erstellt damit sie quasi vor jedem test leer ist?
Bei Hibernate geht das ja ganz gut mit 

	<property name="schemaUpdate">
			<value>true</value>
		</property>

danke im voraus
theo


----------



## maki (3. Sep 2009)

[xml]
            <property name="eclipselink.ddl-generation" value="drop-and-create-tables" />
            <property name="eclipselink.ddl-generation.output-mode" value="both"/>  
[/xml]

Welche Db verwendest du zum testen?
Du willst ja sicher nicht nur eine leere DB, Testdaten brauchst du schon auch, oder?
Kann da DBUnit empfehlen.


----------



## floetentheo (3. Sep 2009)

Ich nutze ne HSQL.
Und nein die Anwendung ist so klein, ich brauch da keine Testdaten. 
Aber irgendwie  scheint es so auch nicht wirklich zu funktionieren, das Problem liegt wohl doch wo anders. 
Hier rauf bin ich nur gekommen weil Objekte mehrfach in der DB drin sind obwohl sie es nicht sein dürfen.
In einem Test erstell ich eine Objet vom Typ A und in einen anderen 4 Objekte vom Typ A um zu prfüen ob er sie auch fein alle läd aber am Ende kommen 5 raus und net wie angenommen 4, weil das erste sollte er ja so abräumen. 

Der eigentlich Fehler ist dieser hier aber dazu werd ich wenn ich net selber drauf komme gleich hier nen thread erzeugen.

009-09-03 10:27:11,956] L=[INFO] C=[de.***.***.***.***.persist.DatabaseTestCase] M=[setup DatabaseTestCase] 
[EL Warning]: 2009-09-03 10:27:12.157--UnitOfWork(1118816)--Exception [EclipseLink-7197] (Eclipse Persistence Services - 2.0.0.v20090821-r4934): org.eclipse.persistence.exceptions.ValidationException
Exception Description: Null primary key encountered in unit of work clone


----------



## maki (3. Sep 2009)

HSQL funzt nicht wirklich sauber mit Eclipselink, da braucht man mehrere Workarounds, bis hin wie man Unique Felder markiert, gibt da noch den einen oder anderen Bug, Derby ist ime besser zum testen von Eclipselink geeignet, aber auch langsamer.

Zeig mal deinen Code..


----------



## floetentheo (3. Sep 2009)

Also was ich hier im Prinzip mache ist eine Anwendung von Hibernate auf EclipseLink zu portieren. 
Beide laufen auf ner HSQL DB und die test von der Hibernate Sache sollen auch auf dem EclipseLink laufen, aber je mehr ich google Frage desto eher komm ich zu der Annahme das EclipseLink + HSQL = böse.

Was wäre denn besser zu nutzen, das Derby oder DBUnit?


----------



## maki (3. Sep 2009)

DBUnit ist ein Framework für Unittests mit relationalen DBs, damit kann man zum Beispiel Testdaten einspielen vor den Tests und diese Testdaten danach wieder löschen, also allgemein gesagt kann man damit die DB in einen definierten Zustand setzen, ist ja nicht unwichtig beim Testen  DBunit kann aber noch mehr...
Ich nutze DBUnit immer in meinen Tests, auch wenn es nicht immer ganz einfach ist es mit der jeweiligen DB zum zusammenspielen zu bringen, muss aber nur einmal gemacht werden, danach läuft alles, hier meine Anpassung für Derby mit DBUnit:

```
public class MyDerbyPlatform extends DerbyPlatform {

	@Override
	public void printFieldIdentityClause(Writer writer)
			throws ValidationException {
		try {
			writer.write(" GENERATED BY DEFAULT AS IDENTITY (START WITH 1000) ");
		} catch (IOException ioException) {
			throw ValidationException.fileError(ioException);
		}
	}
}
```
DBUnit ist aber egal wenn du "nur" migrieren musst, dann musst du auch nix ändern an der DERBY target-database.

Derby ist imho eine gute Wahl für EclipseLink tests, man muss den "Database Dialect" (oder wie er bei EclipseLink heisst die target-database) etwas anpassen wenn man es mit DBUnit verwenden will, ist aber nicht wirklich nur ein ein paar Zeilen Code.


----------



## floetentheo (3. Sep 2009)

So die Sache rennt nun auf Derby, nur hab ich das gleich Problem das er die DB zwischen den Test nicht abräumt!


----------



## maki (3. Sep 2009)

floetentheo hat gesagt.:


> So die Sache rennt nun auf Derby, nur hab ich das gleich Problem das er die DB zwischen den Test nicht abräumt!


Du musst schon einen neuen EMF erstellen und den alten löschen zwischen Testcases (setUp/tearDown bzw. @Before/@After). 

Zeig doch mal den Testcode...


----------



## floetentheo (3. Sep 2009)

So also das sind die Properties von Derby in der persistence.xml 
[xml]
<persistenceroperties>
			<persistenceroperty name="javax.persistence.jdbc.driver"
				value="org.apache.derby.jdbc.EmbeddedDriver" />
			<persistenceroperty name="javax.persistence.jdbc.url"
				value="jdbc:derby:target/data/derby_demo;create=true" />
			<persistenceroperty name="javax.persistence.jdbc.user"
				value="user" />
			<persistenceroperty name="javax.persistence.jdbc.password"
				value="password" />

			<persistenceroperty name="eclipselink.target-database"
				value="Derby" />

			<persistenceroperty name="eclipselink.ddl-generation"
				value="drop-and-create-tables" />
			<persistenceroperty name="eclipselink.ddl-generation.output-mode"
				value="database" />
		</persistenceroperties>
[/xml]
Und das ist die Testklasse:


```
@Test
	public void testPersist() {
		final ManufacturerDO manufactur = getSimpleObjektFactory()
				.createManufacturerDO("Opel", "Die mit dem Blitz");
		manufactur.setErsteller(admin);
		manufactur.setLetzerBearbeiter(bearbeiter);
		manufacturerDao.persist(manufactur);
		assertNotNull(manufactur.getPk());

	}

	
	@Test
	public void testLoadByPk() {
		final ManufacturerDO manufacturerDO = getSimpleObjektFactory()
				.createManufacturerDO("Ford", "");
		manufacturerDO.setErsteller(admin);
		manufacturerDO.setLetzerBearbeiter(bearbeiter);
		manufacturerDao.persist(manufacturerDO);
		assertNotNull(manufacturerDO.getPk());
		final int pk = manufacturerDO.getPk();

		final ManufacturerDO loadByPk = manufacturerDao.loadByPk(pk);
		assertNotNull(loadByPk);
		assertEquals(manufacturerDO, loadByPk);

	}

	@Test
	public void testLoadByName() {
		final String name = "Mercedes";

		final ManufacturerDO manufacturerDO = getSimpleObjektFactory()
				.createManufacturerDO(name, "");
		manufacturerDO.setErsteller(admin);
		manufacturerDO.setLetzerBearbeiter(bearbeiter);
		manufacturerDao.persist(manufacturerDO);

		final List<ManufacturerDO> loadByName = manufacturerDao
				.loadByName(name);
		assertNotNull(loadByName);
		assertTrue(loadByName.size() > 0);

		final ManufacturerDO manufacturerDO2 = loadByName.get(0);
		assertEquals(manufacturerDO, manufacturerDO2);
	}


	@Test
	public void testLoadAll() {
		final ManufacturerDO ford = getSimpleObjektFactory()
				.createManufacturerDO("Ford", "");
		ford.setErsteller(admin);
		ford.setLetzerBearbeiter(bearbeiter);
		manufacturerDao.persist(ford);

		final ManufacturerDO opel = getSimpleObjektFactory()
				.createManufacturerDO("Opel", "");
		opel.setErsteller(admin);
		opel.setLetzerBearbeiter(bearbeiter);
		manufacturerDao.persist(opel);

		final ManufacturerDO vw = getSimpleObjektFactory()
				.createManufacturerDO("VW", "");
		vw.setErsteller(admin);
		vw.setLetzerBearbeiter(bearbeiter);
		manufacturerDao.persist(vw);

		final ManufacturerDO porsche = getSimpleObjektFactory()
				.createManufacturerDO("Porsche", "");
		porsche.setErsteller(admin);
		porsche.setLetzerBearbeiter(bearbeiter);
		manufacturerDao.persist(porsche);

		final List<ManufacturerDO> loadAll = manufacturerDao.loadAll();
		assertEquals(4, loadAll.size());

	}

	@Test
	public void persistWithAllProperties() {
		final ManufacturerDO manufacturerDO = new ManufacturerDO();
		final List<ProductDO> products = manufacturerDO.getProducts();
		products.add(new ProductDO());

		manufacturerDao.persist(manufacturerDO);

		assertNotNull(manufacturerDO.getPk());
		// TODO asserts
	}
```


Zeile 89 schlägt dann fehl, weil 7 anstatt 4 drin sind.


----------



## maki (3. Sep 2009)

Das manufacturerDao braucht imo für jeden Tests einen neuen EntityManger der von einer neuen EntityMangerFactory erzeugt wurde, wie kommt das Dao denn an den EM?

Nebenbei, ist zwar nicht dein Problem, aber nur dass ich es erwähnt hatte:

```
@Test
    public void testLoadByPk() {
        final ManufacturerDO manufacturerDO = getSimpleObjektFactory()
                .createManufacturerDO("Ford", "");
        manufacturerDO.setErsteller(admin);
        manufacturerDO.setLetzerBearbeiter(bearbeiter);
        manufacturerDao.persist(manufacturerDO);
        assertNotNull(manufacturerDO.getPk());
        final int pk = manufacturerDO.getPk();
 
        final ManufacturerDO loadByPk = manufacturerDao.loadByPk(pk);
        assertNotNull(loadByPk);
        assertEquals(manufacturerDO, loadByPk);
 
    }
```
[c] manufacturerDao.persist[/c] wird mitgetestet, und falls es fehlschlägt, schlägt [c]manufacturerDao.loadByPk[/c] auch fehl, DBUnit verhindert das und der TEst würde kürzer ausfallen:

```
@Test
    public void testLoadByPk() {
 
        final ManufacturerDO loadByPk = manufacturerDao.loadByPk(pk);
        assertNotNull(loadByPk);
        assertEquals(manufacturerDO, loadByPk); 
    }
```


----------



## floetentheo (3. Sep 2009)

Die Daos erben alle von dieser Klasse:


```
public abstract class BaseDaoEntity<T extends EntityObjectDO<?>> extends
		JpaDaoSupport {

	static protected final EntityManager em = Persistence
			.createEntityManagerFactory("prometheus").createEntityManager();

	public abstract Class<T> getDoClass();

	@SuppressWarnings("unchecked")
	protected T loadByPk(final Session session, final Integer pk) {
		final Class<T> doClass = getDoClass();
		String tableName = doClass.getName().split(".")[0];
		tableName = tableName.substring(0, tableName.length() - 2);
		final Expression selectionCriteria = new FieldExpression(
				new DatabaseField("id", tableName));

		final T retVal = (T) session.readObject(doClass, selectionCriteria);
		return retVal;
	}

	public void persist(final T entity) {
		em.getTransaction().begin();
		em.persist(entity);
		em.getTransaction().commit();
	}

	public T loadByPk(final Integer pk) {
		return em.find(getDoClass(), pk);
	}

	@SuppressWarnings("unchecked")
	public List<T> loadAll() {
		final Query query = em.createQuery("select m from "
				+ getDoClass().getSimpleName() + " m");
		return query.getResultList();
	}

	@SuppressWarnings("unchecked")
	public List<T> loadByName(final String searchName) {
		final Query query = em.createQuery(
				"select m from " + getDoClass().getSimpleName()
						+ " m where m.name = ?1").setParameter(1, searchName);
		return query.getResultList();
	}

}
```

Soll ich etwa für jede Transaktion nen neuen EM erzeugen?


----------



## maki (3. Sep 2009)

> Soll ich etwa für jede Transaktion nen neuen EM erzeugen?


Für jeden Test einen neuen EMF und einen neuen EM.
Alternativ kannst du natürlich einen Rollback nach jedem Test machen, die Frage ist ob die Daten dann auch wirklich zur DB gesendet werden.


----------

