java Hibernate:如何在实体中获取Set中实体的特定列?

kuarbcqp  于 2023-06-04  发布在  Java
关注(0)|答案(1)|浏览(125)

我有一个User实体,里面有一个relatedUsers(Set)属性,当获取一个User时,我不想加载relatedUsers中实体的所有属性,只想加载它们的id。我一直在尝试使用实体图来实现这一点,但没有成功。这是我的实体:

@Entity
@Table(name = "USERS")
@NamedEntityGraph(
        name = "User.users",
        attributeNodes = {
                @NamedAttributeNode(value = "users", subgraph = "usersSubgraph")
        },
        subgraphs = {
                @NamedSubgraph(name = "usersSubgraph", attributeNodes = {
                        @NamedAttributeNode("id")
                })
        }
)
public class User {
    public User() {}

    @Id
    @Column(name = "id", unique = true)
    Long id;
    
    @Column(name = "xpto")
    String xpto;
    
    @Column(name = "xpto2")
    String xpto2;
    
    @ManyToMany(fetch = FetchType.LAZY)
    @JoinTable(name = "USERS_USERS",
            joinColumns = @JoinColumn(name = "User_id"),
            inverseJoinColumns = @JoinColumn(name = "users_id"))
    Set<User> users;

    // ... the rest are the getters and setters
}

这是一个查询:

CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<User> cq = cb.createQuery(User.class);

EntityGraph<?> eg = entityManager.getEntityGraph("User.users");

Root<User> root = cq.from(User.class);

Predicate predicate = cb.or(cb.equal(root.get("id"), 1L));

cq.select(root).distinct(true).where(predicate);

TypedQuery<User> tq = entityManager.createQuery(cq);

return tq.setHint("jakarta.persistence.fetchgraph", eg).getSingleResult();

这个查询并没有像我预期的那样执行(假设我理解了实体图的功能),因为实体图似乎什么也没做,因为relatedUsers的实体仍然被完全加载,而不仅仅是加载id。我想做的事有可能吗如果是这样,我该如何完成呢?

8hhllhi2

8hhllhi21#

在Hibernate中,总是获取整个实体对象,不可能只获取实体属性的子集,并且仍然获取该类型的实体。但是,如果只需要某些特定字段,则可以创建一个DTO投影,在其中封装要返回的数据。

public class UserIdProjection {
    private Long id;

    public UserIdProjection(Long id) {
        this.id = id;
    }

    // getter
}

并修改您的查询:

CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<UserIdProjection> cq = cb.createQuery(UserIdProjection.class);

Root<User> root = cq.from(User.class);

Predicate predicate = cb.or(cb.equal(root.get("id"), 1L));

cq.select(cb.construct(UserIdProjection.class, root.get("id"))).distinct(true).where(predicate);

TypedQuery<UserIdProjection> tq = entityManager.createQuery(cq);

List<UserIdProjection> results = tq.getResultList();

这应该返回一个UserIdProjection对象的列表,以及它们相关的用户ID。原始实体不会以这种方式获取。

相关问题