代码之家  ›  专栏  ›  技术社区  ›  TofuBeer

JPA包装将未检查的异常转换为已检查的异常?

  •  3
  • TofuBeer  · 技术社区  · 15 年前

    在我离开并重新创建控制盘之前,是否有人知道JPA包装器将JPA抛出的未检查异常转换为检查异常?

    我不想找一个关于为什么我不希望检查异常的争论,我确实希望它们:-)

    1 回复  |  直到 15 年前
        1
  •  1
  •   Simon G.    15 年前

    使用下面的代码,您可以自己滚动99%。由于集合的成员需要被封装,它会给您留下两个编译错误,但是它会使您越过不再需要自动化的那一点。

    package so;
    
    import javax.persistence.*;
    
    import java.io.File;
    import java.io.FileWriter;
    import java.lang.reflect.*;
    
    public class CheckedPersistenceMaker {
    static final String PACKAGE = "stackoverflow.javax.persistence";
    
    static final String PACKAGE_DIR = PACKAGE.replace('.', '/');
    
    static Class<?>[] CLASSES = new Class<?>[] { Cache.class,
            EntityManager.class, EntityManagerFactory.class,
            EntityTransaction.class, Parameter.class,
            PersistenceUnitUtil.class, PersistenceUtil.class,
            Persistence.class, Query.class, Tuple.class, TupleElement.class,
            TypedQuery.class };
    
    
    private static String getName(Class<?> c) {
        String name = c.getName();
        for(Class<?> p:CLASSES) {
            if (p.equals(c))
                return PACKAGE + ".Checked"
                        + name.substring(name.lastIndexOf('.') + 1);
        }
        return c.getName();
    }
    
    
    static void generateWrapper(Class<?> c) throws Exception {
        String name = c.getName();
        TypeVariable<?>[] genType = c.getTypeParameters();
        String varNames = "";
        if (genType != null && genType.length != 0) {
            StringBuilder b = new StringBuilder();
            b.append("<");
            for(int i = 0;i < genType.length;i++) {
                if (i > 0) b.append(",");
                b.append(genType[i].getName());
            }
            b.append(">");
            varNames = b.toString();
        }
        name = "Checked" + name.substring(name.lastIndexOf('.') + 1);
        File javaFile = new File(PACKAGE_DIR + "/" + name + ".java");
        javaFile.getParentFile().mkdirs();
        FileWriter w = new FileWriter(javaFile);
        w.write("package " + PACKAGE + ";\n");
        w.write("public class " + name + varNames + " {\n");
        w.write("    private final " + c.getName() + varNames
                + " wrapped;\n\n    ");
        w.write(name + "(" + c.getName() + varNames
                + " original) {\nwrapped=original;\n}\n\n");
        w.write("    public " + c.getName() + varNames
                + " getOriginal() { return wrapped; }\n\n");
        Method[] ms = c.getDeclaredMethods();
        for(Method m:ms) {
            if (!Modifier.isPublic(m.getModifiers())) continue;
            w.write("    ");
            String s = m.toGenericString();
            s = s.replace(" abstract ", " ");
            s = s.replace(c.getName() + ".", "");
    
            String q = s.substring(0, s.indexOf('('));
            if (q.indexOf('<',10) != -1) q = q.substring(0, q.indexOf('<',10));
            boolean needsTranslate = false;
    
            for(Class<?> cc:CLASSES) {
                String ccn = cc.getName();
                if (q.indexOf(ccn) != -1) needsTranslate = true;
                String ccc = ccn.replace(cc.getPackage().getName() + ".",
                        PACKAGE + ".Checked");
                s = s.replace(ccn, ccc);
            }
    
            int pc = 0;
            int p = s.indexOf('(');
            if (s.charAt(p + 1) != ')') {
                StringBuilder b = new StringBuilder(s);
                int g = 0;
                char ch;
                do {
                    ch = b.charAt(p);
                    switch (ch) {
                    case '<': {
                        g++;
                        break;
                    }
                    case '>': {
                        g--;
                        break;
                    }
                    case ',':
                    case ')': {
                        if (g == 0) {
                            String pa = " p" + pc;
                            b.insert(p, pa);
                            pc++;
                            p += pa.length();
                        }
                        break;
                    }
                    }
                    p++;
                } while( ch != ')' );
                s = b.toString();
            }
    
            w.write(s);
    
            w.write(" throws CheckedPersistenceException");
    
            Class<?>[] excs = m.getExceptionTypes();
            for(Class<?> e:excs) {
                w.write(", " + e.getName());
            }
            w.write(" {\n        try {\n            ");
    
            Class<?> ret = m.getReturnType();
            if (!ret.equals(Void.TYPE)) {
                w.write("return ");
                if (needsTranslate) {
                    String retName = ret.getName();
                    retName = retName.replace(c.getPackage().getName() + ".",
                            PACKAGE + ".Checked");
                    w.write("new " + retName + "(");
                }
            }
    
            if (Modifier.isStatic(m.getModifiers())) {
                w.write(c.getName() + "." + m.getName() + "(");
            } else {
                w.write("wrapped." + m.getName() + "(");
            }
    
            Class<?> paramTypes[] = m.getParameterTypes();
            for(int i = 0;i < pc;i++) {
                if (i > 0) w.write(',');
    
                boolean isChecked = false;
                for(int j=0;j<CLASSES.length;j++) {
                    if( CLASSES[j].equals(paramTypes[i]) ) isChecked=true;
                }
                w.write("p" + i);
                if(isChecked) w.write(".getOriginal()");
            }
            w.write(')');
    
            if (needsTranslate) w.write(')');
            w.write(";\n        } catch ( javax.persistence.PersistenceException e ) { throw new CheckedPersistenceException(e); }\n    }\n\n");
        }
        w.write("}\n");
        w.close();
    }
    
    
    public static void main(String[] args) throws Exception {
        for(Class<?> c:CLASSES) {
            generateWrapper(c);
        }
    }
    }