AliasToBeanResultTransformer(MyDTO.class) fails to

2020-02-01 08:09发布

I would like a Criteria query to instantiate a DTO class using an AliasToBeanResultTransformer. The goal is to produce a light weight paged list with IDs for further action for a home page. This calls for a reporting type query.

            Criteria crit = session.createCriteria(Profile.class);

        crit.createAlias("personalData", "pd");
        crit.createAlias("emails", "e");
        crit.createAlias("telephones", "t");

        ProjectionList properties = Projections.projectionList();
        properties.add(Projections.property("id").as( "id"));
        properties.add(Projections.property("pd.lastName").as("lastName"));
        properties.add(Projections.property("pd.fullName").as("fullName"));
        properties.add(Projections.property("e.emailAddress").as("email"));
        properties.add(Projections.property("t.phoneNumber").as("phone"));

        crit.setProjection(properties);

        crit.setResultTransformer(new AliasToBeanResultTransformer(ProfileDTO.class));
        profiles = crit.list();

This fails to instantiate my DTO class. ProfileDTO has a matching constructor:

public ProfileDTO(Long id, String lastName, String fullName, String email,
        String phone) {
    this(id,fullName);
    this.lastName = lastName;
    this.email = email;
    this.phone = phone;
}

And the query works when I construct ProfileDTO objects manually with the result rows

        List<Object[]> rows = crit.list();

        for ( Object[] row: rows ) {
            ProfileDTO dto = new ProfileDTO();
            dto.setId((Long)row[0]);
            dto.setLastName((String)row[1]);
            dto.setFullName((String)row[2]);
            dto.setEmail((String)row[3]);
            dto.setPhone((String)row[4]);
            profiles.add(dto);
        }

My workaround is working fine, but it seems unnecessary. What am I doing wrong?

标签: hibernate
2条回答
2楼-- · 2020-02-01 08:15

try with this:

public List<ProfileDTO> getProfiles() throws HibernateException 
{       
    try { 

        session = HibernateUtil.getSessionFactory().openSession();

        Criteria criteria = session.createCriteria(Profile.class);

        criteria.createAlias("personalData", "pd");
        criteria.createAlias("emails", "e");
        criteria.createAlias("telephones", "t");

        criteria.setProjection(Projections.projectionList()
                    .add(Projections.property("id").as( "id"))
                    .add(Projections.property("pd.lastName").as("lastName"))
                    .add(Projections.property("pd.fullName").as("fullName"))
                    .add(Projections.property("e.emailAddress").as("email"))
                    .add(Projections.property("t.phoneNumber").as("phone"))
        );

        criteria.setResultTransformer(Transformers.aliasToBean(ProfileDTO.class));

        return (List<ProfileDTO>)criteria.list();

    } catch (HibernateException he){
        he.printStackTrace();
        throw he; 
    } finally {
         if(session.isOpen()){
             session.close();
         }
    }
}
查看更多
家丑人穷心不美
3楼-- · 2020-02-01 08:26

The AliasToBeanResultTransformer uses setters to populate the DTO. If you want to use a constructor, to create your bean instance, you need to use an AliasToBeanConstructorResultTransformer.

Your DTO seems to have a setter for all the elements of the tuple, except for lastName. Maybe this is the problem.

That said, your code as is is simple, easy to maintain, and refactorable. It wouldn't be refactorable with an AliasToBeanResultTransformer. I generally prefer to instantiate my DTOs myself, just as you did.

查看更多
登录 后发表回答