Reputation: 1542
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 :(
Upvotes: 4
Views: 2973
Reputation: 1
Based on answer provided by Seymur Asadov, this can be done in Gradle Kotlin DSL using processResources
task:
tasks {
processResources {
val currentSourceSet = sourceSets.find { sourceSet ->
sourceSet.resources.any {
source.contains(it)
}
}
val properties = "classesDirectory" to currentSourceSet!!.output.classesDirs.singleFile.relativeTo(projectDir)
filesMatching("META-INF/persistence.xml") {
expand(properties)
}
}
}
and by adding expanding property in META-INF/persistence.xml
<jar-file>...</jar-file>
XML tags:
<persistence-unit name="application">
<jar-file>${classesDirectory}</jar-file>
<!-- your persistence unit data -->
</persistence-unit>
This way, Gradle will expand current source set compiled classes directory property for the META-INF/persistence.xml
file to use.
Upvotes: 0
Reputation: 1542
The issue was resolved (thanks to Vlad Mihalcea) ultimately as follows:
META-INF
folder under src/main
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.
Upvotes: -1
Reputation: 672
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>
Upvotes: 3