Pergunta

Estou tentando executar um script SQL em meu teste JUnit usando Spring.O script está sendo usado para configurar dados para os testes.No entanto, quando o script é executado, os INSERTs no script são confirmados após cada teste.A documentação do Spring diz para não esperar reversão com DDL, mas tudo no meu script é DML.Tudo o que ele contém são instruções INSERT e a obtenção do último ID de inserção (SET @blah = LAST_INSERT_ID()).

Estou configurando algo errado?Estou usando isso em um banco de dados MySQL.Nossa configuração é a seguinte:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "/applicationContext.xml" })
@TransactionConfiguration(defaultRollback = true)
public class OrderTestCase extends AbstractTransactionalJUnit4SpringContextTests {

    @Before
    public void runSql() {
        String fileName = StringUtils.replace(getClass().getName(), ".", "/") + ".sql";
        Resource resource = applicationContext.getResource(fileName);
        if (resource.exists()) {
            executeSqlScript(fileName, false);
        } else {
            LOGGER.debug("Resource doesn't exist: {}", resource);
        }
    }

@Test
public void testLoadOrders() {
    Collection<Order> orders= dao.findAll();
    assertTrue(orders.size() == 3);
}
}

Aqui está o que ACHO que está acontecendo com base em algumas pesquisas.A primeira chamada para executeSqlScript está sendo executada em uma transação separada.O método SimpleJdbcTemplate.update do Spring é chamado por executeSqlScript.Como este é um escopo para uma conexão JDBC, que é obtida de um pool de conexões, não tenho garantia de obter a mesma conexão em acessos subsequentes ao banco de dados e, portanto, não posso garantir a execução na mesma transação.

Se eu fizesse todas as minhas operações de banco de dados por meio do TransactionManager ou (Hibernate Session Factory), isso funcionaria devido à forma como os internos definem o escopo das transações.Minhas opções aqui são:

  1. Descubra como executar SimpleJdbcTemplate.update e o código real subsequente que estou testando na mesma transação.Acho que posso fazer isso, mas meus esforços até agora foram infrutíferos.

  2. Configure todos os meus dados de teste por meio do SessionFactory.Portanto, em vez de executar scripts SQL diretos por meio de JDBC, eu estaria preenchendo objetos de modelo e persistindo-os por meio de um DAO do Hibernate.

Estou no caminho certo aqui?Alguém pode fornecer mais alguma orientação?

Foi útil?

Solução 2

Consegui resolver isso adicionando o seguinte 'jpaVendorAdapter' à declaração da minha entidadeManagerFactory.

<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory">
    <property name="dataSource" ref="dataSource"/>
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
        </property>
</bean>

Outras dicas

Você provavelmente tem a confirmação automática habilitada na conexão db.

<bean id="dataSource" 
    class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
  <property name="driverClassName" value="${jdbc.driverClassName}"/>
  <property name="url" value="${jdbc.url}"/>
  <property name="username" value="${jdbc.username}"/>
  <property name="password" value="${jdbc.password}"/>
  <property name="defaultAutoCommit" value="false"/>
</bean>

Observe que você também pode passar esse argumento no URL jdbc.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top