Search code examples
hibernatemavenjpapersistence-unit

Hibernate Mapping Errors due Seperate Modules in IntelliJ?


Using several modules with independent Hibernate Instances

I am creating a multi-module maven project with modules ModuleA and ModuleB below the parent.

Hibernate throws a MappingException

The modules use their own Hibernate mapping with a own resource folder. Each module persists its objects independently from the other modules. Now when I try to instantiate a Class from Module B within Module A, I can access all the required Methods, but when I execute the Application, Hibernate throws this error:

Exception in thread "main" org.hibernate.MappingException: Unknown entity: org.example.ModuleB.Person
    at org.hibernate.internal.SessionFactoryImpl.getEntityPersister(SessionFactoryImpl.java:1096)
    at org.hibernate.internal.SessionImpl.getEntityPersister(SessionImpl.java:1443)
    at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:116)
    at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:209)
    at org.hibernate.event.internal.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:55)
    at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:194)
    at org.hibernate.event.internal.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:49)
    at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:90)
    at org.hibernate.internal.SessionImpl.fireSave(SessionImpl.java:715)
    at org.hibernate.internal.SessionImpl.save(SessionImpl.java:707)
    at org.hibernate.internal.SessionImpl.save(SessionImpl.java:702)

I can add the mapping for the class from ModuleB additionally into the Hibernate config file of Module A. Then it works. But this is not how it should work as each module should be independent. It could be theoretically be stored within a completely different RDBMS.

More background

Originally I only used only one module, it split it and want to have it more distangled. I executed mvn clean and compiled everything from scratch.

Additionally the pom.xml from Modue A has a dependency on Module B.

    <dependency>
        <groupId>org.example</groupId>
        <artifactId>ModuleB</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>

Solution

As proposed by @Skizzo, I just renamed the configuration files for each module. Originally, each module contained a Hibernate configuration file called hibernate.cfg.xml. I renamed these config files in both modules. The config file of ModuleA is now called hibernate.moduleA.cfg.xml and the config file of ModuleB is now called hibernate.moduleB.cfg.xml

Each module also contained a HibernateUtil.java class used for initializing the Session Factory. I also renamed the HibernateUtil classes for each module. ModuleA's Util class is now called HibernateUtilModuleA whereas the Util class of ModuleB is called HibernateUtilModuleB. Now there is no confusion between the two configurations possible ans Hibernate now knows which configuration to pick for each module.

Then I adapted the two HibernateUtil classes to load the individual config file like this:

HibernateUtilModuleA:

configuration.configure("hibernate.moduleA.cfg.xml");

HibernateUtilModuleB:

configuration.configure("hibernate.moduleB.cfg.xml");

The HibernateUtil class for ModuleA now looks roughly like this:

 /**
 * Hibernate session management
 */
public class HibernateUtilModuleA {
    private static SessionFactory sessionFactory;
    private static ServiceRegistry serviceRegistry;

    static {
    try {

        Configuration configuration = new Configuration();

        configuration.configure("hibernate.ModuleA.cfg.xml");

        serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build();
        sessionFactory = configuration.buildSessionFactory(serviceRegistry);


    } catch (HibernateException he) {
        System.err.println("Error creating Session: " + he);
        throw new ExceptionInInitializerError(he);
    }
    }


    public static SessionFactory getSessionFactory() {
    return sessionFactory;
    }
}

Solution

  • I had your same problem and I solved with a Composite Persistence Unit, but in my case I'm using eclipse link like Jpa implementation Composite Persistence Units. I found some information about Hibernate at this link, I think the the correct way to solve your problem is this.