首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >传递给持久化的分离实体- on findByMethod

传递给持久化的分离实体- on findByMethod
EN

Stack Overflow用户
提问于 2022-05-11 09:16:09
回答 1查看 480关注 0票数 5

我理解错误消息,我知道如何解决它,但我想知道为什么它发生在这个特定的地方,特别是在查找方法上。我为此创建了一个小例子。

我有三个实体:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Entity
data class Animal(
    var name: String,
    @ManyToOne(cascade = [CascadeType.ALL]) val zoo: Zoo) {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    var id: Int = -1
}

@Entity
data class Zoo(
    var city: String,
    @OneToMany(cascade = [CascadeType.ALL]) val employee: MutableList<Person>) {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    var id: Int = -1
}

@Entity
data class Person(var age: Int) {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    var id: Int = -1
}

服务:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
   @Transactional
    fun save(name:String, city: String){
        repo.findByZooCity(city).ifPresent {
            it.zoo.employee.add(Person(22))
        }
        repo.findByZooCity("OTHER STRING!!!!").ifPresent { println("FOUND!") }
        repo.save(Animal(name, Zoo(city, mutableListOf(Person(33)))))
    }

回购:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
interface AnimalRep: JpaRepository<Animal, Int>{

    fun findByZooCity(name: String): Optional<Animal>
}

呼叫:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  animalService.save("Zoo1", "Animal1")
  animalService.save("Zoo1", "Animal1")

例外情况:在第二个调用中,我在repo.findByZooCity("OTHER STRING!!!!")上得到一个“传递到持久化的独立实体:repo.findByZooCity("OTHER STRING!!!!")”。我知道这是因为我之前添加了一个“独立”的人。但是为什么会发生在findBy上呢?(甚至没有结果?)

有脏支票吗?

谢谢你的时间和帮助。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-05-15 11:46:31

这种行为取决于FlushMode of EntityManager

FlushMode定义新实体以及对现有实体的更改何时写入数据库,换句话说,定义flush()操作执行的时间。

刷新过程通过检测状态更改和执行SQL语句来同步数据库状态和会话状态。

JPA规范将FlushModeType.AUTO定义为默认的刷新模式。它在接下来的情况下刷新持久性上下文:

  • 在事务提交之前
  • 在执行使用持久性上下文包含任何挂起更改的任何数据库表的查询之前。

根据文档

自动 在执行查询之前,有时会刷新会话,以确保查询永远不会返回陈旧状态。这是默认的刷新模式。

摘要:

因此,在您的示例中,我们有默认的FlushMode.AUTO,在查询执行框架执行flush()操作期间,这就是原因。

FlushMode.AUTO在查询的基础上解决了一致性问题,但另一方面也会导致不可预测的刷新操作,从而导致大型服务的性能问题。当您不需要解决一致性问题时,我建议将FlushMode改为COMMITFlushModeType.COMMIT在提交事务之前需要刷新,但没有定义在执行查询之前需要发生什么。执行任何查询都不会刷新任何挂起的更改。

FlushMode**:** Changing

1.全局服务器添加到属性

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
spring.jpa.properties.org.hibernate.flushMode=COMMIT

2.为特定查询设置

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Query quey = entityManager.createQuery("SELECT * from Foo");
quey.setFlushMode(FlushModeType.COMMIT);

Session设置为3.

EntityManager注入您的服务。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
   @Transactional
    fun save(name:String, city: String){
        entityManager.setFlushMode(FlushModeType.COMMIT)
        ...
    }

在JPA和Hibernate中自动刷新策略是如何工作的?上详细描述

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

https://stackoverflow.com/questions/72205108

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文