java - 在通过java反射加载的插件中使用持久性的问题

标签 java maven jpa plugins method-invocation

三周以来,我尝试加载一些我使用 JarClassLoader 和反射编写的插件。
插件加载是完美的,但是当我必须使用持久性和实体类时,我收到此错误:

GRAVE: null
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.amepa.plugin03.Test.main(Test.java:29)
Caused by: javax.persistence.PersistenceException: No Persistence provider for EntityManager named pu
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:85)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:54)
at plugin.Main.getLocalFactory(Main.java:126)
... 5 more

当我使用 java -jar plugin.jar 在命令行中运行插件时 它运行完美地向我显示从数据库中获取的数据。 此外,当我不使用持久性 API 并直接通过驱动程序连接时,即使通过反射,我也会得到正确的结果。

所以我想了解错误从何而来,以及如果可能的话如何解决它。

这是插件的代码:

public class Main /*implements PluginImplement*/{

    public  List<String> getStudent(){
        List<Eleves> findElevesEntities = (new ElevesJpaController(getLocalFactory())).findElevesEntities();
        List<String> lst = new ArrayList<>();
        for(Eleves el : findElevesEntities){
            lst.add(el.toString());
            System.out.println(" Eleves : "+el.toString());
        }
        return lst;
    }

    public static void main(String args[]){
        Main m = new Main();
        m.getStudent();
    }

    public static EntityManagerFactory getLocalFactory() {
        return Persistence.createEntityManagerFactory("pu");
    }
}

这是我的持久性文件:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns  /persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
  <persistence-unit name="pu" transaction-type="RESOURCE_LOCAL">
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<class>entities.Eleves</class>
<properties>
  <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/emt?zeroDateTimeBehavior=convertToNull"/>
  <property name="javax.persistence.jdbc.user" value="user"/>
  <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
  <property name="javax.persistence.jdbc.password" value="password"/>
</properties>
  </persistence-unit>
</persistence>

实体

@Entity
@Table(name = "eleves")
@XmlRootElement
public class Eleves implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "id")
    private Integer id;
    @Column(name = "created")
    @Temporal(TemporalType.TIMESTAMP)
    private Date created;
    @Column(name = "date_bapteme")
    @Temporal(TemporalType.DATE)
    private Date dateBapteme;
    @Column(name = "date_inscription_ecole")
    @Temporal(TemporalType.DATE)
    private Date dateInscriptionEcole;
    @Column(name = "date_naissance")
    @Temporal(TemporalType.DATE)
    private Date dateNaissance;
    @Column(name = "email")
    private String email;
    @Basic(optional = false)
    @Column(name = "nom")
    private String nom;
    @Basic(optional = false)
    @Column(name = "prenom")
    private String prenom;
    @Column(name = "numero")
    private String numero;

    public Eleves() {
    }

    public Eleves(Integer id) {
        this.id = id;
    }

    public Eleves(Integer id, String nom, String prenom) {
        this.id = id;
        this.nom = nom;
        this.prenom = prenom;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Date getCreated() {
        return created;
    }

    public void setCreated(Date created) {
        this.created = created;
    }

    public Date getDateBapteme() {
        return dateBapteme;
    }

    public void setDateBapteme(Date dateBapteme) {
        this.dateBapteme = dateBapteme;
    }

    public Date getDateInscriptionEcole() {
        return dateInscriptionEcole;
    }

    public void setDateInscriptionEcole(Date dateInscriptionEcole) {
        this.dateInscriptionEcole = dateInscriptionEcole;
    }

    public Date getDateNaissance() {
        return dateNaissance;
    }

    public void setDateNaissance(Date dateNaissance) {
        this.dateNaissance = dateNaissance;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getNom() {
        return nom;
    }

    public void setNom(String nom) {
        this.nom = nom;
    }

    public String getPrenom() {
        return prenom;
    }

    public void setPrenom(String prenom) {
        this.prenom = prenom;
    }

    public String getNumero() {
        return numero;
    }

    public void setNumero(String numero) {
        this.numero = numero;
    }

    @Override
    public String toString() {
        return "Eleves{" + "id=" + id + ", created=" + created + ", dateBapteme=" + dateBapteme + ", dateInscriptionEcole=" + dateInscriptionEcole + ", dateNaissance=" + dateNaissance + ", email=" + email + ", nom=" + nom + ", prenom=" + prenom + ", numero=" + numero + '}';
    }
}

和 Controller :

public class ElevesJpaController implements Serializable {

    public ElevesJpaController(EntityManagerFactory emf) {
        this.emf = emf;
    }
    private EntityManagerFactory emf = null;

    public EntityManager getEntityManager() {
        return emf.createEntityManager();
    }


    public List<Eleves> findElevesEntities() {
        return findElevesEntities(true, -1, -1);
    }

    public List<Eleves> findElevesEntities(int maxResults, int firstResult) {
        return findElevesEntities(false, maxResults, firstResult);
    }

    private List<Eleves> findElevesEntities(boolean all, int maxResults, int firstResult) {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            cq.select(cq.from(Eleves.class));
            Query q = em.createQuery(cq);
            if (!all) {
                q.setMaxResults(maxResults);
                q.setFirstResult(firstResult);
            }
            return q.getResultList();
        } finally {
            em.close();
        }
    }

    public Eleves findEleves(Integer id) {
        EntityManager em = getEntityManager();
        try {
            return em.find(Eleves.class, id);
        } finally {
            em.close();
        }
    }

    public int getElevesCount() {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            Root<Eleves> rt = cq.from(Eleves.class);
            cq.select(em.getCriteriaBuilder().count(rt));
            Query q = em.createQuery(cq);
            return ((Long) q.getSingleResult()).intValue();
        } finally {
            em.close();
        }
    }    
}

它们都使用maven打包在jar中。

加载 jar 的主类是:

public class Test {
    public static void main(String args[]) throws ClassNotFoundException, NoSuchMethodException{
        JarClassLoader jcl = new JarClassLoader();
        Class loadClass = jcl.loadClass("plugin.Main");
        System.out.println(" Class : "+loadClass);
        for(Method m : loadClass.getDeclaredMethods())
            System.out.println(" Method : "+m.getName());

        Method declaredMethod = loadClass.getDeclaredMethod("getStudent");
        try {
            Object newInstance = loadClass.newInstance();
            declaredMethod.invoke(newInstance);
        } catch (IllegalAccessException ex) {
            Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IllegalArgumentException ex) {
            Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
        } catch (InvocationTargetException ex) {
            Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

JarClassLoader 是从这篇文章派生的类: http://kalanir.blogspot.com/2010/01/how-to-write-custom-class-loader-to.html

我在上面的链接中添加了更正后的代码版本:

public class JarClassLoader extends ClassLoader {
private final String jarFile = "path_to_jar.jar"; //Path to the jar file
private Hashtable classes = new Hashtable(); //used to cache already defined classes
public JarClassLoader() {
    super(JarClassLoader.class.getClassLoader()); //calls the parent class loader's constructor
}
public Class loadClass(String className) throws ClassNotFoundException {
    return findClass(className);
}
public Class findClass(String className) {
    byte classByte[];
    Class result = null;

    result = (Class) classes.get(className); //checks in cached classes
    if (result != null) {
        return result;
    }

    try {
        return findSystemClass(className);
    } catch (Exception e) {

    }

    try {
          className = className.replaceAll("\\.", "/");
        JarFile jar = new JarFile(jarFile);
        Enumeration<JarEntry> entries = jar.entries();
        JarEntry entry = jar.getJarEntry(className + ".class");
        InputStream is = jar.getInputStream(entry);
        ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
        int nextValue = is.read();
        while (-1 != nextValue) {
            byteStream.write(nextValue);
            nextValue = is.read();
        }

            classByte = byteStream.toByteArray(); 
  className = className.replaceAll("/","\\." ); 
 result = defineClass(className, classByte, 0, classByte.length,null);
         classes.put(className, result);
        return result;
    } catch (Exception e)
   { e.printStackTrace();
        return null;
    }
}

}

提前致谢。

最佳答案

如果您使用从链接中的代码派生的 JarClassLoader,那么它的编写质量很差并且存在错误。

使用URLClassLoader

关于java - 在通过java反射加载的插件中使用持久性的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39333498/

相关文章:

java - 在unix环境下的jboss中部署应用程序时出现问题

java - 我怎样才能使这个查询只使用 JPA(或 Hibernate)API 工作?

java - invokeAndWait 似乎会导致应用程序间歇性卡住

java - Spark 提交中不支持的类版本错误

java - 尝试运行命名查询

java - 无法解析符号 'App'

java - 有谁知道是否有一个eclipse插件可以指出pom.xml中不兼容的jar?

java - 如何让 log4j 与 jetty 一起工作?

java - 搜索嵌套对象的规范/谓词

java - 为什么 JPA persist() 不生成自增主 ID?