24

I'm trying to set up a Spring JPA Hibernate simple example WAR for deployment to Glassfish. I see some examples use a persistence.xml file, and other examples do not. Some examples use a dataSource, and some do not. So far my understanding is that a dataSource is not needed if I have:

<persistence-unit name="educationPU"
    transaction-type="JTA">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <class>com.coe.jpa.StudentProfile</class>
    <properties>
        <property name="hibernate.connection.driver_class"
            value="com.mysql.jdbc.Driver" />
        <property name="hibernate.connection.url"
            value="jdbc:mysql://localhost:3306/COE" />
        <property name="hibernate.connection.username" value="root" />
        <property name="show_sql" value="true" />
        <property name="dialect" value="org.hibernate.dialect.MySQLDialect" />
    </properties>
</persistence-unit>

I can deploy fine, but my EntityManager is not getting injected by Spring.

My applicationContext.xml:

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
    <property name="persistenceUnitName" value="educationPU" />
</bean>

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>

<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />

<tx:annotation-driven transaction-manager="transactionManager" />

<bean id="StudentProfileDAO" class="com.coe.jpa.StudentProfileDAO">
    <property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>

<bean id="studentService" class="com.coe.services.StudentService">
</bean>

My class with the EntityManager:

public class StudentService {
private String  saveMessage;
private String  showModal;
private String modalHeader;
private StudentProfile studentProfile;
private String lastName;
private String firstName;

@PersistenceContext(unitName="educationPU")
private EntityManager em;

@Transactional
public String save()
{
    System.out.println("*** em: " + this.em); //em is null
    this.studentProfile= new StudentProfile();
    this.saveMessage = "saved";
    this.showModal = "true";
    this.modalHeader= "Information Saved";
    return "successs";
}

My web.xml:

  <listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

Are there any pieces I am missing to have Spring inject "em" in to StudentService?

5 Answers 5

13

Just to confirm though you probably did...

Did you include the

<!--  tell spring to use annotation based congfigurations -->
<context:annotation-config />
<!--  tell spring where to find the beans -->
<context:component-scan base-package="zz.yy.abcd" />

bits in your application context.xml?

Also I'm not so sure you'd be able to use a jta transaction type with this kind of setup? Wouldn't that require a data source managed connection pool? So try RESOURCE_LOCAL instead.

4

I'm confused. You're injecting a PU into the service layer and not the persistence layer? I don't get that.

I inject the persistence layer into the service layer. The service layer contains business logic and demarcates transaction boundaries. It can include more than one DAO in a transaction.

I don't get the magic in your save() method either. How is the data saved?

In production I configure spring like this:

<jee:jndi-lookup id="entityManagerFactory" jndi-name="persistence/ThePUname" />

along with the reference in web.xml

For unit testing I do this:

<bean id="entityManagerFactory"
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
    p:dataSource-ref="dataSource" p:persistence-xml-location="classpath*:META-INF/test-persistence.xml"
    p:persistence-unit-name="RealPUName" p:jpaDialect-ref="jpaDialect"
    p:jpaVendorAdapter-ref="jpaVendorAdapter" p:loadTimeWeaver-ref="weaver">
</bean>
3

If anyone wants to use purely Java configuration instead of xml configuration of hibernate, use this:

You can configure Hibernate without using persistence.xml at all in Spring like like this:

@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean()
{
Map<String, Object> properties = new Hashtable<>();
properties.put("javax.persistence.schema-generation.database.action",
"none");
HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
adapter.setDatabasePlatform("org.hibernate.dialect.MySQL5InnoDBDialect"); //you can change this if you have a different DB
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setJpaVendorAdapter(adapter);
factory.setDataSource(this.springJpaDataSource());
factory.setPackagesToScan("package name");
factory.setSharedCacheMode(SharedCacheMode.ENABLE_SELECTIVE);
factory.setValidationMode(ValidationMode.NONE);
factory.setJpaPropertyMap(properties);
return factory;
}

Since you are not using persistence.xml, you should create a bean that returns DataSource which you specify in the above method that sets the data source:

@Bean
public DataSource springJpaDataSource()
{
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setUrl("jdbc:mysql://localhost/SpringJpa");
dataSource.setUsername("tomcatUser");
dataSource.setPassword("password1234");
return dataSource;
}

Then you use @EnableTransactionManagement annotation over this configuration file. Now when you put that annotation, you have to create one last bean:

@Bean
public PlatformTransactionManager jpaTransactionManager()
{
return new JpaTransactionManager(
this.entityManagerFactoryBean().getObject());
}

Now, don't forget to use @Transactional Annotation over those method that deal with DB.

Lastly, don't forget to inject EntityManager in your repository (This repository class should have @Repository annotation over it).

1
  • Thanks working finally! Looks like HibernateJpaVendorAdapter is the key to specify the dialect. Haven't seen any documents/examples mentioning it.
    – Adam D.
    Commented May 17 at 2:16
0

I have a test application set up using JPA/Hibernate & Spring, and my configuration mirrors yours with the exception that I create a datasource and inject it into the EntityManagerFactory, and moved the datasource specific properties out of the persistenceUnit and into the datasource. With these two small changes, my EM gets injected properly.

-2

This may be old, but if anyone has the same problem try changing unitname to just name in the PersistenceContext annotation:

From

@PersistenceContext(unitName="educationPU")

to

@PersistenceContext(name="educationPU")
1
  • 10
    Huh? The optional name attribute of @PersistenceContext is used to look up the injected entity manager. It has no corresponding element in persistence.xml. If this worked for you, this is IMO just a lucky side effect related to the absence of unitName (the behavior in this case is vendor-specific). But this is not correct. Commented Jul 14, 2010 at 23:02

Not the answer you're looking for? Browse other questions tagged or ask your own question.