MATLAB仅在最初几秒内找到eclipselink的persistence.xml

时间:2010-12-13 22:42:55

标签: matlab osgi eclipselink

这是Using eclipselink in Java code run from MATLAB中描述的问题的延续,与Java JPA Class for MATLAB中描述的问题类似,但其中描述的已接受解决方案尚未完全解决问题。

我正在尝试使用eclipselink连接到matlab中的oracle数据库。从前面帖子的答案中,我将代码放在静态类路径中(在classpath.txt中)。当我这样做时,我能够使用它,但只有在我加载matlab后的前几秒内创建EntityManager(通过调用Persistence.createEntityManager(...))。如果我在启动Matlab后等待超过5秒,则完全相同的代码会给出“No Persistence provided”异常。我已经确认它确实工作的时间,它实际上使用的是不同的类加载器而不是它没有的时间。我唯一能想到的是,类路径是在一个独立的线程上初始化而不是Matlab控制台,如果我快速运行它,那么Matlab的OSGI类加载器还没有初始化,所以它使用默认的java类加载器。

这显然不是一个可以接受的解决方案,并且似乎没有真正解决为什么Matlab类加载器无法找到persistence.xml的原因。有没有人有任何进一步的想法?可能是我如何初始化eclipselink?在我之前处理这段代码的人也没有能够找到一种方法让它以任何方式识别persistence.xml,而不是将它放在类路径的META-INF文件夹中。

2 个答案:

答案 0 :(得分:2)

eclipselink有两种版本可供选择:

  1. “打算在Java EE和SE环境中使用。”
  2. “OSGI Bundle Zip在OSGi容器中使用EclipseLink 2.1.2运行时。”
  3. 由于缺少OSGI容器,“OSGI Bundle”将无法在MATLAB JVM上运行。因此,Java EE和SE环境的单个jar将是正确的选择。

    根据Deploying EclipseLinkpersistence.xml放在类路径上的META-INF文件夹中,似乎是正确的。

    修改

    以下行添加到startup.m,而ClassPathHacker.class必须位于/MATLAB/java/。可以从JPA 2.0 with EclipseLink Tutorial中给出的位置下载所有三个必需的库derby.jareclipselink.jarjavax.persistence_2.0.1.v201006031150.jar

    javaaddpath('/MATLAB/java/');
    ClassPathHacker.addFile(java.lang.String('/NetBeansProjects/JpaForMatlab/dist/JpaForMatlab.jar'))
    ClassPathHacker.addFile(java.lang.String('/NetBeansProjects/JpaForMatlab/lib/derby.jar'))
    ClassPathHacker.addFile(java.lang.String('/NetBeansProjects/JpaForMatlab/lib/eclipselink.jar'))
    ClassPathHacker.addFile(java.lang.String('/NetBeansProjects/JpaForMatlab/lib/javax.persistence_2.0.1.v201006031150.jar'))
    

    JpaForMatlab.jar具有以下布局:

    |- META-INF
       |- persistence.xml
    |- jpaformatlab
       |- Main.class
       |- Todo.class
    

    的persistence.xml

    <?xml version="1.0" encoding="UTF-8" ?>
    <persistence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
        version="2.0" xmlns="http://java.sun.com/xml/ns/persistence">
        <persistence-unit name="todos" transaction-type="RESOURCE_LOCAL">
            <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
            <class>jpaformatlab.Todo</class>
            <properties>
                <property name="javax.persistence.jdbc.driver" value="org.apache.derby.jdbc.EmbeddedDriver" />
                <property name="javax.persistence.jdbc.url"
                    value="jdbc:derby:/NetBeansProjects/derby-db/simpleDb;create=true" />
                <property name="javax.persistence.jdbc.user" value="test" />
                <property name="javax.persistence.jdbc.password" value="test" />
                <property name="eclipselink.ddl-generation" value="create-tables" />
                <property name="eclipselink.ddl-generation.output-mode" value="both" />
            </properties>
        </persistence-unit>
    </persistence>
    

    Main.java

    package jpaformatlab;
    
    import java.util.List;
    
    import javax.persistence.EntityManager;
    import javax.persistence.EntityManagerFactory;
    import javax.persistence.Persistence;
    import javax.persistence.Query;
    
    public class Main {
    
        private static final String PERSISTENCE_UNIT_NAME = "todos";
        private static EntityManagerFactory factory;
    
        public static void main(String[] args) {
            factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
            EntityManager em = factory.createEntityManager();
            // Read the existing entries and write to console
            Query q = em.createQuery("select t from Todo t");
            List<Todo> todoList = q.getResultList();
            for (Todo todo : todoList) {
                System.out.println(todo);
            }
            System.out.println("Size: " + todoList.size());
    
            // Create new todo
            em.getTransaction().begin();
            Todo todo = new Todo();
            todo.setSummary("This is a test");
            todo.setDescription("This is a test");
            em.persist(todo);
            em.getTransaction().commit();
    
            em.close();
        }
    }
    

    Todo.java

    package jpaformatlab;
    
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.GenerationType;
    import javax.persistence.Id;
    
    @Entity
    public class Todo {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
        private String summary;
        private String description;
    
        public String getSummary() {
            return summary;
        }
    
        public void setSummary(String summary) {
            this.summary = summary;
        }
    
        public String getDescription() {
            return description;
        }
    
        public void setDescription(String description) {
            this.description = description;
        }
    
        @Override
        public String toString() {
            return "Todo [summary=" + summary + ", description=" + description
                    + "]";
        }
    
    }
    

    最后,我们调用main方法,以便从MATLAB提示符中运行这个简单的示例。

    >> jpaformatlab.Main.main(javaArray('java.lang.String',1))
    >> Todo [summary=This is a test, description=This is a test]
    

答案 1 :(得分:2)

我找到了一个有效的解决方案,虽然我对此并不十分满意。首次初始化PersistenceProviderResolverHolder时,它会构造一个名为DefaultPersistenceProviderResolver的私有内部类,当被询问时,它将在META-INF目录中找到persistence.xml。稍后,当您调用Persistence.createEntityManagerFactory()时,它会向PersistenceProviderResolverHolder询问解析程序,然后让解析程序找到persistence.xml。

在Matlab中运行它时的问题是,在初始化期间的某个时间,PersistenceProviderResolverHolder会被赋予一个Activator类来替换默认的解析器。据我所知,这个Activator类试图使用OSGI来查找任何持久性配置。最好我应该能够配置这样的东西,它也可以找到persistence.xml,但到目前为止我还没有成功。

我想出的解决方案是创建自己的DefaultPersistenceProviderResolver类副本,并将其实例设置为PersistenceProviderResolverHolder中的解析器。这将替换已放入其中的Activator类并将其返回到在META-INF文件夹中查找persistence.xml。我真的不喜欢这样做,但这是我能够在一周内完成这项工作的唯一解决方案。