Skip to content

Propagate LCEMFB.packagesToScan to native PersistenceProvider to pick up annotated packages [SPR-10910] #15538

Closed
@spring-projects-issues

Description

@spring-projects-issues

Joris Kuipers opened SPR-10910 and commented

I'm using LocalContainerEntityManagerFactoryBean#setPackagesToScan without a persistence.xml in combination with Hibernate. This works great for annotated entities, but fails to pick up annotated packages. Case in point: I'm using an @FilterDef that I don't want to have to repeat on multiple entities, so I've placed it on a package.
This works with a persistence.xml as Hibernate does some additional work when building the PersistenceUnitInfo then, but I would like to remain persistence.xml-less if possible.

From what I can see, the JPA PersistenceUnitInfo (which Spring creates for me in this case) simply doesn't provide support to pass in annotated packages. However, there is (at least for Hibernate) a workaround: from inside the HibernatePersistenceProvider you can call Ejb3Configuration#addPackage to have Hibernate pick up the annotated packages. So, for now I'm subclassing the HibernatePersistenceProvider and override createContainerEntityManagerFactory(PersistenceUnitInfo, Map) like this:

public class SmartHibernatePersistence extends HibernatePersistence {
	
	private String[] annotatedPackages = new String[0];
	
	/**
	 * Overridden to allow specifying annotated packages. Without this, when you use Spring's
	 * {@link LocalContainerEntityManagerFactoryBean#setPackagesToScan(String...)} package-level
	 * annotations are not picked up. 
	 */
	public EntityManagerFactory createContainerEntityManagerFactory(PersistenceUnitInfo info, Map properties) {
		Ejb3Configuration cfg = new Ejb3Configuration();
		for (String annotatedPackage: annotatedPackages) {
			cfg.addPackage(annotatedPackage);
		}
		Ejb3Configuration configured = cfg.configure( info, properties );
		return configured != null ? configured.buildEntityManagerFactory() : null;
	}
	
	public void setAnnotatedPackages(String... annotatedPackages) {
		this.annotatedPackages = annotatedPackages;
	}

}

and then call LCEMFB#setPersistenceProvider with a configured instance of this class.

That does however require me to specify all my annotated packages (there is no recursive scanning here).
It would be way cooler if Spring would recursively scan for annotated packages when using LCEMFB#setPackagesToScan and would then pass them on to a Spring-provided extension of the native JPA provider's PersistenceProvider implementation that knows how to register these annotated packages: for example, by having it's own subtype of the PersistenceProvider interface that is 'package aware' that is supported in addition to the regular PersistenceProvider, with implementations for the common JPA providers.

So, basically, that's my feature request ;)

I haven't checked how this works for other JPA providers, but I assume they should provide similar ways to deal with annotated packages when building up their own EntityManagerFactoryBean from their configuration.


Issue Links:

Referenced from: commits 591f795, 0232739

4 votes, 7 watchers

Metadata

Metadata

Assignees

Labels

in: dataIssues in data modules (jdbc, orm, oxm, tx)type: enhancementA general enhancement

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions