检索表连接的结果
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 为每一行创建一个对象。
【讨论】:
以上是关于检索表连接的结果的主要内容,如果未能解决你的问题,请参考以下文章