hibernatejpagradleintellij-ideajunit

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 :(


Solution

  • The issue was resolved (thanks to Vlad Mihalcea) ultimately as follows:

    1. Moved the META-INF folder under src/main
    2. Added the following to build.gradle:

      apply plugin: 'idea'

      idea { module { inheritOutputDirs = true } }

      sourceSets { main { output.resourcesDir = "build/classes" } test { output.resourcesDir = "build/classes" } }

    Afterwards, tests are working as expected both from IDEA and with Gradle.