gpt4 book ai didi

java - 由于内部联接而不是左联接,Spring DTO 投影查询不会返回所有结果

转载 作者:行者123 更新时间:2023-11-30 05:44:38 26 4
gpt4 key购买 nike

我正在尝试在具有订单列表的实体User 上获取简单的 DTO 投影。投影应仅包含用户的名字、姓氏和链接表中的订单数。

用户类:

@Entity
@Table(name = "user")
public class User {

@Column(name = "firstName")
private String firstName;

@Column(name = "lastName")
private String lastName;

@OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
private Set<Order> orders;

// many other fields here

}

订单类:

@Entity
@Table(name = "order")
public class Order {

@ManyToOne
@JoinColumn(name = "user_id")
private User user;

// many other fields here

}

然后我就有了 DTO 对象:

public class UserDetailOrderCountDto {

private String firstName;
private String lastName;
private int orderCount;

public UserDetailOrderCountDto(String firstName, String lastName, int orderCount) {
this.firstName = firstName;
this.lastName = lastName;
this.orderCount = orderCount;
}

// getters, setters, ...

}

最后是带有查询的存储库:

public interface UserRepository extends JpaRepository<User, Long> {

@Query("select new a.b.c.UserDetailOrderCountDto(u.firstName, u.lastName, size(u.orders)) from User u group by u.firstName, u.lastName")
List<UserDetailOrderCountDto> findUsersAndOrderCount();

}

数据库包含 2 个用户的 2 个订单。有很多用户没有任何订单(我仍然希望收到 orderCount 为 0 的订单)。存储库中的查询为 2 个用户返回 2 个 DTO,每个用户有 1 个订单(正确),但没有订单的用户将被跳过(因为它不是左连接)。 Hibernate生成的查询如下:

从用户 user0_ 中选择 user0_.firstName 作为 col_0_0_,user0_.lastName 作为 col_1_0_,count(orders1_.user_id) 作为 col_2_0_,订单orders1_,其中 user0_.id=orders1_.user_id 按 user0_.firstName 、 user0_.lastName 分组

如何强制 Hibernate 为我提供所有用户(又名左连接,但如果可能的话,没有 native 查询)?或者有其他方法来获得我想要的解决方案吗?任何帮助表示赞赏。谢谢。

更新 1:如果我尝试强制 Hibernate 使用 FetchMode.JOIN 连接表,它仍然使用内部连接。

@OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
@Fetch(FetchMode.JOIN)
private Set<Order> orders;

查询如下所示:

从用户 user0_ 交叉联接订单orders1_ 中选择 user0_.firstName 作为 col_0_0_、user0_.lastName 作为 col_1_0_、count(orders1_.user_id) 作为 col_2_0_,其中 user0_.id=orders1_.user_id 按 user0_.firstName 、 user0_ 分组。姓氏

最佳答案

JPA 查询

您可以按照下一种方法指示左连接:

  @Query("SELECT new com.your.package.dto.UserDetailOrderCountDto(u.firstName, u.lastName, COUNT(o)) "
+ "FROM User u LEFT JOIN u.orders o group by u.firstName, u.lastName")
List<UserDetailOrderCountDto> findUsersAndOrderCount();

只需确保将类属性 orderCount 更改为 long:

public class UserDetailOrderCountDto {
private String firstName;
private String lastName;
private long orderCount;

public UserDetail() {
}

public UserDetail(String firstName, String lastName, long orderCount) {
this.firstName = firstName;
this.lastName = lastName;
this.orderCount = orderCount;
}

// Getters and setters
}

注意,这适用于您的 User 类的以下配置:

@OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
private Set<Order> orders;

使用 native 查询

您可以使用 native 查询,这样您就可以定义左连接:

@Query(value = "select u.first_name as firstName, u.last_name as lastName, count(o.id) as orderCount from user u left join orders o on u.id = o.user_id  group by u.first_name, u.last_name;"
, nativeQuery = true)
List<UserDetailOrderCountDto> findUsersAndOrderCount();

您只需确保生成的列名称与您的 bean 的属性名称相匹配。

此外,在最新版本的 spring 上,您不需要创建 bean,您可以定义一个接口(interface),然后 spring 创建一个继承自接口(interface)的 bean:

public interface UserDetailOrderCountDto {
public String getFirstName();
public String getLastName();
public int getOrderCount();
}

关于java - 由于内部联接而不是左联接,Spring DTO 投影查询不会返回所有结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55080817/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com