我想知道交易如何在春季工作,或多或少我已经学会了(或者我认为我已经学会了)。唯一没有得到的是如下:为了检查回滚如何实现它的魔力,我创建了一个测试,用@Transacional注释调用一个方法,该方法抛出一个异常,并查看方法更改是否从外部保存。令我惊讶的是,这一变化似乎已经付诸实施。春季交易方法测试不会回滚
这是代码:
import static org.hamcrest.core.IsNull.nullValue;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
import org.springframework.transaction.annotation.Transactional;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import repositories.files.ArchivoEnDisco;
import repositories.files.ArchivosEnDiscoRepo;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = GhcserviceapiApplication.class)
@WebAppConfiguration
public class PruebasSinTransacciones {
@Autowired
ArchivosEnDiscoRepo repositorio;
@Test
public void compruebaTransaccionSinVariable() {
// I get one far away from the last.
Long id = repositorio.count() + 10l;
try {
inTransacction(id);
fail("Exception must be throw");
} catch (Exception e) {
}
// I try to get the saved object
ArchivoEnDisco aedOriginal = repositorio.findOne(id);
assertThat("An exception ocurred so it doesn't have to find it", aedOriginal, nullValue());
}
@Transactional()
private void inTransacction(Long id) throws Exception {
repositorio.save(new ArchivoEnDisco(id, id + "A.txt"));
throw new Exception();
}
}
对于我来说,作为一个例外是抛出事务必须回滚,因此保存对象不需要在仓库中存在。但是当我运行测试时,find方法返回保存的对象。可能有人在我错了什么?
注:GhcserviceapiApplication
是@SpringBootApplication
注释的类。 ArchivosEnDiscoRepo
是CrudRepository
。我在我的pom中有spring-boot-starter-data-jpa
和hsqldb
,但jpa没有配置(所以我在内存中使用hsqldb)。
编辑
我分开,因为@M类。 Deinum评论,并试图使用和具体的rollbackFor
参数,但结果是一样的。
// ConTransacciones.java
// Also tried with Throwable.class
@Transactional(rollbackFor=CustomError.class)
public class ConTransacciones {
public ArchivosEnDiscoRepo repositorio;
public void enTransaccion(Long id) throws CustomError {
repositorio.save(new ArchivoEnDisco(id, id + "A.txt"));
throw new CustomError();
}
}
// CustomError.java
public class CustomError extends Exception { }
// PruebasSinTransacciones.java
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = GhcserviceapiApplication.class)
@WebAppConfiguration
public class PruebasSinTransacciones {
@Autowired
ArchivosEnDiscoRepo repositorio;
@Test
public void compruebaTransaccionSinVariable() {
ConTransacciones ct = new ConTransacciones();
ct.repositorio = this.repositorio;
Long id = repositorio.count() + 10l;
try {
ct.enTransaccion(id);
fail("Debería haberse lanzado una excepción");
} catch (Exception e) {
}
ArchivoEnDisco aedOriginal = repositorio.findOne(id);
assertThat("La transacción no debería haber guardado el archivo", aedOriginal, nullValue());
}
}
这是一个内部方法调用,所以你的'@ Transactional'几乎没用。接下来,即使它不会工作,因为这不是'@ Transactional'在测试用例中的工作方式!此外,您并未测试与数据库相关的任何内容,因此您只测试一级缓存。最后,'@ Transactional'默认情况下只会在'RuntimeException'上回滚而不在'Exception's上。 –
是的,我真的不想测试我的数据库,这个测试只是一种测试我认为交易是如何完成的方式。你能解释一下在测试中@Transactional有什么区别吗? – PhoneixS