Adding entity classes dynamically at runtime

JPA doesn’t offer this feature yet. Here are three options you can check out :

  • This work around :
    1. Generate a persistence.xml on the fly (simple XML file creation) with a new persistence unit.
    2. Add persistence file to classpath dynamically (URLCLassLoader)
    3. Ask PersistenceProvider to load new persistence unit (createEntityManagerFactory)

I did implement this workaround. However, it didn’t scale well as the number of entities grows (100+). I finally switched to JDBC. Here is a capture of the memory consumption (-75%) before and after the switch from JPA to JDBC.

Memory consumption reduction by switching from JPA to JDBC

  • Programmatically loading Entity classes with JPA 2.0?
    This question on SO is similar to yours. An answer reports that it feasible with Spring.

  • JPA 2.0: Adding entity classes to PersistenceUnit *from different jar* automatically
    Good pointers are given here.

Nota

If the JPA provider is Hibernate, since Hibernate 4.0, it’s possible to pass directly entities to this JPA provider without declaring them in the persistence.xml file. Hibernate will handle the entities on the fly.

Here is a sample configuration of JPA 2.1 + Hibernate 4.3.7.Final without declaring any entities :

META-INF/persistence.xml

<?xml version="1.0" encoding="UTF-8" ?>
<persistence 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"
    version="2.1">

    <persistence-unit name="my-persistence-unit"
        transaction-type="RESOURCE_LOCAL">
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
        <properties>
            <!-- Database Properties -->
            <property name="javax.persistence.jdbc.url"
                value="jdbc:postgresql://localhost:5432/my-database" />
            <property name="javax.persistence.jdbc.user" value="login" />
            <property name="javax.persistence.jdbc.password" value="password" />

            <!-- Hibernate Properties -->
            <property name="hibernate.connection.driver_class" value="org.postgresql.Driver" />
            <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect" />
            <property name="hibernate.default_schema" value="public" />
            <property name="hibernate.hbm2ddl.auto" value="update" />
            <property name="hibernate.show_sql" value="false" />
            <property name="hibernate.format_sql" value="true" />

            <!-- Connection Pool -->
            <property name="hibernate.c3p0.min_size" value="5" />
            <property name="hibernate.c3p0.max_size" value="20" />
            <property name="hibernate.c3p0.timeout" value="500" />
            <property name="hibernate.c3p0.max_statements" value="50" />
            <property name="hibernate.c3p0.idle_test_period" value="2000" />
        </properties>
    </persistence-unit>

</persistence>

References

  • JPA 2.1 Specs : 8.2 Persistence Unit Packaging
  • JPA 2.1 Specs : 8.2.1.6 mapping-file, jar-file, class, exclude-unlisted-classes

Leave a Comment