JPA : How to convert a native query result set to POJO class collection

后端 未结 21 1526
孤街浪徒
孤街浪徒 2020-11-22 09:23

I am using JPA in my project.

I came to a query in which I need to make join operation on five tables. So I created a native query which returns five fields.

21条回答
  •  旧时难觅i
    2020-11-22 09:30

    First declare following annotations:

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface NativeQueryResultEntity {
    }
    
    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface NativeQueryResultColumn {
        int index();
    }
    

    Then annotate your POJO as follows:

    @NativeQueryResultEntity
    public class ClassX {
        @NativeQueryResultColumn(index=0)
        private String a;
    
        @NativeQueryResultColumn(index=1)
        private String b;
    }
    

    Then write annotation processor:

    public class NativeQueryResultsMapper {
    
        private static Logger log = LoggerFactory.getLogger(NativeQueryResultsMapper.class);
    
        public static  List map(List objectArrayList, Class genericType) {
            List ret = new ArrayList();
            List mappingFields = getNativeQueryResultColumnAnnotatedFields(genericType);
            try {
                for (Object[] objectArr : objectArrayList) {
                    T t = genericType.newInstance();
                    for (int i = 0; i < objectArr.length; i++) {
                        BeanUtils.setProperty(t, mappingFields.get(i).getName(), objectArr[i]);
                    }
                    ret.add(t);
                }
            } catch (InstantiationException ie) {
                log.debug("Cannot instantiate: ", ie);
                ret.clear();
            } catch (IllegalAccessException iae) {
                log.debug("Illegal access: ", iae);
                ret.clear();
            } catch (InvocationTargetException ite) {
                log.debug("Cannot invoke method: ", ite);
                ret.clear();
            }
            return ret;
        }
    
        // Get ordered list of fields
        private static  List getNativeQueryResultColumnAnnotatedFields(Class genericType) {
            Field[] fields = genericType.getDeclaredFields();
            List orderedFields = Arrays.asList(new Field[fields.length]);
            for (int i = 0; i < fields.length; i++) {
                if (fields[i].isAnnotationPresent(NativeQueryResultColumn.class)) {
                    NativeQueryResultColumn nqrc = fields[i].getAnnotation(NativeQueryResultColumn.class);
                    orderedFields.set(nqrc.index(), fields[i]);
                }
            }
            return orderedFields;
        }
    }
    

    Use above framework as follows:

    String sql = "select a,b from x order by a";
    Query q = entityManager.createNativeQuery(sql);
    
    List results = NativeQueryResultsMapper.map(q.getResultList(), ClassX.class);
    

提交回复
热议问题