我想测试一种通过在循环中调用 DAO 将数据插入表的服务方法。服务方法被注释为
@Transactional(propagation = Propagation.REQUIRES_NEW)
Run Code Online (Sandbox Code Playgroud)
单元测试调用服务方法并用
@Transactional
Run Code Online (Sandbox Code Playgroud)
现在我想告诉事务,它始终应该在最后进行回滚。我不想在测试运行后手动清理数据库。
@Rollback 和 EntityManager.getTransaction().setRollbackOnly() 不起作用。我认为原因是注释和 setRollbackOnly() 仅应用于由测试方法创建的事务,而不应用于由服务方法创建的事务。
有谁知道如何解决这个问题?
@Transactional
public MyEntity getEntity(long id) {
return dao.findOne(id);
//or select and update as well
}
Run Code Online (Sandbox Code Playgroud)
每次调用事务方法时:我会从休眠中获取任何缓存的实体吗(第一次除外)?或者我总是会从数据库中获取新的实体?
这很重要,因为我将有两个独立的应用程序共享同一个数据库,并且我想确保 hibernate 不会返回任何缓存的实体,而另一个应用程序可能已经在后台更新了数据库中的同一个实体。
我有一个 JDBC 批量更新操作可能需要很长时间,因此我使用事务超时来处理这个。
@Override
@Transactional(propagation=Propagation.REQUIRES_NEW,timeout=10)
public void saveAllUsingBatch(List<KillPrintModel> list){
PreparedStatmentMapper ps= new HibernateDao.PreparedStatmentMapper<KillPrintModel>() {
@Override
public void prepareStatement(PreparedStatement ps, KillPrintModel t)
throws SQLException {
ps.setString(1, t.getOffice());
ps.setString(2, t.getAccount());
ps.setDate(3, new java.sql.Date(t.getUpdatedOn().getTime()));
}
};
String sql = String.format("INSERT INTO dbo.%s (%s,%s,%s) VALUES (?,?,?)",KillPrintModel.TABLE_NAME,KillPrintModel.FIELD_Office,KillPrintModel.FIELD_Account,KillPrintModel.FIELD_UpdatedOn);
this.jdbcBatchOperation(list, sql, ps);
}
Run Code Online (Sandbox Code Playgroud)
即使我的事务时间超过 10 秒,此方法也会持续一分钟以上(并成功返回)。当超时为 0 时它工作正常。
是不是因为我的线程一旦开始执行就一直处于运行状态?
我的应用程序是由Spring休息控制器使用redis调用服务.我使用的是spring boot starter redis 1.2.5,我在beans.xml文件中定义了一个模板:
<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
p:host-name="${spring.redis.host}"
p:use-pool="true"
p:port="${spring.redis.port}"
/>
<bean id="redisTemplateForTransaction" class="org.springframework.data.redis.core.RedisTemplate"
p:connection-factory-ref="jedisConnectionFactory"
p:keySerializer-ref="stringRedisSerializer"
p:valueSerializer-ref="jsonRedisSerializerForTransaction"
p:enableTransactionSupport="true">
<qualifier value="redisTemplateForTransaction" />
</bean>
Run Code Online (Sandbox Code Playgroud)
当我启动超过8个查询时,我的应用程序阻止.我知道我已达到池中的默认连接数.
为什么在请求处理结束时没有自动返回连接?
如何在事务模式下工作,以便任何传入的请求将获得其redis连接并在处理结束时返回它?
@Transactional在集成测试期间,我需要忽略以下注释。
@Service
public class MyClass {
@Transactional(propagation = Propagation.NEVER)
public void doSomething() {
// do something that once in production can not be inside a transaction (reasons are omitted)
}
}
Run Code Online (Sandbox Code Playgroud)
问题是我所有的测试都是在默认回滚的事务中执行的。@Transactional(propagation = Propagation.NEVER)当此方法在测试 ( @ActiveProfiles("test"))范围内运行时,我怎么能忽略它的注释,允许它在事务内执行?
@Transactional在Spring中使用注解方法时,注解方法的返回是否与底层数据库事务的成功提交同步?
(这是假设事务在返回后实际上会提交,这可能不是这种情况,具体取决于所选的传播方法。)
如果等待提交不是默认行为,有没有办法通过配置或其他方式启用它?
我的问题的动机是我想实现一个可靠的“存储和转发”类型的端点,它只在调用的影响被提交到稳定存储后才向客户端返回响应。这可能@Transactional吗?
这并不完全像标题所说的那样,但接近。考虑这些 Spring bean:
@Bean
class BeanA {
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = EvilException.class)
public void methodA() {
/* ... some actions */
if (condition) {
throw new EvilException();
}
}
}
@Bean
class BeanB {
@Autowired private BeanA beanA;
final int MAX_TRIES = 3;
@Transactional(propagation = Propagation.NESTED)
public void methodB() {
// prepare to call Bean A
try {
beanA.methodA();
/* maybe do some more things */
}
catch (EvilException e) {
/* recover from evil */
}
}
} …Run Code Online (Sandbox Code Playgroud) 我正在使用Spring Data MongoDB(2.2.5)和MongoDB 4.2.5 社区版本测试事务回滚功能。正如Spring Data官方文档中提到的,我在配置类中配置了MongoTransactionManager,并在后端创建了一个包含3个成员的副本集。
此外,还使用了 mongo 数据库事务存储库。使用@Transactional注释了我的Dao方法。即使我已经在方法中实现了事务范围,我的数据仍然保存在集合中(人员以及地址),并且在应用程序中的运行时异常上数据库层没有发生回滚。我已经提供了我的应用程序所需的源代码和跟踪。请帮助解决真实问题,如果我遗漏了任何内容,请告诉我。
@Slf4j
@Configuration
@EnableMongoRepositories
@EnableTransactionManagement(proxyTargetClass=true)
class ApplicationConfig extends AbstractMongoClientConfiguration {
@Bean
MongoTransactionManager transactionManager(MongoDbFactory dbFactory) {
log.info("Creating dbFactory {}", dbFactory);
MongoTransactionManager manager=new MongoTransactionManager(dbFactory);
log.info("Creating manager {}",manager);
return manager;
}
@Override
public MongoClient mongoClient() {
return MongoClients.create("mongodb://localhost:27020,localhost:27021,localhost:27022/?replicaSet=rs0");
}
@Override
protected String getDatabaseName() {
return "testDB";
}
public @Bean MongoTemplate mongoTemplate() {
return new MongoTemplate(mongoClient(), "testDB");
}
}
@Slf4j
@Service("TestDao")
public class TestDaoImpl implements TestDao{
@Autowired
PersonRepository repository;
@Autowired
MongoOperations ops;
@Autowired …Run Code Online (Sandbox Code Playgroud) 对于这个基于spring-boot-starter-data-jpa依赖和H2内存数据库的实验项目,我定义了一个User具有两个字段(id和firstName)的实体,并UsersRepository通过扩展CrudRepository接口声明了一个。
现在,考虑一个简单的控制器,它提供两个端点:/print-user读取同一用户两次,间隔打印其名字,并/update-user用于在两次读取之间更改用户的名字。请注意,我特意设置了Isolation.READ_COMMITTEDlevel 并期望在第一次事务过程中,通过相同 id 检索两次的用户将具有不同的名称。但是相反,第一笔交易打印出两次相同的值。为了更清楚,这是完整的操作序列:
jeremy的名字设置为Jeremy。/print-userwhich 打印出来Jeremy并进入睡眠状态。/update-user从另一个会话调用,它将jeremy的名字更改为Bob.jeremy用户时,Jeremy即使名字已经更改为他的名字,它也会再次打印出来Bob(如果我们打开数据库控制台,它现在确实存储为Bob,不是Jeremy)。似乎在这里设置隔离级别没有任何影响,我很好奇为什么会这样。
@RestController
@RequestMapping
public class UsersController {
private final UsersRepository usersRepository;
@Autowired
public UsersController(UsersRepository usersRepository) {
this.usersRepository = usersRepository;
}
@GetMapping("/print-user")
@ResponseStatus(HttpStatus.OK)
@Transactional (isolation = Isolation.READ_COMMITTED) …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用 Kotlin 的 Arrow 库Either对象来处理项目中的异常。
到目前为止,我的经验还不错,但我正在努力寻找一种方法来处理事务Either,特别是回滚。在 Spring 中抛出 aRuntimeException是导致事务回滚的可靠方法。但是,通过使用Either不会引发异常,因此不会触发回滚。
您可以将此视为一个多方面的问题:
Either适合真实Exception处理?不是替代控制流,我的意思是程序流需要停止的真正错误情况。transactionManager编程方式使用- 你能避免这种情况吗?Either?spring ×8
java ×7
arrow-kt ×1
hibernate ×1
jdbc ×1
jpa ×1
junit ×1
kotlin ×1
redis ×1
spring-boot ×1
spring-mvc ×1
transactions ×1