在 HQL 中使用 SELECT DISTINCT
Using SELECT DISTINCT in HQL
我一直在研究私人消息传递数据库模式,目前我正在尝试构建一个基本的数据库模式来存储和检索消息——没什么太复杂的。
这是消息实体:
@Entity
@Table(name="messages")
class Message {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="id", unique=true, nullable = false)
private int id;
@ManyToOne(cascade = CascadeType.MERGE)
@JoinColumn(name = "thread_id")
private Thread thread_id;
@Column(name="sent_date")
private Date sent_date;
@Column(name="message_body")
private String message_body;
@JoinColumn(name = "sender_id")
private User sender;
@JoinColumn(name = "receiver_id")
private User receiver;
// getters and setters
}
Thread 实体只是一个 id :
@Entity
@Table(name="threads")
class Thread {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="id", unique=true, nullable = false)
private int id;
// getters and setters
}
这是调用我的查询的方法:
public List<Message> getDistinctMessagesForUser(int id) {
return em.createQuery("SELECT m FROM Message m WHERE m.thread_id IN (SELECT DISTINCT m.thread_id FROM Message m WHERE (m.sender.id =:id OR m.receiver.id =:id)) ORDER BY m.sent_date DESC", Message.class)
.setParameter("id", id)
.getResultList();
}
我正在使用 HQL 查询数据库。我正在尝试使用 SELECT DISTINCT 获取每个线程的最新消息,但我似乎无法使其工作。
我试过用这个:
SELECT m FROM Message m WHERE (m.sender.id =:id OR m.receiver.id =:id) GROUP BY m.thread_id ORDER BY m.sent_date DESC)
但我一直收到此错误:
ERROR: column "message0_.id" must appear in the GROUP BY clause or be used in an aggregate function
我也试过 link 中显示的方法,但错误是由于查询有 e 和 m。
我尝试的所有其他查询要么返回所有消息(而不是不同的消息),要么抛出我上面描述的错误。我不想使用 CriteriaAPI,因为我读到它比 HQL 慢,而我的其他代码是用 HQL 编写的,我打算坚持使用一种方法。
我错过了什么?
DISTINCT
在这种情况下有效,它应该有效。问题出在你的逻辑上,因为你在子查询中检索不同的 thread
实体,然后你的外部查询根据子查询的结果集检索 message
,但你没有得到唯一的 'message' 实体,因为每个 message
实体都可以与几个甚至唯一的 thread
关联。
我建议更改
的查询
List<MyMessage> myMes = em.createQuery(
"SELECT m from MyMessage m where m.id "
+ "in (select min(m2.id) from MyMessage m2 group by m2.thread_id) "
+ "and (m.sender.id =:id OR m.receiver.id =:id)", MyMessage.class)
.setParameter("id", 1L)
在这里,我们通过获取最早的消息(通过 message
的 PK(或 ID))在 via min()
.
我一直在研究私人消息传递数据库模式,目前我正在尝试构建一个基本的数据库模式来存储和检索消息——没什么太复杂的。 这是消息实体:
@Entity
@Table(name="messages")
class Message {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="id", unique=true, nullable = false)
private int id;
@ManyToOne(cascade = CascadeType.MERGE)
@JoinColumn(name = "thread_id")
private Thread thread_id;
@Column(name="sent_date")
private Date sent_date;
@Column(name="message_body")
private String message_body;
@JoinColumn(name = "sender_id")
private User sender;
@JoinColumn(name = "receiver_id")
private User receiver;
// getters and setters
}
Thread 实体只是一个 id :
@Entity
@Table(name="threads")
class Thread {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="id", unique=true, nullable = false)
private int id;
// getters and setters
}
这是调用我的查询的方法:
public List<Message> getDistinctMessagesForUser(int id) {
return em.createQuery("SELECT m FROM Message m WHERE m.thread_id IN (SELECT DISTINCT m.thread_id FROM Message m WHERE (m.sender.id =:id OR m.receiver.id =:id)) ORDER BY m.sent_date DESC", Message.class)
.setParameter("id", id)
.getResultList();
}
我正在使用 HQL 查询数据库。我正在尝试使用 SELECT DISTINCT 获取每个线程的最新消息,但我似乎无法使其工作。
我试过用这个:
SELECT m FROM Message m WHERE (m.sender.id =:id OR m.receiver.id =:id) GROUP BY m.thread_id ORDER BY m.sent_date DESC)
但我一直收到此错误:
ERROR: column "message0_.id" must appear in the GROUP BY clause or be used in an aggregate function
我也试过 link 中显示的方法,但错误是由于查询有 e 和 m。
我尝试的所有其他查询要么返回所有消息(而不是不同的消息),要么抛出我上面描述的错误。我不想使用 CriteriaAPI,因为我读到它比 HQL 慢,而我的其他代码是用 HQL 编写的,我打算坚持使用一种方法。 我错过了什么?
DISTINCT
在这种情况下有效,它应该有效。问题出在你的逻辑上,因为你在子查询中检索不同的 thread
实体,然后你的外部查询根据子查询的结果集检索 message
,但你没有得到唯一的 'message' 实体,因为每个 message
实体都可以与几个甚至唯一的 thread
关联。
我建议更改
的查询List<MyMessage> myMes = em.createQuery(
"SELECT m from MyMessage m where m.id "
+ "in (select min(m2.id) from MyMessage m2 group by m2.thread_id) "
+ "and (m.sender.id =:id OR m.receiver.id =:id)", MyMessage.class)
.setParameter("id", 1L)
在这里,我们通过获取最早的消息(通过 message
的 PK(或 ID))在 via min()
.