检索表连接的结果

Posted

技术标签:

【中文标题】检索表连接的结果【英文标题】:Retrieving the results of a table join 【发布时间】:2019-10-31 01:12:14 【问题描述】:

在 Spring-Boot 项目中,有两个实体(从 Kafka 消费并)独立地持久化到 PostgreSQL 数据库中。

从语义上讲,它们共享相同的 id,我想加入其中的表并检索结果。

当然,我可以使用本机查询等,但如果可行,我更喜欢更高级的方法。如果这有意义的话,也许检索连接会产生一种新类型的数据类?

这里是一个最小的例子,我的意思是:

@Entity
@Table(name = "foo")
data class Foo(
    @Id
    var id: Long,
    val fooval: Long
)

@Repository
interface FooRepository : JpaRepository<Foo, Long>


@Entity
@Table(name = "bar")
data class Bar(
    @Id
    var id: Long,
    val barval: Long
)

@Repository
interface BarRepository : JpaRepository<Bar, Long>
CREATE TABLE foo(
    id        BIGINT PRIMARY KEY NOT NULL,
    fooval    BIGINT NOT NULL
);

CREATE TABLE bar(
    id        BIGINT PRIMARY KEY NOT NULL,
    barval    BIGINT NOT NULL
);

Foo 不拥有Bar,反之亦然。这些表的清理(实体删除)不是问题。

所以我目前检索连接结果的解决方案如下所示:

@Entity
data class FooBar(
    @Id
    var id: Long,
    val fooval: Long,
    val barval: Long
)

@Repository
interface FooBarRepository : JpaRepository<FooBar, Long> 
    @Query(
        nativeQuery = true,
        value = "SELECT foo.id, fooval, barval FROM foo, bar WHERE foo.id = bar.id;"
    )
    fun fetchAll(): Iterable<FooBar>

但这真的是明智的选择吗?

【问题讨论】:

嗨 Tobias,但是在这种情况下,您是说 FooBar 它是数据库中的一个实体,但事实并非如此,因为在这种情况下,休眠它也会查找表 foo_bar,对吗?我会在没有实体的情况下创建类 FooBar 并在 Foo 或 Bar 的存储库中找到 findAllFooBar() 并从查询内部调用类 FooBar 的构造函数:“SELECT new your.package.FooBar(foo.id , fooval, barval) 来自 foo, bar WHERE foo.id = bar.id" @Brother "对于休眠,在这种情况下它也会查找表 foo_bar,对吧" 只要在 FooBarRepository 上只调用 fetchAll,但没有其他方法,它就可以工作.但是,您当然是完全正确的,这并不理想。我会试试你的建议。 我试过this,但结果是java.lang.IllegalArgumentException: Validation failed for query for method public abstract java.lang.Iterable entityrelationtest.FooRepository.findAllFooBar()。你看到我做错了吗? 从 FooBar 中删除 @entity,然后在查询中你有表 Foo 但它是 foo.id ..(区分大小写) @Brother 谢谢。当前代码:gist.github.com/Dobiasd/8a191c4bc5a395ba3e79d9ac8c4ecbefSELECT new entityrelationtest.FooBar(foo.id, fooval, barval) FROM foo, bar WHERE foo.id = bar.id 结果为QuerySyntaxException: foo is not mapped [SELECT new entityrelationtest.FooBar(foo.id, fooval, barval) FROM foo, bar WHERE foo.id = bar.id]SELECT new entityrelationtest.FooBar(Foo.id, fooval, barval) FROM Foo, Bar WHERE Foo.id = Bar.id 的结果是 IllegalArgumentException: Validation failed for query ... 知道还有什么问题吗? 【参考方案1】:

这是您的场景在本地工作和测试的实现:

package entityrelationtest

import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.data.jpa.repository.Query
import org.springframework.stereotype.Repository
import javax.persistence.Entity
import javax.persistence.Id
import javax.persistence.Table

@Entity
@Table(name = "foo")
data class Foo(
    @Id
    var id: Long,
    val fooval: Long
)

@Entity
@Table(name = "bar")
data class Bar(
    @Id
    var id: Long,
    val barval: Long
)

data class FooBar(
    @Id
    var id: Long,
    val fooval: Long,
    val barval: Long
)

@Repository
interface FooRepository : JpaRepository<Foo, Long> 
    @Query(value = "SELECT new entityrelationtest.FooBar(f.id, f.fooval, b.barval) FROM Foo f, Bar b WHERE f.id = b.id")
    fun findAllFooBar(): Iterable<FooBar>


@Repository
interface BarRepository : JpaRepository<Bar, Long>

@SpringBootApplication
class Application

fun main(args: Array<String>) 
    runApplication<Application>(*args)

还缺少表的别名。并且 SELECT new to JPA 为每一行创建一个对象。

【讨论】:

以上是关于检索表连接的结果的主要内容,如果未能解决你的问题,请参考以下文章

Hibernate检索(下)

Oracle 多表查询

从内部连接表中检索最新记录

如何加入我的结果以检索另一个表的相应记录?

从多对多连接表中检索行的 HQL 查询

MySQL使用连接实现多表检索