No insert: Spring (3.x), Hibernate (3.5) and JPA (2.0)


Hello everyone,

I'm new to Spring and have one more question about the combination Spring (3.x), Hibernate (3.5) and JPA (2.0).
My objective is to use a plain JPA DAO with Spring transaction management. My problem is that the createUser
method does not cause a database insert.

The DAO:

Code:
public class JpaPlainUserDAO implements UserDAO {

	@PersistenceContext
	private EntityManager entityManager;
  
  
	public void setEntityManager(EntityManager entityManager) {
		this.entityManager = entityManager;
	}
	
	@Transactional(readOnly = false)
	@Override
	public void createUser(User user) {
		entityManager.persist(user);
	}

	@Transactional(readOnly = true)
	@Override
	public User findByPrimaryKey(Long id) {
		return entityManager.find(User.class, id);
	}
}

The User class is an usual entity bean that has a OneToMany relationship to an entity bean Address and some simple
fields.

the spring beans config file:

Code:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	   xmlns:aop="http://www.springframework.org/schema/aop"
	   xmlns:tx="http://www.springframework.org/schema/tx"
	   xmlns:context="http://www.springframework.org/schema/context"
	   xmlns:p="http://www.springframework.org/schema/p"
	   xmlns:jee="http://www.springframework.org/schema/jee"
	   xsi:schemaLocation="http://www.springframework.org/schema/beans
	   			http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
	   			http://www.springframework.org/schema/tx
	   			http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
	   			http://www.springframework.org/schema/context
				http://www.springframework.org/schema/context/spring-context-3.0.xsd
				http://www.springframework.org/schema/jee
				http://www.springframework.org/schema/jee/spring-jee-3.0.xsd">

    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
	<property name="driverClass" value="org.postgresql.Driver"/>
	<property name="jdbcUrl" value="jdbc:postgresql://localhost/testDB"/>
	<property name="user" value="standard"/>
	<property name="password" value="standard"/>
	<!-- ... -->
    </bean>

    <bean id="jpaDialect" class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"/>
	
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="persistenceUnitName" value="testUnit"/>
	<property name="dataSource" ref="dataSource"/>

        <property name="jpaVendorAdapter">
           <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
              <property name="database" value="POSTGRESQL"/>
              <property name="showSql" value="true"/>
              <property name="generateDdl" value="true"/>
           </bean>
        </property>
	<property name="jpaDialect" ref="jpaDialect"/>
    </bean>

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

    <!-- also tried: org.springframework.orm.hibernate3.HibernateTransactionManager -->
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
	<property name="entityManagerFactory" ref="entityManagerFactory"/>
	<property name="dataSource" ref="dataSource"/>
	<property name="jpaDialect" ref="jpaDialect"/>
    </bean>


    <bean id="entityManager" class="org.springframework.orm.jpa.support.SharedEntityManagerBean">
      <property name="entityManagerFactory" ref="entityManagerFactory"/>
    </bean>
	
    <bean id="jpaPlainUserDAO" class="com.test.dao.JpaPlainUserDAO">
	<property name="entityManager" ref="entityManager"/>
    </bean>
	
	
    <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>

</beans>

the persistence.xml

Code:
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
             version="2.0">
			 
	 <persistence-unit name="testUnit" transaction-type="RESOURCE_LOCAL">
		<provider>org.hibernate.ejb.HibernatePersistence</provider>
		
		<class>com.test.entity.User</class>
		<class>com.test.entity.Address</class>
		<exclude-unlisted-classes/>

		<properties>
			<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/>
			<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
			<property name="hibernate.show_sql" value="true"/>				

			<property name="hibernate.connection.url" value="jdbc:postgresql://localhost/testDB"/>
			<property name="hibernate.connection.driver_class" value="org.postgresql.Driver"/>
			<property name="hibernate.connection.username" value="standard"/>
			<property name="hibernate.connection.password" value="standard"/>

		</properties>
	</persistence-unit>
</persistence>

The test client:

Code:
public class UserDaoTest {

	private BeanFactory jpaBeanFactory = null;

	@Before
	public void setUp() throws Exception {
		//hibernateBeanFactory = new XmlBeanFactory(new ClassPathResource("spring3-hibernate.xml"));
		jpaBeanFactory = new XmlBeanFactory(new ClassPathResource("spring3-entity.xml"));//spring3-entity spring3-jpa2.xml
	}


	@Test
	public void testJpaPlainUserDAO() {
		UserDAO userDAO = (UserDAO)jpaBeanFactory.getBean("jpaPlainUserDAO");
		log.debug(userDAO.getClass().getName());

		User u = userDAO.findByPrimaryKey(new Long(1));
		
		log.debug("user="+u); 
		// u is null after DB was completely refreshed making shure that PK value 1 is the PK of the
		// not existing User :-(
	}


	@Test
	public void testJpaPlainUserDAOManual() {
		UserDAO userDAO = (UserDAO)jpaBeanFactory.getBean("jpaPlainUserDAO");
		log.debug(userDAO.getClass().getName());
		
		JpaTransactionManager transactionManager = (JpaTransactionManager)jpaBeanFactory.getBean("transactionManager");
		TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition());
		User user = newUser();
		userDAO.createUser(user);
		transactionManager.commit(status);
		
		User u = userDAO.findByPrimaryKey(new Long(1));

		log.debug("user="+u);
		// u is NOT null
	}
}

When I use manual transaction management, the User entity is inserted in method testJpaPlainUserDAOManual.
I clearly prefer the spring transaction managed solution. Unfortunately, the Hibernate enabled logging
issues no insert log statement:

Hibernate: select nextval ('hibernate_sequence')
Hibernate: select nextval ('hibernate_sequence')
Hibernate: select nextval ('hibernate_sequence')
Hibernate: select nextval ('hibernate_sequence')

4 times because of 1 user and 3 address entities, but no Hibernate: insert into ...


In contrast to the testJpaPlainUserDAOManual method:

Hibernate: select nextval ('hibernate_sequence')
Hibernate: select nextval ('hibernate_sequence')
Hibernate: select nextval ('hibernate_sequence')
Hibernate: select nextval ('hibernate_sequence')
Hibernate: insert into table_user (creationdate, firstname, lastname, id) values (?, ?, ?, ?)
...


What is wrong with my configuration? I read already countless forum posts with very similar problems,
tutorials and books, but I can't figure out what is missing.


Kind regards,

Andreas