使用Query.getResultList()返回List <object []>而不是List <vector>的版本,从旧版JPA迁移到更新版本的最简单方法

时间:2017-01-16 13:12:15

标签: jpa migration eclipselink aspectj toplink

我们目前正在研究从Toplink 2.1-60f升级到EclipseLink 2.6的最佳方式。该项目有点大,大部分手动工作都必须在我们使用NativeQuery的部分代码中完成。 Query.getResultList()结果在两个JPA实现之间有所不同,因为TopLink返回List<Vector>,另一方面EclipseLink返回List<Object[]>。遗憾的是,代码中充斥着List<Vector>个引用。

解决方案的一部分是将list数组的结果转换为向量列表。我没有手动在所有地方进行此操作,而是认为我们可以使用 AspectJ 来拦截getResultList()调用并转换返回值。这是一个可行的解决方案?有人实施过类似的解决方案我们正在使用 Maven 作为我们的构建工具。

提前致谢!

1 个答案:

答案 0 :(得分:0)

我的建议是:使用一个好的IDE并重构你的代码!

但是因为你要求AOP解决方案,这里是一个自洽的AspectJ示例。由于我从未使用过JPA,因此我只是将您的情况重新创建为一个小抽象。

具有大量虚拟方法的抽象Query基础实现:

package de.scrum_master.persistence;

import java.util.*;
import javax.persistence.*;

public abstract class MyBaseQueryImpl implements Query {
    @Override public int executeUpdate() { return 0; }
    @Override public int getFirstResult() { return 0; }
    @Override public FlushModeType getFlushMode() { return null; }
    @Override public Map<String, Object> getHints() { return null; }
    @Override public LockModeType getLockMode() { return null; }
    @Override public int getMaxResults() { return 0; }
    @Override public Parameter<?> getParameter(String arg0) { return null; }
    @Override public Parameter<?> getParameter(int arg0) { return null; }
    @Override public <T> Parameter<T> getParameter(String arg0, Class<T> arg1) { return null; }
    @Override public <T> Parameter<T> getParameter(int arg0, Class<T> arg1) { return null; }
    @Override public <T> T getParameterValue(Parameter<T> arg0) { return null; }
    @Override public Object getParameterValue(String arg0) { return null; }
    @Override public Object getParameterValue(int arg0) { return null; }
    @Override public Set<Parameter<?>> getParameters() { return null; }
    @Override public Object getSingleResult() { return null; }
    @Override public boolean isBound(Parameter<?> arg0) { return false; }
    @Override public Query setFirstResult(int arg0) { return null; }
    @Override public Query setFlushMode(FlushModeType arg0) { return null; }
    @Override public Query setHint(String arg0, Object arg1) { return null; }
    @Override public Query setLockMode(LockModeType arg0) { return null; }
    @Override public Query setMaxResults(int arg0) { return null; }
    @Override public <T> Query setParameter(Parameter<T> arg0, T arg1) { return null; }
    @Override public Query setParameter(String arg0, Object arg1) { return null; }
    @Override public Query setParameter(int arg0, Object arg1) { return null; }
    @Override public Query setParameter(Parameter<Calendar> arg0, Calendar arg1, TemporalType arg2) { return null; }
    @Override public Query setParameter(Parameter<Date> arg0, Date arg1, TemporalType arg2) { return null; }
    @Override public Query setParameter(String arg0, Calendar arg1, TemporalType arg2) { return null; }
    @Override public Query setParameter(String arg0, Date arg1, TemporalType arg2) { return null; }
    @Override public Query setParameter(int arg0, Calendar arg1, TemporalType arg2) { return null; }
    @Override public Query setParameter(int arg0, Date arg1, TemporalType arg2) { return null; }
    @Override public <T> T unwrap(Class<T> arg0) { return null; }
 }

唯一缺少的方法是getResultList(),所以现在让我们为它提供两种不同的实现,扩展抽象基础实现:

具体Query实施返回List<Vector>

这会模拟您的TopLink课程。

package de.scrum_master.persistence;

import java.util.*;

public class VectorQuery extends MyBaseQueryImpl {
    @Override
    public List getResultList() {
        List<Vector<String>> resultList = new ArrayList<>();
        Vector<String> result = new Vector<>();
        result.add("foo"); result.add("bar");
        resultList.add(result);
        result = new Vector<>();
        result.add("one"); result.add("two");
        resultList.add(result);
        return resultList;
    }
}

具体Query实施返回List<Object[]>

这模拟您的EclipseLink类。

package de.scrum_master.persistence;

import java.util.*;

public class ArrayQuery extends MyBaseQueryImpl {
    @Override
    public List getResultList() {
        List<Object[]> resultList = new ArrayList<>();
        Object[] result = new Object[] { "foo", "bar" };
        resultList.add(result);
        result = new Object[] { "one", "two" };
        resultList.add(result);
        return resultList;
    }
}

驱动程序应用程序:

应用程序创建两个具体子类型的查询,每次假设列表元素都是向量。

package de.scrum_master.app;

import java.util.*;
import de.scrum_master.persistence.*;

public class Application {
    public static void main(String[] args) {
        List<Vector<?>> resultList;

        resultList = new VectorQuery().getResultList();
        for (Vector<?> result : resultList)
            System.out.println(result);

        resultList = new ArrayQuery().getResultList();
        for (Vector<?> result : resultList)
            System.out.println(result);
    }
}

没有方面的控制台日志:

[foo, bar]
[one, two]
Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to java.util.Vector
    at de.scrum_master.app.Application.main(Application.java:15)

嗯,哦!这正是你的问题,对吗?如果我们绝对拒绝重构,那么我们能做些什么呢?我们滥用AOP来修补遗留代码。 (请不要这样做,但如果你绝对想要,你可以。)

AspectJ查询结果适配器:

无视原始类型和其他丑陋的东西的使用,这是我的概念证明:

package de.scrum_master.aspect;

import java.util.*;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;

@Aspect
public class QueryResultAdapter {
    @Around("call(* javax.persistence.Query.getResultList())")
    public List<Vector> transformQueryResult(ProceedingJoinPoint thisJoinPoint) throws Throwable {
        System.out.println(thisJoinPoint);
        List result = (List) thisJoinPoint.proceed();
        if (result != null && result.size() > 0 && result.get(0) instanceof Vector)
            return result;
        System.out.println("Transforming arrays to vectors");
        List<Vector> transformedResult = new ArrayList<Vector>();
        for (Object[] arrayItem : (List<Object[]>) result)
            transformedResult.add(new Vector(Arrays.asList(arrayItem)));
        return transformedResult;
    }
}

带方面的控制台日志:

call(List de.scrum_master.persistence.VectorQuery.getResultList())
[foo, bar]
[one, two]
call(List de.scrum_master.persistence.ArrayQuery.getResultList())
Transforming arrays to vectors
[foo, bar]
[one, two]

Etvoilà - 你可以做丑陋的东西以及其他不是用AOP发明的东西。 ;-)