java - Spring Boot JPA 数据:服务层方法没有正在进行的事务异常
问题描述
@Lock(LockModeType.PESSIMISTIC_WRITE)
问题是我无法使用注释的服务层方法来处理简单的项目
@Transactional
。我需要在锁定的实体/数据库行上运行业务逻辑。当我运行应用程序时,它会在会话层引发错误
org.springframework.dao.InvalidDataAccessApiUsageException: no transaction is in progress; nested exception is javax.persistence.TransactionRequiredException: no transaction is in progress
Main class
@SpringBootApplication
@EnableConfigurationProperties
@ConfigurationPropertiesScan
@RequiredArgsConstructor
@Slf4j
@EnableTransactionManagement
public class BackendApplication {
private final BackendConfiguration configuration;
public static void main(String[] args) {
SpringApplication.run(BackendApplication.class, args);
}
}
SessionService
@Service
@RequiredArgsConstructor
@Slf4j
public class SessionService {
final private SessionRepository sessionRepository;
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED)
Session readAndUpdateSession(String sessionId, Function<Session, Session> sessionPreUpdateHandler, String threadName) {
Optional<SessionEntity> forUpdate = sessionRepository.getBySessionId(sessionId);
Session session = new Session(forUpdate.map(SessionEntity::getSessionId).orElse(null), false);
Session updatedSession = sessionPreUpdateHandler.apply(session);
sessionRepository.save(forUpdate.orElse(null));
log.info(" thread [{}] updated session", threadName);
return updatedSession;
}
}
SessionRepository
@Repository
public interface SessionRepository extends JpaRepository<SessionEntity, String> {
@Lock(LockModeType.PESSIMISTIC_WRITE)
Optional<SessionEntity> getBySessionId(String id);
}
并CommandLineRunner
测试
@Component
@RequiredArgsConstructor
@Slf4j
public class CommandLineRunner implements org.springframework.boot.CommandLineRunner {
private final SessionRepository sessionRepository;
private final ApplicationContext applicationContext;
@Override
public void run(String... args) throws Exception {
sessionRepository.save(new SessionEntity().setSessionId("7d010e0a-cf6e-492c-9db4-690a96b4e345"));
log.info("" + sessionRepository.findForUpdate("7d010e0a-cf6e-492c-9db4-690a96b4e345").orElse(null));
new Thread(() -> applicationContext.getBean(SessionService.class).readAndUpdateSession("7d010e0a-cf6e-492c-9db4-690a96b4e345", session -> {
log.info("first thread reading and updating doing business ");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info("first thread return session back ");
return session;
}, "first")).start();
new Thread(() -> applicationContext.getBean(SessionService.class).readAndUpdateSession("7d010e0a-cf6e-492c-9db4-690a96b4e345", session -> {
log.info("second thread reading and updating but first is not accomplished");
log.info("second thread return session back ");
return session;
}, "second")).start();
}
}
最后但并非最不重要application.yml
spring:
datasource:
url: jdbc:postgresql://localhost:5432/backend
hikari:
username: backend
password: backend
driver-class-name: org.postgresql.Driver
connection-timeout: 1000
connection-test-query: SELECT 1
maximum-pool-size: 32
sql-script-encoding: UTF-8
cache:
type: jcache
jpa:
generate-ddl: false
database-platform: org.hibernate.dialect.PostgreSQLDialect
我在互联网上应用了建议,但没有弄清楚如何解决这个问题,
解决方案
推荐阅读
- python - 用两个具有相同字符的分解对象断言 True
- matlab - 在 Matlab 中表示来自 2D 图像的 3D 体积图像
- r - 如何在R中的差异分析中为时间创建一个虚拟变量?
- javascript - 如何从 html 文件中的 java 脚本文件调用另一个函数内部的函数?
- python-3.x - 如果失败(链、link_error 和 get_leaf)如何等待 celery 任务?
- database - 我可以在自己的程序中使用其他防病毒数据库签名吗?
- python - 使用 for 循环对列表进行排序
- android - 如何在表格行中创建 Edittext
- angular - 角度构建编译错误,即使库可用
- node.js - 在 mac m1 bigSur 上 npm 安装 opencv4nodejs 错误