hibernate - 如何在包含 spring-session-jdbc 时防止数据库在事务方法之外更新
问题描述
我对弹簧事务如何工作的行为有疑问。我不清楚如何正确实施它。仅当我包含依赖项时才会出现问题spring-session-jdbc
。
- 我正在使用 Spring Boot 2.2.6
- 使用休眠/Mariadb
- 启用了 Spring 安全性
InMemoryUserDetailsManager
我有一个方法被注释为@Transactional(readonly=true)
并返回实体的集合。从该方法接收到集合后,在调度之前,我将一些变量设置为不同的值,以不显示或更改它的表示。问题是,在发送输出后,数据库值会自动更新。
总结一下这个问题,我创建了一个基本的 SpringBoot 2.2.6 项目,下面是内容。
客户.java
@Data
@Entity
@Table(name = "customers")
public class Customer {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String name;
private Integer age;
private Integer batch;
private String secret;
}
CustomerRepository.java
@Repository
public interface CustomerRepository extends JpaRepository<Customer, Integer> {
Page<Customer> findByBatch(Integer batchId, Pageable pagaable);
}
CustomerService.java
需要注意的是,在这个服务类中,方法用 注释@Transactional(readOnly = true)
。
@Service
public class CustomerService {
@Autowired
private CustomerRepository repo;
@Transactional(readOnly = true)
public Page<Customer> findAllCustomers() {
Pageable pageable = PageRequest.of(0, 10);
return repo.findByBatch(4, pageable);
}
}
客户控制器.java
@Controller
public class CustController {
@Autowired
private CustomerService service;
@GetMapping("/")
public ResponseEntity<Page<Customer>> indexPath(Model model) {
Page<Customer> customers = this.service.findAllCustomers();
model.addAttribute("customers", customers);
// setting null before sending to client
// this is for demonstration purpose only
customers.getContent().forEach(i -> i.setSecret(null));
return ResponseEntity.ok(customers);
}
}
pom.xml 中的依赖项
- spring-boot-starter-数据-jpa
- spring-boot-starter-百里香叶
- spring-boot-starter-web
- spring-boot-starter-安全
- mariadb-java-client
- 龙目岛
- spring-session-jdbc
并填充下面的数据库是一些 SQL 插入语句。
CREATE TABLE IF NOT EXISTS `customers` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`age` int(11) DEFAULT NULL,
`batch` int(11) DEFAULT NULL,
`name` varchar(255) DEFAULT NULL,
`secret` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM; // changed to InnoDB basedon @M.Deinum comment
INSERT INTO `customers` (`id`, `age`, `batch`, `name`, `secret`) VALUES (1, 94, 4, 'Ravi', '23423424234');
INSERT INTO `customers` (`id`, `age`, `batch`, `name`, `secret`) VALUES (2, 32, 4, 'Silva', '3424252432');
INSERT INTO `customers` (`id`, `age`, `batch`, `name`, `secret`) VALUES (3, 18, 4, 'Rahul', '322342424');
Github 中的示例项目
我将其创建为一个简单的项目,它重现了该问题并将其上传到 Github 的此 URL https://github.com/imuneer/sprintboot-db-issue中。
通过简单地注释掉spring-session-jdbc
pom.xml 中的内容,使项目按预期工作;我在控制器中更新的任何值都没有修改实际的数据库值。但是当spring-session-jdbc
未注释时,它的作用相反。
我在这里很困惑。
- 为什么添加
spring-session-jdbc
更改弹簧事务的行为 - 我是否首先遗漏了任何东西,因此程序在两种情况下的行为都不同?
- 还是我的理解有误?如果是这样,在修改到客户端之前保持集合与持久性上下文分离的正确方法是什么。
解决方案
推荐阅读
- php - 无法获取存储在 MySQL 数据库中的信息
- javascript - 在图表中添加第二条线
- javascript - Node.js 中每个模块的格式是什么?
- android - 安卓:java.lang.IllegalThreadStateException
- php - SQL - ORDER BY 未正确读取位置
- java - 从数据模型访问兄弟数据
- android - 如何在 gradle (android-studio) 中获取 shamsi 日期 [波斯日历]
- android - 用户位置分享
- javascript - 如何使此部分背景响应?
- jmeter - jmeter可以获取参数吗?