嗨,我正在尝试加入3个表并使用以下查询获取集体结果,即dto
SELECT f.id, u.email,
count(distinct l.id) as likes_count,
count(distinct c.id) as comments_count
FROM feeds f
INNER JOIN users u ON f.user_id = u.id
INNER JOIN likes l on l.feed_id = f.id
left join comments c on c.feed_id = f.id
WHERE u.id = 12055
group by f.id order by comments_count asc;
此查询在mysql工作台中工作正常,当我尝试将此查询添加到@Query
注释中时,我正在解决AbstractJpaQuery$TupleConverter$TupleBackedMap
异常,对此的解决方法是使用ContructorExpression
我添加了{ {1}}表达式,但我无法正常工作,我的数据库实体如下所示
new
上述SQL查询的自定义DTO对象:
@Entity
@Table(name = "feeds")
@NoArgsConstructor
public class Feed {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Getter
@Setter
Long id;
@Getter
@Setter
@Column(columnDefinition = "TEXT")
String content;
public Feed(String content, User user) {
this.content = content;
this.user = user;
}
@ManyToOne(optional = false, cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@Getter
@Setter
User user;
@OneToMany(mappedBy = "feed", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
@Getter
@Setter
List<Like> likes;
@OneToMany(mappedBy = "feed", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
@Getter
@Setter
List<Comment> comments;
@Override
public String toString() {
return "Feed{" +
"id=" + id +
", user=" + user +
'}';
}
}
@NoArgsConstructor
@AllArgsConstructor
public class FeedDetails {
@Getter
@Setter
private Long id;
@Getter
@Setter
private Long likes;
@Getter
@Setter
private Long comments;
}
方法如下:
Repository
我不确定我在@Query("**sql_query**")
List<FeedDetails> findAllFeedsByUserId(Long userId);
中写了什么叫喊,以便得到正确的sql_query
FeedDetails
结果。
答案 0 :(得分:1)
您不能对本机查询使用构造函数表达式(NEW运算符)。
您可以使用JPA构造函数结果。看起来像:
Query q = em.createNativeQuery(
"SELECT c.id, c.name, COUNT(o) as orderCount, AVG(o.price) AS avgOrder " +
"FROM Customer c " +
"JOIN Orders o ON o.cid = c.id " +
"GROUP BY c.id, c.name",
"CustomerDetailsResult");
@SqlResultSetMapping(name="CustomerDetailsResult",
classes={
@ConstructorResult(targetClass=com.acme.CustomerDetails.class,
columns={
@ColumnResult(name="id"),
@ColumnResult(name="name"),
@ColumnResult(name="orderCount"),
@ColumnResult(name="avgOrder", type=Double.class)})
})
或者您可以将FeedDetails转换为接口并尝试使用Spring Data JPA Interface投影:https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#projections
或者,如果您不喜欢这些选项,则有一个名为QLRM的小图书馆:https://github.com/simasch/qlrm/blob/master/ConstructorResult.md
答案 1 :(得分:0)
谢谢您的快速解答,我从您的回答中得到了参考,这两种方法都是正确的。关于问题,将我的答案发布在这里:
Feed.java
@Entity
@Table(name = "feeds")
@SqlResultSetMapping(name = "findAllFeedByUserIdMapping",
classes = @ConstructorResult(
targetClass = FeedDetailsClass.class,
columns = {
@ColumnResult(name = "id", type = Long.class),
@ColumnResult(name = "likes", type = Long.class),
@ColumnResult(name = "comments", type = Long.class)
}
)
)
@NamedNativeQuery(name = "findAllFeedByUserIdNamedQuery",
resultClass = FeedDetails.class, resultSetMapping ="findAllFeedByUserIdMapping",
query = "SELECT f.id,count(distinct l.id) as likes, count(distinct c.id) as comments FROM feeds f INNER JOIN users u ON f.user_id = u.id INNER JOIN likes l on l.feed_id = f.id left join comments c on c.feed_id = f.id WHERE u.id = 12055 group by f.id order by comments asc")
@NoArgsConstructor
public class Feed {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Getter
@Setter
Long id;
@Getter
@Setter
@Column(columnDefinition = "TEXT")
String content;
public Feed(String content, User user) {
this.content = content;
this.user = user;
}
@ManyToOne(optional = false, cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@Getter
@Setter
User user;
@OneToMany(mappedBy = "feed", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
@Getter
@Setter
List<Like> likes;
@Fetch(value = FetchMode.JOIN)
@OneToMany(mappedBy = "feed", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
@Getter
@Setter
List<Comment> comments;
@Override
public String toString() {
return "Feed{" +
"id=" + id +
", user=" + user +
'}';
}
}
存储库
@Query(value = "SELECT f.id, f.content, u.name, u.email, " +
"count(distinct l.id) as likes, " +
"count(distinct c.id) as comments " +
"FROM feeds f " +
"INNER JOIN users u ON f.user_id = u.id " +
"INNER JOIN likes l on l.feed_id = f.id " +
"left join comments c on c.feed_id = f.id " +
"WHERE u.id = 12055 " +
"group by f.id " +
"order by comments asc",
nativeQuery = true)
List<FeedDetails> findAllFeedsByUserId(Long userId);
@Query(nativeQuery = true, name = "findAllFeedByUserIdNamedQuery")
List<FeedDetailsClass> findAllFeedByUserIdNamedQuery(Long userId);
接口方法适用于本机查询findAllFeedsByUserId
public interface FeedDetails {
Long getId();
String getContent();
String getEmail();
String getName();
Long getLikes();
Long getComments();
}
模型类方法与SqlResultSetMapping
方法findAllFeedByUserIdNamedQuery配合得很好,我也不得不明确提及列的类型
@Data
@NoArgsConstructor
public class FeedDetailsClass {
@Getter
@Setter
private Long id;
@Getter
@Setter
private Long likes;
@Getter
@Setter
private Long comments;
public FeedDetailsClass(Long id, Long likes, Long comments) {
this.id = id;
this.likes = likes;
this.comments = comments;
}
}