Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/hibernate/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何从外部JAR加载Hibernate实体_Java_Hibernate - Fatal编程技术网

Java 如何从外部JAR加载Hibernate实体

Java 如何从外部JAR加载Hibernate实体,java,hibernate,Java,Hibernate,我正在尝试从几个jar文件加载实体。 我设法做到的是 配置休眠 private void configure(File[] moduleFiles) { Configuration configuration = new Configuration() .setProperty("hibernate.connection.url", getConnectionString()) .setProperty("hibernate.connection.username", "user

我正在尝试从几个jar文件加载实体。 我设法做到的是

  • 配置休眠

    private void configure(File[] moduleFiles)
    {
    Configuration configuration = new Configuration()
        .setProperty("hibernate.connection.url", getConnectionString())
        .setProperty("hibernate.connection.username", "user")
        .setProperty("hibernate.connection.password", "pass")
        .setProperty("hibernate.connection.driver_class", "org.hsqldb.jdbc.JDBCDriver")
        .setProperty("hibernate.dialect", "org.hibernate.dialect.HSQLDialect")
        .setProperty("hibernate.archive.autodetection", "class,hbm")
        .setProperty("exclude-unlisted-classes", "false")
        .setProperty("hibernate.hbm2ddl.auto", "update");
    
    if (moduleFiles != null) {
        for (File f : moduleFiles) {
            configuration.addJar(f);
        }
    }
    
    ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build();
    this.sessionFactory = configuration.buildSessionFactory(serviceRegistry);
    }
    
  • 因此,应该从moduleFiles数组加载实体。在日志中,我可以看到:

        2015-08-25 20:52:12 INFO  Configuration:837 - HHH000235: Searching for mapping documents in jar: ProgramInfo.jar
        2015-08-25 20:52:12 INFO  Configuration:837 - HHH000235: Searching for mapping documents in jar: SampleModule.jar
    
  • 外部jar中的实体

    @Entity
    @Table(name = "PROGRAMINFO_DATA", schema = "PUBLIC", catalog = "PUBLIC")
    @NamedQueries({@NamedQuery(name = "PrograminfoDataEntity.findByWindowInfo", query = "FROM PrograminfoDataEntity WHERE PROCESSPATH = :pp AND WINDOWTITLE = :wt AND DAY = :d")})
    public class PrograminfoDataEntity implements SVEntity {
        private long id;
        private Date day;
        private String processname;
        private String processpath;
        private String programname;
        private String windowtitle;
    
        // getters setters etc.
    }
    
  • 外部jar(META-INF目录)中的persistence.xml

  • 引发了一个异常:

    org.hibernate.MappingException: Named query not known: PrograminfoDataEntity.findByWindowInfo
        at org.hibernate.internal.AbstractSessionImpl.getNamedQuery(AbstractSessionImpl.java:177)
        at org.hibernate.internal.SessionImpl.getNamedQuery(SessionImpl.java:1372)
        at com.antara.modules.programinfo.db.dao.PrograminfoDao.findByWindowInfo(PrograminfoDao.java:26)
        at com.antara.modules.programinfo.ProgramInfoImpl.run(ProgramInfoImpl.java:84)
    
    ERROR AssertionFailure:61 - HHH000099: an assertion failure occured (this may indicate a bug in Hibernate, but is more likely due to unsafe use of the session): java.lang.ClassNotFoundException: com.antara.modules.programinfo.db.model.PrograminfoDataEntity
    ERROR Main:114 - PersistentClass name cannot be converted into a Class
    ...
    Caused by: java.lang.ClassNotFoundException: com.antara.modules.programinfo.db.model.PrograminfoDataEntity
    
    问题是为什么hibernate没有从jar加载带注释的实体?异常不仅由命名查询引发,而且由实体的任何其他操作引发。使用此实体之前没有错误。本地实体已正确加载

    编辑:

    经过一些更改后,我设法通过Hibernate识别实体

    DEBUG AnnotationBinder:601 - Binding entity from annotated class: com.antara.modules.programinfo.db.model.PrograminfoDataEntity
    DEBUG QueryBinder:93 - Binding named query: PrograminfoDataEntity.findByWindowInfo => FROM PrograminfoDataEntity ....
    
    但当我尝试使用实体时,仍然会出现异常:

    org.hibernate.MappingException: Named query not known: PrograminfoDataEntity.findByWindowInfo
        at org.hibernate.internal.AbstractSessionImpl.getNamedQuery(AbstractSessionImpl.java:177)
        at org.hibernate.internal.SessionImpl.getNamedQuery(SessionImpl.java:1372)
        at com.antara.modules.programinfo.db.dao.PrograminfoDao.findByWindowInfo(PrograminfoDao.java:26)
        at com.antara.modules.programinfo.ProgramInfoImpl.run(ProgramInfoImpl.java:84)
    
    ERROR AssertionFailure:61 - HHH000099: an assertion failure occured (this may indicate a bug in Hibernate, but is more likely due to unsafe use of the session): java.lang.ClassNotFoundException: com.antara.modules.programinfo.db.model.PrograminfoDataEntity
    ERROR Main:114 - PersistentClass name cannot be converted into a Class
    ...
    Caused by: java.lang.ClassNotFoundException: com.antara.modules.programinfo.db.model.PrograminfoDataEntity
    
    更改是:将配置传递给jar中的每个“模块”,并添加带注释的类(所谓模块,我指的是启动时调用方法的SPI服务)

    根据Hibernate only read*.hbm.xml at Configuration.addJar方法

    我猜Hibernate不会自动扫描JAR,因为JPA规范中有限制

    我已经在hibernate中完成了JAR的自动扫描,扩展了扫描仪并在其上添加了JAR。但您应该使用JPAAPI来实现这一点。比如:

    Map<String, Object> map = new HashMap<>();
    map.put("hibernate.connection.url", getConnectionString());
    map.put("hibernate.connection.username", "user");
    map.put("hibernate.connection.password", "pass");
    map.put("hibernate.connection.driver_class", "org.hsqldb.jdbc.JDBCDriver");
    map.put("hibernate.dialect", "org.hibernate.dialect.HSQLDialect");
    map.put("hibernate.archive.autodetection", "class,hbm");
    map.put("exclude-unlisted-classes", "false");
    map.put("hibernate.hbm2ddl.auto", "update");
    //Property to change scanner
    map.put("hibernate.ejb.resource_scanner", "me.janario.MyScanner");
    
    EntityManagerFactory emf = Persistence.createEntityManagerFactory("ProgramInfoPersistenceUnit", map);
    SessionFactory sessionFactory = ((HibernateEntityManagerFactory) emf).getSessionFactory();
    
    public class MyScanner extends StandardScanner {
        @Override
        public ScanResult scan(PersistenceUnitDescriptor persistenceUnit, ScanOptions scanOptions) {
            try {
                persistenceUnit.getJarFileUrls()
                        .add(new URL("file:/path/my.jar"));
                return super.scan(persistenceUnit, scanOptions);
            } catch (MalformedURLException e) {
                throw new IllegalStateException(e);
            }
        }
    }
    

    经过3天的试验,我找到了解决方案:Hibernate使用ContextClassLoader的反射机制加载类

    Thread.currentThread().getContextClassLoader();
    
    所以我将ContextClassLoader设置为PrograminfoDataEntity的ClassLoader

    Thread.currentThread().setContextClassLoader(PrograminfoDataEntity.class.getClassLoader());
    

    它解决了所有NoClassDefFound、ClassCastException和类似错误

    您正在设置Hibernate引导过程。以下是文件:

    这里基本上有两条路线。您正在以特定于Hibernate的方式进行操作。我通常更喜欢JPA,因为它是最自动、最简单的一个:将persistence.xml文件放入jar中,jar将被扫描以查找具有适当实体注释的类。JPA随后将注入实体管理器(和工厂),然后您可以使用以下方法将其转换为本机Hibernate会话:

    Session s = (Session) em.getDelegate();
    

    反过来,如果需要的话,应该允许您访问非JPA功能。

    不幸的是,它不起作用:无法构建实体管理器工厂org.hibernate.boot.registry.classloading.spi.ClassLoadingException:无法加载类[com.antara.modules.programinfo.db.model.PrograminfoDataEntity]您是作为java se应用程序还是在jee容器中?(Wildfly中还有一个conf来代替scanner)标准JavaSE应用程序。我认为您的解决方案的问题在于ProgramInfoPersistenceUnit位于JAR中,因此在创建EntityManagerFactory时无法访问它。方法configure(File[]moduleFiles)是加载包含实体的JAR的“父级”,该实体可能与
    Session s = (Session) em.getDelegate();