2014-09-30 11 views
5

Sto chiedendo e rispondendo a questa domanda per riferimento futuro, perché penso di aver trovato una soluzione decente per un problema comune con DbUnit. Spero che aiuti qualcuno, da qualche parte lungo la linea.DbUnit non riesce a pulire: inserire il vincolo di chiave esterna

Sto usando DbUnit 2.5.0 e TestNG 6.8.8. Il mio caso d'uso è per una parte di un database che comprende 3 entità. C'è un ServiceUser che contiene una chiave esterna sia per un Administrable sia per un UserGroup.

ho seguito più dell'esempio di codice da http://city81.blogspot.com/2011/03/testing-jpa-entities-using-dbunit.html

public abstract class AbstractDatabaseTest { 
    protected EntityManager em; // initialized elsewhere 
    private IDatabaseConnection connection; 
    private IDataSet dataset; 

    @BeforeClass 
    private void setupDatabaseResource() throws Exception { 
     // using Hibernate 
     connection = new DatabaseConnection(((SessionImpl) (em.getDelegate())).connection()); 
     connection.getConfig().setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY, new HsqldbDataTypeFactory()); 

     // full database export 
     IDataSet fullDataSet = connection.createDataSet(); 

     final String datasetPath = String.format("%s%s", RESOURCE_FOLDER, "Testing.xml"); 
     FlatXmlDataSet.write(fullDataSet, new FileOutputStream(datasetPath)); 

     FlatXmlDataSetBuilder flatXmlDataSetBuilder = new FlatXmlDataSetBuilder(); 
     flatXmlDataSetBuilder.setColumnSensing(true); 
     dataset = flatXmlDataSetBuilder.build(new FileInputStream(datasetPath)); 
    } 

    @AfterMethod 
    public void cleanDB() throws Exception { 
     em.getTransaction().begin(); 
     DatabaseOperation.CLEAN_INSERT.execute(connection, dataset); 
     em.getTransaction().commit(); 
    } 
} 

Il risultato di questo è la seguente XMLDataSet (dati omessi):

<dataset> 
    <administrable/> 
    <serviceuser/> 
    <usergroup/> 
</dataset> 

Quando TestNG esegue il @AfterMethod, ottengo il seguente Eccezione:

com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException 
Cannot delete or update a parent row: a foreign key constraint fails (`testing_db`.`serviceuser`, CONSTRAINT `FK_gyylcfbhpl2ukqs5rm7sq0uy8` FOREIGN KEY (`userGroup_id`) REFERENCES `usergroup` (`id`)) 

risposta

11

Il problema è che lo XMLDataSet creato sopra non conosce i vincoli di chiave esterna nelle tabelle e crea l'elenco di tabelle in ordine alfabetico. L'operazione CLEAN_INSERT, tuttavia, prende l'elenco delle tabelle e lo attraversa in ordine inverso e richiede che i riferimenti di chiave esterna (qui: ServiceUser.userGroup_id) vengano eliminati prima dell'entità di riferimento (qui: UserGroup).

ho trovato queste informazioni tramite Unitils doesn't work e http://forum.spring.io/forum/spring-projects/data/12868-dbunit-test-fails-mysql-server-hates-me?p=337672#post337672

qualche scavo minore nella documentazione DBUnit ha portato ad un approccio corretto a creare il set di dati, che controlla le dipendenze chiave esterna e cerca di ordinare le entità in modo appropriato:

IDataSet fullDataSet = new FilteredDataSet(new DatabaseSequenceFilter(connection), connection.createDataSet()); 

Risultato:

<dataset> 
    <administrable/> 
    <usergroup/> 
    <serviceuser/> 
</dataset> 

Questa volontà CLEAN_INSERT correttamente.

Declinazione di responsabilità: Non ho riscontrato dipendenze circolari o chiavi esterne autoreferenziali e non ho verificato che questa correzione possa gestirle.

+0

Dove hai inserito lo snippet di codice? –

+0

Non sono sicuro di cosa stai chiedendo. Non dico nulla su un frammento di codice e tutto il codice pertinente è disponibile sia nella domanda che nella risposta. – blagae

+0

Il frammento di codice IDataSet che stavi utilizzando. In quale file l'hai posto? –

Problemi correlati