How to load Hibernate objects from an external JAR

I am trying to load objects from multiple jar files. What I managed to do is

  • configure hibernate

    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);
    }
    

so that the objects are loaded from the modulesFiles array. In the logs I see:

    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
  1. Object in an external bank

    @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.
    }
    
  2. persistence.xml in an external bank (META-INF directory)

    <persistence-unit name="ProgramInfoPersistenceUnit">
        <class>com.antara.modules.programinfo.db.model.PrograminfoDataEntity</class>
    </persistence-unit>
    

  3. Request using the above object

        Session session = openSession();
        Query q = session.getNamedQuery("PrograminfoDataEntity.findByWindowInfo");
        q.setParameter("pp", windowInfo.getProcessPath());
        q.setParameter("wt", windowInfo.getWindowTitle());
        q.setDate("d", date);
    
        PrograminfoDataEntity result = (PrograminfoDataEntity) q.uniqueResult();
        closeSession(session);
    

in which there was an exception:

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)

The question is, why did the sleep mode not load the annotated object from the jar? An exception is raised not only by a named query, but also by any other operation with an entity. There are no errors before using this object. Local objects load properly.

EDIT:

After some changes, I managed to recognize the object using 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 ....

But when I try to use the entity, I still get the exception:

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- , )

@Override
public void configureDB(Configuration configuration) {
    configuration.addAnnotatedClass(PrograminfoDataEntity.class);
}
+4
2

3 : Hibernate ContextClassLoader

Thread.currentThread().getContextClassLoader();

ContextClassLoader ClassLoader PrograminfoDataEntity

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

NoClassDefFound, ClassCastException

+2

javadoc Hibernate *.hbm.xml Configuration.addJar

, Hibernate - JPA

, . JPA api. - :

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);
        }
    }
}
+2

All Articles