Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to have JPA with Hibernate provider auto-scan for entity classes

there's a LOT of questions on this on the internets.. however I still struggle with what seems to be a quite typical scenario.

I'm doing a quite simple JPA (using Hibernate) project, with Entity classes being resided with a com.actions.domain package

I have persistence.xml as follows:

<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">
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>

        <properties>
            <property name="javax.persistence.jdbc.driver"
                      value="org.h2.Driver" />

            <property name="javax.persistence.jdbc.url"
                      value="jdbc:h2:~/test.h2db" />

            <property name="hibernate.archive.autodetection" value="class, hbm"/>
        </properties>

    </persistence-unit>

</persistence>

this file resides in src\test\resources\META-INF folder

I have also JUnit test classes written like this:

protected EntityManager entityManager;

@Before
public void setUp() throws Exception {
    EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("my-persistence-unit");
    entityManager = entityManagerFactory.createEntityManager();
}

@Test
public void actionsAdded_success() {
    entityManager.getTransaction().begin();
    entityManager.persist(new Action("TEST_ACTION1", "ACTION"));
    entityManager.persist(new Action("TEST_ACTION2", "ACTION"));
    entityManager.getTransaction().commit();
}

An example of an Entity:

@Entity
@Table(name = "UC_ACTIONS")
@Data
public class Action {

    @Id
    @GeneratedValue(generator="increment")
    private Long id;

    private String name;

    private String type;

    public Action(String name, String type) {
        this.name = name;
        this.type = type;
    }
}

If I put a <class>com.actions.domain.Action</class> element into persistence unit description, it all works like a charm, however I don't want to enumerate the classes here by hand, also don't want to have any hibernate.cfg.xml file

So if I remove that element, and try to somehow have provider auto-scan for entities, I get errors like Unknown entity: com.actions.domain.Action

I've tried running these tests both a Run configuration in IntelliJ and as a gradle test command. In none of the cases META-INF folder is in the same directory as classes, so how are people achieving this ??

How on Earth can one have it working ?

UPDATE: there's an accepted answer to identical question here: https://stackoverflow.com/a/16598682/2583044 Still, I'm struggling to believe that such a main-stream use case issue could have such a marginal dirty hack of a solution :(

like image 520
62mkv Avatar asked Oct 20 '25 11:10

62mkv


1 Answers

By default autodetection works for entities in the same classpath item as persistence.xml. It can be configured by elements.

To enable correct autodetection when persistence.xml is in src/test/resources/META-INF I use the following trick:

persistence.xml

<persistence ...>
      <persistence-unit ...>
            <jar-file>${project.build.outputDirectory}</jar-file>
            ...
      </persistence-unit>
  </persistence>

pom.xml - enable resource filtering for src/test/resources:

<project ...>
    ...
    <build>
        <testResources>
            <testResource>
                <directory>src/test/resources</directory>
                <filtering>true</filtering>
            </testResource>
        </testResources>
    </build>
</project>
like image 190
Seymur Asadov Avatar answered Oct 23 '25 00:10

Seymur Asadov