Chris Lacy's Software Engineering Blog
Hibernate using JPA Annotations in One Eclipse Project
I finally put together a small Java web app that has all of my favorite tools: Spring, Hibernate, JPA annotations, and Maven (m2eclipse); all in one Eclipse project. If you've ever tried to get these to work together you know it can be a hassle. Recent improvements in m2eclipse have made things a lot easier. For this blog entry I want to share with you one of the last pieces of my puzzle.
My understanding is that the Spring/Hibernate combination works in two modes: Hibernate and JPA. In both modes you can scan for annotated entities, but in the JPA mode the scan depends on EJB3 package compilation artifacts. I could have tried creating a separate project for the EJBs, but imo that's too much work, especially when you get Maven involved. Instead, I dove into the Spring and Hibernate internals and hacked together my own solution. Then, of course, I read this blog post (warning, language), and followed up by exploring loom. They use a bean post processor, which is much cleaner than my hack. Here's the low down:
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
p:dataSource-ref="dataSource">
<property name="persistenceUnitPostProcessors">
<bean class="net.chrislacy.webapp.HibernateJpaPostProcessor" p:packages="net.chrislacy.webapp"/>
</property>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"
p:database="HSQL"
p:showSql="false"
p:generateDdl="true">
</bean>
</property>
<property name="persistenceXmlLocation" value="/META-INF/persistence.xml" />
</bean>
public class HibernateJpaPostProcessor implements PersistenceUnitPostProcessor, InitializingBean {
private ClassPathScanningCandidateComponentProvider provider;
private String[] packages = new String[] {};
/**
* Search for persistent classes under the configured folders and register
* them in the persistence unit.
*/
public void postProcessPersistenceUnitInfo(MutablePersistenceUnitInfo unit) {
for (String pakage : packages) {
for (BeanDefinition bean : provider.findCandidateComponents(pakage)) {
unit.addManagedClassName(bean.getBeanClassName());
}
}
}
public void afterPropertiesSet() {
if (provider == null) {
provider = new ClassPathScanningCandidateComponentProvider(false);
provider.addIncludeFilter(new AnnotationTypeFilter(Entity.class, false));
}
}
public void setProvider(ClassPathScanningCandidateComponentProvider provider) {
this.provider = provider;
}
public void setPackages(String[] packages) {
this.packages = packages;
}
}
Posted at 08:21PM Sep 07, 2008 by chris in General |