我正在使用Kotlin开发一个Spring JPA/Hibernate应用程序,我想找到一个实体中的所有元素。
下面是示例代码:
@Entity
data class A {
@Id
val id: Long,
@Column
val uuid: UUID,
@Column
val name: String
}
@Entity
data class B {
@Id
val id: Long,
...
@Fetch(FetchMode.JOIN)
@ManyToOne
@JoinColumn(name = "a_uuid", referencedColumnName = "uuid", insertable = false, updatable = false)
val a: A
}
@Repository
interface Repo<B> : CrudRepository<B, Long>
...
repo.findAll() // <-- This triggers N+1 queries instead of making a JOIN
...
您的另一个选择是使用EntityGraph
。它允许通过分组我们想要检索的相关持久性字段来定义模板,并允许我们在运行时选择图类型。
这是一个通过修改代码而生成的示例代码。
@Entity
data class A (
@Id
val id: Long,
@Column
val uuid: UUID,
@Column
val name: String
) : Serializable
@NamedEntityGraph(
name = "b_with_all_associations",
includeAllAttributes = true
)
@Entity
data class B (
@Id
val id: Long,
@ManyToOne
@JoinColumn(name = "a_uuid", referencedColumnName = "uuid")
val a: A
)
@Repository
interface ARepo: CrudRepository<A, Long>
@Repository
interface BRepo: CrudRepository<B, Long> {
@EntityGraph(value = "b_with_all_associations", type = EntityGraph.EntityGraphType.FETCH)
override fun findAll(): List<B>
}
@Service
class Main(
private val aRepo: ARepo,
private val bRepo: BRepo
) : CommandLineRunner {
override fun run(vararg args: String?) {
(1..3L).forEach {
val a = aRepo.save(A(id = it, uuid = UUID.randomUUID(), name = "Name-$it"))
bRepo.save(B(id = it + 100, a = a))
}
println("===============================================")
println("===============================================")
println("===============================================")
println("===============================================")
bRepo.findAll()
}
}
在B
实体上定义了一个名为“B_with_all_associations”的实体图,并将其应用于load
类型的B实体的存储库的findall
方法。
select
b0_.id as id1_1_0_,
a1_.id as id1_0_1_,
b0_.a_uuid as a_uuid2_1_0_,
a1_.name as name2_0_1_,
a1_.uuid as uuid3_0_1_
from
b b0_
left outer join
a a1_
on b0_.a_uuid=a1_.uuid
PS2.当您希望使用join
解决N+1问题时,EntityGraph
可以很好地回答您的问题。但我会推荐更好的解决方案:尝试用惰性加载来解决它。
PS3.使用非PK关联进行Hibernate不是一个好主意。我真的同意这个意见。我认为这是一个尚未解决的bug。它打破了Hibernate的惰性加载机制。
问题内容: 我有以下查询,希望在单个选择请求中运行: 问题在于,所有内容都是通过单独的多个查询获取的。我只希望在单个请求中获取团队和团队的球员以及每个球员的技能。但是取而代之的是,我有多个选择查询来获取每个球队,每个球员,每个球员的统计数据和技能。 以下是带有给定注释的实体: 游戏实体: 团队实体: 玩家实体: 您能指出犯下的错误吗?我需要一个选择查询来加载游戏,它是团队,团队的球员和每个球员的技
默认情况下,Android Pie会要求应用程序使用HTTPS连接而不是HTTP。因此无法在HTTP中命中restful API
问题内容: 我将实体添加到数据库中,并且工作正常。但是,当我检索列表时,会得到旧实体,直到取消取消部署应用程序并再次重新部署它之后,才会显示添加的新实体。这意味着默认情况下会缓存我的实体吗?但是,我没有在persistence.xml或任何此类文件中进行任何用于缓存实体的设置。 我什至尝试调用flush(),refresh()和merge()。但它仍然仅显示旧实体。我想念什么吗?请帮我。 问题答案
我有一个关于Hibernate中乐观锁定的问题。我正试图深入乐观地锁定Hibernate,但我有一个疑问。Hibernate使用版本方法(整数或时间戳)来实现乐观锁定。要进行配置,可以使用@Version注释(或xml配置)并创建版本属性。另一个选项是在不使用乐观lock=“all”属性进行版本控制的情况下进行配置。 我的问题是,如果你没有定义任何版本属性,也没有指定乐观锁属性,在这种情况下,哪种
在MySQL Ver 14.14 Distrib 5.7.25上,对于Linux(x86_64),默认设置似乎不起作用,因为我试图一行,其中包含父表键中不存在的值,而成功了。 为什么我必须,即使在默认情况下设置了? ...我将中,得到了这个... 因此,为了弄清楚为什么不应该成功,但却成功了,我阅读了以下网页... null 外键必须为。是。 默认存储引擎必须为。是的。 对每个外键声明使用。是。
问题内容: 我有以下查询,希望在单个选择请求中运行: 问题在于,所有内容都是通过单独的多个查询获取的。我只希望在单个请求中获取团队和团队的球员以及每个球员的技能。但是取而代之的是,我有多个选择查询来获取每个球队,每个球员,每个球员的数据和技能。 以下是带有给定注释的实体: 游戏实体: 团队实体: 玩家实体: 您能指出犯下的错误吗?我需要一个选择查询来加载游戏,它是团队,团队的球员和每个球员的技能。