【发布时间】:2020-12-03 03:54:07
【问题描述】:
我正在努力让查询在 JPQL 中工作。
我有以下实体(精简):
对话
一个对话有很多消息。
一个对话有多个用户对话。
@Entity
@Table(name = "conversations")
data class Conversation(
@Column(nullable = false)
var createdAt: LocalDateTime = LocalDateTime.now(),
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
var id: IDType = 0
) {
@OneToMany(mappedBy = "conversation")
lateinit var messages: MutableSet<Message>
@OneToMany(mappedBy = "conversation")
lateinit var userConversation: MutableSet<UserConversation>
}
留言
许多消息都有一个对话。
@Entity
@Table(name = "messages")
data class Message(
@Column(nullable = false)
var createdAt: LocalDateTime = LocalDateTime.now(),
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
var id: IDType = 0
) {
@ManyToOne(cascade = [CascadeType.MERGE], optional = false)
@JoinColumn(name = "conversation_id", nullable = false)
lateinit var conversation: Conversation
}
用户对话
许多 UserConversation 有一个 Conversation。
@Entity
@Table(name = "user_conversations")
data class UserConversation(
@Column(nullable = false)
var createdAt: LocalDateTime = LocalDateTime.now(),
@Column(nullable = false)
var allowHistory: Boolean = true,
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
var id: IDType = 0
) {
@ManyToOne(cascade = [CascadeType.MERGE], optional = false)
@JoinColumn(name = "conversation_id", nullable = false)
lateinit var conversation: Conversation
}
为了帮助您了解这些实体:想想频道或群聊。
对话就是这样一个群体。
一条消息被发布到该组。
UserConversation 描述了用户与此类组之间的关系。
我要实现的场景:
如果用户不允许查看对话历史记录,则只应显示他加入后的消息。
本机解决方案如下所示:
SELECT messages.*, user_conversations.*
FROM messages
INNER JOIN user_conversations
ON messages.conversation_id = user_conversations.conversation_id
WHERE user_conversations.id IN (42) # I might want to fetch multiple userConversations at once
AND messages.created_at >= IF(user_conversations.allow_history, messages.created_at, user_conversations.created_at)
我想将它放在 JPA 存储库中。
因为我首先要获取消息,所以我想把它放到我的 MessageRepository 中(这不是必须的)。
稍后我需要能够将 userConversations 链接到他们的消息,因此我尝试引入自定义结果:
// query here
fun findAllByUserConversationIdIn(userConversationIds: Collection<IDType>): Collection<UserConversationMessage>
interface UserConversationMessage {
val message: Message
val userConversation: UserConversation
}
这是我想出的 JPQL:
SELECT
m as message,
uc as userConversation
FROM
Message m
INNER JOIN UserConversation uc
ON uc.conversation.id = m.conversation.id
WHERE uc.id IN (?1)
AND m.createdAt >= CASE WHEN uc.allowHistory THEN m.createdAt ELSE uc.createdAt END
但验证失败。
你能帮帮我吗?
干杯
【问题讨论】:
-
有什么例外?
-
@Andronicus ``` 原因:java.lang.IllegalArgumentException:查询方法公共抽象 java.util.Collection fin.message.datasource.MessageRepository.findAllByUserConversationIdIn(java.util.Collection) 的验证失败)!在 org.springframework.data.jpa.repository.query.SimpleJpaQuery.validateQuery(SimpleJpaQuery.java:93) ~[spring-data-jpa-2.2.5.RELEASE.jar:2.2.5.RELEASE] 在 org.springframework。 data.jpa.repository.query.SimpleJpaQuery.
(SimpleJpaQuery.java:63) ~[spring-data-jpa-2.2.5.RELEASE.jar:2.2.5.RELEASE] at (...) `` `
标签: hibernate kotlin spring-data-jpa spring-data