0

We are using DB Unit to test some of our classes. Our main database is Oracle but for DB Unit we work with HSQLDB.

We have a class that has two attributes like these:

@Column(columnDefinition="NUMBER(6,2)")
private Double height;

@Column(columnDefinition="NUMBER(6,2)")
private Double weight;

This is our test context configuration class:

@Configuration
@EnableJpaRepositories(basePackages = {"com.mycompany"})
@ComponentScan(basePackages = "com.mycompany")
public class TestContextConfiguration {

    private final String DB_DRIVER = "org.hsqldb.jdbcDriver";
    private final String DB_URL = "jdbc:hsqldb:mem:test;sql.syntax‌​_ora=true";
    private final String DB_USER = "sa";
    private final String DB_PASS = "";

    private final String PACKAGES = "com.mycompany.myapp.domain";
    private final String PERSISTENCE_UNIT_NAME = "testDatabase";
    private final String PERSISTENCE_UNIT_LOCATION = "classpath:META-INF/persistence.xml";

    @Bean
    public DataSource dataSource() {
        BasicDataSource ds = new BasicDataSource();

        ds.setDriverClassName(DB_DRIVER);
        ds.setUrl(DB_URL);
        ds.setUsername(DB_USER);
        ds.setPassword(DB_PASS);
        return ds;
    }

    @Bean
    public EntityManagerFactory entityManagerFactory() {
        LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();

        em.setDataSource(dataSource());
        em.setJpaDialect(new HibernateJpaDialect());
        em.setPackagesToScan(PACKAGES); 
        em.setPersistenceUnitName(PERSISTENCE_UNIT_NAME);
        em.setPersistenceXmlLocation(PERSISTENCE_UNIT_LOCATION);
        em.setJpaProperties(jpaProperties());
        em.afterPropertiesSet();
        return em.getObject();
    }

    @Bean
    public JpaTransactionManager transactionManager() {
        JpaTransactionManager tm = new JpaTransactionManager();
        tm.setEntityManagerFactory(entityManagerFactory());
        return tm;
    }

    public Properties jpaProperties() {
        Properties properties = new Properties();
        properties.setProperty("hibernate.dialect", "org.hibernate.dialect.HSQLDialect");
        properties.setProperty("hibernate.hbm2ddl.auto", "update");
        properties.setProperty("hibernate.show_sql", "true");
        properties.setProperty("hibernate.cache.provider_class", "org.hibernate.cache.HashtableCacheProvider");
        return properties;
    }

}

And this is one of the tests:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {TestContextConfiguration.class})
@TestExecutionListeners({ DependencyInjectionTestExecutionListener.class,
        DbUnitTestExecutionListener.class,
        TransactionalTestExecutionListener.class })
public class GestionUsuarioServiceDbunitTest {

    @Autowired
    private UserServiceImpl userService;

    @Test
    @DatabaseSetup("/META-INF/dataset-test.xml")
    public void testFindByLogin() throws Exception {

        User user = userService.findByLogin("admin");

        assertEquals("Admin", user.getNombre());
    }
}

When we run it we get the following error:

Caused by: org.hsqldb.HsqlException: user lacks privilege or object not found: NUMBER
    at org.hsqldb.error.Error.error(Unknown Source)
    at org.hsqldb.ParserDQL.readTypeDefinition(Unknown Source)
    at org.hsqldb.ParserDDL.readColumnDefinitionOrNull(Unknown Source)
    at org.hsqldb.ParserDDL.compileCreateTableBody(Unknown Source)
    at org.hsqldb.ParserDDL.compileCreateTable(Unknown Source)
    at org.hsqldb.ParserDDL.compileCreate(Unknown Source)
    at org.hsqldb.ParserCommand.compilePart(Unknown Source)
    at org.hsqldb.ParserCommand.compileStatements(Unknown Source)
    at org.hsqldb.Session.executeDirectStatement(Unknown Source)
    at org.hsqldb.Session.execute(Unknown Source)
    ... 110 more

Note that I already told the DB sql.syntax‌​_ora=true

What's happening here?

diminuta
  • 1,545
  • 8
  • 32
  • 55
  • 1
    Another good example why using a different DBMS for testing and production is not a good idea. And why letting the obfuscation layer (aka ORM) create tables isn't a good idea either. –  Feb 10 '17 at 13:26
  • Yeah that's obvious, but it's not my call. I'm just looking for a solution to the problem we have now. And the problem we have now is the one I'm describing. – diminuta Feb 10 '17 at 13:28
  • What if you tried `@Column(precision=6, scale=2)` in the column definition, instead of `@Column(columnDefinition="NUMBER(6,2))"`? I.e. portable JPA syntax instead of native Oracle syntax. – Mick Mnemonic Feb 10 '17 at 13:29
  • @MickMnemonic I already tried that, and then we got a different error. I think then Oracle wanted to have a double precision data type instead of number. – diminuta Feb 10 '17 at 13:36
  • @GurV thanks but solved nothing for me :( we are already using version 2 – diminuta Feb 10 '17 at 13:37
  • What is the exact Oracle error you get when using `precision` and `scale`? – Mick Mnemonic Feb 10 '17 at 13:43
  • @MickMnemonic: Caused by: org.hibernate.tool.schema.spi.SchemaManagementException: Schema-validation: wrong column type encountered in column [height] in table [Person]; found [number (Types#DECIMAL)], but expecting [double precision (Types#DOUBLE)] – diminuta Feb 10 '17 at 13:49
  • Okay, then, perhaps you could have the fields in the Entity use data type `Float` instaed of `Double`? Or if that's not possible, extend Oracle dialect to map DOUBLE types into FLOATs [like this](http://stackoverflow.com/questions/2524966/hibernate-found-float-expected-double-precision/13272074#13272074) – Mick Mnemonic Feb 10 '17 at 14:07
  • 1
    The stack trace indicates sql.syntax_ora is not being used. You need to use the latest HSQLDB version (2.3.4). Version 2.0.0 did not support syntax compatibility modes. – fredt Feb 10 '17 at 14:08
  • 1
    What's the datatype of the Column in Oracle? Perhaps Numeric(6,2)? That would map to a BigDecimal, not Double by default I think. – tom Feb 11 '17 at 12:06
  • I changed it to BigDecimal and everything is fine :) – diminuta Feb 13 '17 at 09:01

0 Answers0