spring - Spring Boot jpa 防止自动更新
问题描述
我有一个关于 Jpa 和并发访问的问题。这里有一个示例代码
用户
@Entity
public class User {
@Id
@GeneratedValue
private Long id;
private String firstName;
private String lastName;
...
用户服务
public class UserService {
private final UserRepository userRepository;
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
@Transactional
public String getFirstName(Long userId) throws InterruptedException {
User user = userRepository.findById(userId).get();
Thread.sleep(5000L); // 5s
// ...
return user.getFirstname();
}
@Transactional
public void updateUser(Long userId, String firstName, String lastName) {
User user = userRepository.findById(userId).get();
user.setFirstname(firstName);
user.setLastname(lastName);
userRepository.save(user);
}
}
如果我同时调用两个端点(POST 之前的 GET),getFirstName 方法将覆盖更新,因为在事务结束时,即使没有更新,JPA 也会进行隐式保存。我的更新将被覆盖,因为在我的 getFirstName 方法开始时,我用旧的名字加载用户
如果我们不调用存储库的保存方法,有没有办法禁用同步?我不想每次都分离实体。此外,我不想将事务置于只读状态(也许我需要在 getFirstName 方法中更新另一个实体)。
如果我没有进行任何更改,我不希望 JPA 自动保存我的实体。由于并发访问,这可能是一个问题。
谢谢
编辑(解决)
我为属性用户使用了转换器
@Entity
public class User {
@Id
@GeneratedValue
private Long id;
private String firstName;
private String lastName;
@Convert(converter = SimpleConverter.class)
private customObject object;
...
@Component
@Converter
public class SimpleConverter implements AttributeConverter<CustomObject, String> {
private static ObjectMapper objectMapper;
@SneakyThrows
@Override
public String convertToDatabaseColumn(CustomObject object) {
if (Objects.isNull(object)) {
return null;
}
return objectMapper.writeValueAsString(object);
}
@SneakyThrows
@Override
public CustomObject convertToEntityAttribute(String data) {
if (StringUtils.isBlank(data)) {
return null;
}
return objectMapper.readValue(data, CustomObject.class);
}
@Autowired
public void setObjectMapper(ObjectMapper objectMapper) {
TutorialConverter.objectMapper = objectMapper;
}
}
我无法解释为什么,但是使用此转换器,即使我没有进行任何更改,我的实体也会在每次事务结束时在数据库中更新。
我删除了这个属性,现在当两个方法同时执行时,getFirstName 方法不会覆盖数据
编辑 2
CustomObject 类没有 equals 方法……大错误。这解释了这种行为。谢谢 !
解决方案
通过删除@Transactional,persistanceContext 将不会被刷新。或者你可以有@Transactional(readOnly=true)。您可以在此处阅读更多信息:https ://vladmihalcea.com/spring-read-only-transaction-hibernate-optimization/
推荐阅读
- r - 通过闪亮编织文档的进度条
- c++ - 使用 `typedef` 强制类型约束
- react-native - 从最里面的堆栈屏幕导航到最外面的堆栈屏幕时出现白屏死机
- typo3 - 将 .htm 格式的旧 TYPO3 tt_address 模板转换为最新的 tt_address
- validation - Tkinter checkbutton bind 不取更新值
- python - 从 .csv 文件传输到文本文件的数据中删除 'b 和 \n
- html - 如何为 bootstrap 3 nav-tabs 添加填充
- xamarin.forms - 将大图片上传到 FTP 会冻结应用程序
- java - Java:同一类的另一个实例的访问方法
- fullcalendar - fullcalendar 是否支持导出到 Google 日历?