首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >有时不返回最新数据?

有时不返回最新数据?
EN

Stack Overflow用户
提问于 2021-05-28 02:05:43
回答 1查看 576关注 0票数 0

在从一个线程检索实体以及在另一个线程中对其进行修改时,我看到了JPA的“奇怪”行为。下面是我的示例代码来解释这个问题。典型情景:

data

  • 创建学生s1
  • get/打印s1 in s1
  • update s1 details
  • 检查更新后的学生详细信息是否打印在循环
    • 中,它仍然打印旧的

据我所知,JPA具有与每个线程相关联的持久性上下文(PC),因此在其中存储实体。线程不能看到对方的电脑。我认为如果相应的线程在实体上创建/更新操作,PC会得到更新。我认为JPA的这种行为违反了数据库隔离原则。难道不应该把更新的数据从盒子里拿出来吗?还是我在这漏掉了什么?

日志

代码语言:javascript
运行
复制
2021-05-28 07:13:03.503  INFO 7425 --- [nio-8080-exec-2] com.example.demo.StudentController       : Created student... Student{id=1, name='Omkar', score=50}
2021-05-28 07:14:22.272  INFO 7425 --- [nio-8080-exec-4] com.example.demo.StudentController       : Get student Student{id=1, name='Omkar', score=50}
2021-05-28 07:14:27.280  INFO 7425 --- [nio-8080-exec-4] com.example.demo.StudentController       : Get student Student{id=1, name='Omkar', score=50}
2021-05-28 07:14:32.282  INFO 7425 --- [nio-8080-exec-4] com.example.demo.StudentController       : Get student Student{id=1, name='Omkar', score=50}
2021-05-28 07:14:33.748  INFO 7425 --- [nio-8080-exec-5] com.example.demo.StudentController       : Updating student... Student{id=1, name='Omkar', score=75}
2021-05-28 07:14:37.284  INFO 7425 --- [nio-8080-exec-4] com.example.demo.StudentController       : Get student Student{id=1, name='Omkar', score=50}
2021-05-28 07:14:42.288  INFO 7425 --- [nio-8080-exec-4] com.example.demo.StudentController       : Get student Student{id=1, name='Omkar', score=50}

实体

代码语言:javascript
运行
复制
@Entity
public class Student {

    @Id
    private int id;

    private String name;

    private int score;
    ...

存储库

代码语言:javascript
运行
复制
public interface StudentRepository extends JpaRepository<Student, Integer> {
}

控制器

代码语言:javascript
运行
复制
@RestController
@RequestMapping("/api/student")
public class StudentController {

    @Autowired
    private StudentRepository studentRepository;

    private final static Logger LOGGER = LoggerFactory.getLogger(StudentController.class);

    @GetMapping
    public void getStudent() {
        while (true) {
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            Student student = studentRepository.findById(1).orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
            LOGGER.info("Get student {}",student.toString());
        }
    }

    @PostMapping
    public ResponseEntity<Student> updateStudent(@RequestParam("score") int score) {
        Student student = studentRepository.findById(1).orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
        student.setScore(score);
        Student updated = studentRepository.save(student);
        LOGGER.info("Updating student... {}", updated);
        return ResponseEntity.ok(updated);
    }

    @PutMapping
    public ResponseEntity<Student> createStudent(Student student) {
        Student saved = studentRepository.save(student);
        LOGGER.info("Created student... {}", saved);
        return ResponseEntity.created(URI.create("/api/student/" + saved.getId())).body(saved);
    }

}
EN

回答 1

Stack Overflow用户

发布于 2021-05-28 04:38:55

将循环更改为

代码语言:javascript
运行
复制
@GetMapping
public void getStudent() {
    while (true) {
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        entityManager.clear();
        Student student = studentRepository.findById(1).orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
        LOGGER.info("Get student {}",student.toString());
    }
}

基本上,findById的结果会附加到当前事务中,并且查询只会被调用一次(即使是在循环中)。要再次访问数据库,您应该分离该实体。可以通过调用entityManager.clear()来分离实体

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67731984

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档