【问题标题】:Hibernate hql/criteria result contains collectionHibernate hql/criteria 结果包含集合
【发布时间】:2015-08-29 13:18:53
【问题描述】:

我有两个实体:

public class Photo {
   Long id;
   String url;
   @ManyToOne
   @JoinColumn(name ="user_id")
   User user;
   // other fields and getters/setters
}

第二个:

public class User {
   Long id;
   @OneToMany(mappedBy = "user")
   private Collection<Photo> photos;
   // other fields and getters/setters
}

我正在尝试获取此 DTO:

public class UserDTO {
    Long id;
    List<String> photosUrls;
}

但我找不到正确的解决方案。我写了下一个标准 - 通过登录找到有照片的用户:

getCurrentSession().createCriteria(User.class, "user")
    .createAlias("user.photos", "photos")
    .setProjection(getUserProjection())
    .add(Restrictions.eq("user.login",login))
    .setResultTransformer(Transformers.aliasToBean(UserDTO.class))
    .list();
 // projection   
    getUserProjection() {
        return Projections.projectionList()
            .add(Projections.property("user.id"), "id")
            .add(Projections.property("photos"), "url");
    }

也尝试使用 HQL:

getCurrentSession()
    .createQuery("select u.id, p.url " +
        " from User u inner join u.photos p " +
        " where u.login LIKE :login")
    .setString("login", login)
    .list();

但是返回的结果是List&lt;Object[]&gt;类型但是我需要List&lt;UserDTO&gt;


更新:

HTTP 状态 500 - 请求处理失败;嵌套异常是 org.springframework.orm.hibernate4.HibernateSystemException: 为属性调用 setter 时发生 IllegalArgumentException [com.memories.dto.UserDTO.photos(预期类型 = java.util.List)]; 目标 = [com.memories.dto.UserDTO.photos@4e162869],属性值 = [https://i1.sndcdn.com/artworks-000031744302-0730nk-t500x500.jpg] com.memories.dto.UserDTO.photos 的设置器;嵌套异常是 为属性调用 setter 时发生 IllegalArgumentException [com.memories.dto.UserDTO.photos](预期类型 = java.util.List)]; 目标 = [com.memories.dto.UserDTO.photos@4e162869],属性值 = [https://i1.sndcdn.com/artworks-000031744302-0730nk-t500x500.jpg]

【问题讨论】:

  • @DavidLevesque,是的,当然

标签: java hibernate hql hibernate-criteria


【解决方案1】:

我认为使用上面的代码,您只需将结果直接分配给 List,它应该可以轻而易举地工作。像这样的。

List<User> userList = yourCriteria.list();

【讨论】:

  • 如果我尝试list.get(0).toString() - 将抛出 java.lang.ClassCastException: [Ljava.lang.Object;无法转换为 com.dto,UserDTO
  • 那是因为你的 DTO 有一个字符串列表。基本问题在于你的转变。您实际上应该将结果转换为 User 而不是 UserDTO,并编写一个实用方法将 User 转换为 UserDTO。当休眠将尝试将结果转换为 UserDTO 时,它会期望 UserDTO 具有String photos 而不是List&lt;String&gt; photos。我已经编辑了答案以反映相同的情况。
  • 谢谢,我问是因为我想知道更好的解决方案,但事实证明,确实如此。当我搜索变体时,我认为休眠本身将数据从 bd 转换为实体 bean。而且我认为我可以使用休眠功能来转换为 dto 类。
【解决方案2】:

所以,我发现不是最好的解决方案,但是...

首先,需要获取实体用户列表:

List<User> list = getCurrentSession()
                .createQuery("from USer as u where u.login LIKE :login")
                .setString("login", login)
                .list();

接下来,我们像这样在实体 User 方法中声明,将List&lt;Photo&gt; 转换为List&lt;String&gt;

public List<String> getPhotosUrls() {
    List<String> urls = new ArrayList<String>(photos.size());
    for (Photo p : photos)
        urls.add(p.getUrl()));
    return urls;
}

最后一步是硬编码创建 DTO bean:

List<UserDTO> users = new ArrayList<UserDTO>(list.size());
for (User u : list) {
    users.add(new UserDTO(u.id, u.getPhotosUrls));

当然,你必须有UserDTO(Long id, List&lt;String&gt; urls) 构造函数。 如果有人能找到更好的解决方案,请写在这里:)

【讨论】:

    猜你喜欢
    • 2015-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-17
    • 1970-01-01
    • 1970-01-01
    • 2011-08-31
    相关资源
    最近更新 更多