DbUnit H2 in memory db with Spring and Hibernate

10,307

The problem is that DBUnit is loading the table data before Hibernate can initialize.

As part of your @setup, you'll need to get the Hibernate session. This should cause Hibernate to create your table. You could even force it by executing a simple query like select 1

Share:
10,307
Arless
Author by

Arless

Updated on August 22, 2022

Comments

  • Arless
    Arless almost 2 years

    Hi I'm trying a little POC with JPA and unit test to verify that the DB schema is created. I'm working with H2 DB and I set to Hibernate create the schema from the entities, but when DbUnit tries to initialize the DB from a dataset I always get a Table ... not found in tableMap. I read that I have to add the property DB_CLOSE_DELAY=-1 to DB URL but is like after Hibernate creates the schema the DB is losted when DbUnit tries to initialize.

    Any ideas? Any help is highly appreciated.

    This is my config:

    application-context.xml

    <bean id="entityManagerFactory"
        class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="dataSourceH2" />
        <property name="packagesToScan" value="com.xxx.model" />
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <property name="generateDdl" value="true" />
                <property name="showSql" value="true" />
                <!-- property name="databasePlatform" value="org.hibernate.dialect.MySQLInnoDBDialect" /-->
                <property name="databasePlatform" value="org.hibernate.dialect.H2Dialect" />
                <!-- property name="database" value="MYSQL" /-->
            </bean>    
            </property>
            <property name="jpaProperties">
                <props>
                    <prop key="hibernate.hbm2ddl.auto">create</prop>
                    <prop key="javax.persistence.validation.mode">CALLBACK</prop>
                </props>
            </property>
        </bean>
    
    <bean id="dataSourceH2"
            class="org.springframework.jdbc.datasource.DriverManagerDataSource">
            <property name="driverClassName" value="org.h2.Driver" />
            <property name="url" value="jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1" />
            <property name="username" value="sa" />
            <property name="password" value="" />
        </bean>
    

    RepositoryTest.java

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations = { "/application-context-test.xml" })
    @Transactional
    public class SystemEntityRepositoryH2Test {
    
        @Inject
        private SystemEntityRepository repository;
    
        @Inject
        private DataSource dataSourceH2;
    
        private IDatabaseConnection connection;
    
        @Before
        public void setUp() throws Exception {
            IDatabaseConnection dbUnitCon = null;
            dbUnitCon = new DatabaseDataSourceConnection(dataSourceH2, "testdb");
            dbUnitCon.getConfig().setProperty(DatabaseConfig.FEATURE_QUALIFIED_TABLE_NAMES, true);
    
            IDataSet dataSet = this.getDataSet("dataset-systementity.xml");
            DatabaseOperation.INSERT.execute(dbUnitCon, dataSet);
    
        }
    
        @After
        public void tearDown() throws Exception {
            //DatabaseOperation.DELETE_ALL.execute(this.getConnection(), this.getDataSet(dataSetFile));
        }
    
        @Test
        public void test() throws Exception {
    
        }
    
        protected IDataSet getDataSet(String dataSetFile) throws Exception {
            ResourceLoader resourceLoader = new ClassRelativeResourceLoader(this.getClass());
            Resource resource = resourceLoader.getResource(dataSetFile);
    
            if (resource.exists()) {
                return new FlatXmlDataSetBuilder().build(resource.getInputStream());
            }
    
            return null;
        }
    }
    

    dataset-systementity.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <dataset>
        <System_Entities id="2" name="NAME" phone01="+52-55-55555555" email="[email protected]"
                        address01="Street" address02="123" address03="1" address04="Address04"
                        address05="Address05" city="City" state="State" country="MX"
                        zipcode="12345" />
    </dataset>
    

    Error

    ERROR DatabaseDataSet:286 - Table 'System_Entities' not found in tableMap=org.dbunit.dataset.OrderedTableNameMap[_tableNames=[], _tableMap={}, _caseSensitiveTableNames=false]
    

    I can see that the tables are created by hibernate because the log shows all the sql sentences without error.

    Thanks.

    SOLUTION

    Thanks Mark Robinson I modified the setUp method to:

    @Before
        public void setUp() throws Exception {
            IDatabaseConnection dbUnitCon = null;
            EntityManager entityManager = entityManagerFactory.createEntityManager();
            Session session = entityManager.unwrap(Session.class);
            SessionImplementor si = (SessionImplementor) session;
            Connection conn = si.getJdbcConnectionAccess().obtainConnection();
            dbUnitCon = new DatabaseConnection(conn);
    
            //dbUnitCon.getConfig().setProperty(DatabaseConfig.FEATURE_QUALIFIED_TABLE_NAMES, true);
    
            IDataSet dataSet = this.getDataSet("dataset-systementity.xml");
            DatabaseOperation.INSERT.execute(dbUnitCon, dataSet);
        }
    

    It works now, what I don't understand yet is if I use HSQLDB I don't have this problem.

  • Arless
    Arless almost 11 years
    Thanks! the problem now is in my test method, I save an object using a repository object and after that I want to get the actual dataSet using createDataSet() from the dbUnitCon but I get a "Timeout trying to lock table..." error, I added MVCC=TRUE to the connection url and it works but the dataset only includes the data that dbunit initializes, it does not include the object saved with the repository object.
  • Arless
    Arless almost 11 years
    Continuing my previous comment, it's like the transaction used by the repository is not committed yet and when I try to get the actual dataset I can't see that change, I don't know where to go after this.