Announcement Announcement Module
Collapse
No announcement yet.
No insert: Spring (3.x), Hibernate (3.5) and JPA (2.0) Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

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

    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

  • #2
    I suggest chapter 3 of the reference guide.

    You are using a BeanFactory where you should be using an ApplicationContext (chapter 3 explains the difference between both).

    This question has been answered numerous times before (by me alone) so the forum search should really provide the answer.

    Comment


    • #3
      I have a similar problem and cannot find any accurate answer to it (search won't help, I cannot find answer in documentation too), so your help will be appreciated, though I understand I might miss some basics. For the reference my test-config.xml looks like this:

      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:context="http://www.springframework.org/schema/context"
      		xmlns:tx="http://www.springframework.org/schema/tx"		
      		xsi:schemaLocation="http://www.springframework.org/schema/beans
      							http://www.springframework.org/schema/beans/spring-beans-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/tx
      							http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
      	
      	<bean id="swDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
      		<property name="driverClassName" value="com.p6spy.engine.spy.P6SpyDriver" />
      		<property name="url" value="jdbc:oracle:thin:@127.0.0.1:1521:SOMESCHEMA"/>
      		<property name="username" value="user"/>
      		<property name="password" value="password"/>	
      	</bean>
      	
      	<bean id="entityManagerFactory"
      		class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
      		<property name="persistenceXmlLocation" value="classpath:META-INF/persistence.xml"/>
      		<property name="dataSource" ref="swDataSource"/>
      		<property name="jpaVendorAdapter">
      			<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
      		</property>
      	</bean>
      	
      	<bean id="jpaDialect" class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"/>
      	
      	<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager" autowire="byName">
      		<property name="entityManagerFactory" ref="entityManagerFactory"/>
      		<property name="dataSource" ref="swDataSource"/>
      		<property name="jpaDialect" ref="jpaDialect"/>
      	</bean>
      	
      	<tx:annotation-driven transaction-manager="transactionManager" />
      		
      	<bean id="kartotekaStudentaService" class="put.datalayer.kartoteka.impl.KartotekaStudentaServiceImpl" autowire="byName" />
      		
      </beans>
      Class KartotekaStudentaServiceImpl does implement KartotekaStudentaService interface which is annotated with @Transactional.

      I wrote the test:
      Code:
      @RunWith(SpringJUnit4ClassRunner.class)
      @ContextConfiguration(locations = { "/META-INF/spring/test-config.xml" })
      @TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = false)
      @Transactional(propagation = Propagation.REQUIRES_NEW)
      public class KartotekaStudentaServiceImplTest {
      
      	private static final Logger log = Logger.getLogger(KartotekaStudentaServiceImplTest.class);
      
      	@Autowired
      	KartotekaStudentaService kartotekaStudentaService;
      
      	@Test
      	@Rollback(false)
      	public void shouldGetOredCollection() {
      		KartotekaStudenta ks = new KartotekaStudenta();
      		ks.setIndeks("TestStudent" + 1);
      		ks.setNazwisko("Jenkins");
      		ks.setImie("Leeroy");
      		ks.setUrodzeniaData(new GregorianCalendar(87, 6, 21).getTime());
      		Miejscowosc urMi = new Miejscowosc();
      		urMi.setId(969400);
      		ks.setUrodzeniaMiejsce(urMi);
      		ks.setCudzoziemiec(false);
      		Panstwo pa = new Panstwo();
      		pa.setId("PL");
      		ks.setPanstwo(pa);
      		ks.setDataPierwszejImmatrykulacji(new Date());
      		ks.setAktywny(true);
      		ks.setSwiadczeniaPrzelewem(true);
      		KartotekaStudenta mks = kartotekaStudentaService.merge(ks);
      		// kartotekaStudentaService.persist(mks);
      	}
      }
      When I run the test there are no errors, transaction is commited but no data is saved (no insert is made after calling merge). I've even tried to persist the object returned by merge, and it does persist (method throws no error) but no insert is called on DB. i've checked everything with db logs, hibernate query logging and p6spy. It won't even try to call insert on database, which would result in errors if no transaction was found.
      What can I do to deal with that problem?

      Comment


      • #4
        I have a very same problem with PostgreSQL 8.4 on Ubuntu 10.10.
        Strangely I "fixed" it by using Oracle 10g XE (insert/delete works).

        May it is somehow related to JDBC driver itself...?

        JBOSS 6.0 CR1
        JPA 2.0 / Hibernate 3.6.0 Final
        Spring 3.0.5 release


        Any idea how to "debug" it?

        Comment


        • #5
          Originally posted by rstribrn View Post
          I have a very same problem with PostgreSQL 8.4 on Ubuntu 10.10.
          Strangely I "fixed" it by using Oracle 10g XE (insert/delete works).

          May it is somehow related to JDBC driver itself...?

          JBOSS 6.0 CR1
          JPA 2.0 / Hibernate 3.6.0 Final
          Spring 3.0.5 release


          Any idea how to "debug" it?
          Hi rstribrn I want to setup an environment like yours but using Windows as the OS. Can you let me know how do you set that up? I am never able to use Spring 3.0.5 release and JPA 2.0/Hibernate 3.6.0 Final together in JBoss 6.0 because of heaps of errors I get. I also have some legacy EJB 2.0 entity beans which I will be migrating to JPA 2 later but for the time being I will leave them there.
          Can you please show me the configuration files? Thank you.
          Last edited by newguy; Dec 23rd, 2010, 06:51 PM.

          Comment


          • #6
            Originally posted by newguy View Post
            Hi rstribrn I want to setup an environment like yours but using Windows as the OS. Can you let me know how do you set that up? I am never able to use Spring 3.0.5 release and JPA 2.0/Hibernate 3.6.0 Final together in JBoss 6.0 because of heaps of errors I get. I also have some legacy EJB 2.0 entity beans which I will be migrating to JPA 2 later but for the time being I will leave them there.
            Can you please show me the configuration files? Thank you.
            Hi, I've decided to share my example project so you can find the source codes here.
            Application context files: **/app-prod-*.xml, most important ones are under trunk/JPA-Spring-JSF/CZU-PEF-DataModelling/ejb-backend/src/main/resources).

            Note: I'm still working on it but the persistence itself is working quite fine...Have fun.

            Comment


            • #7
              Originally posted by rstribrn View Post
              Hi, I've decided to share my example project so you can find the source codes here.
              Application context files: **/app-prod-*.xml, most important ones are under trunk/JPA-Spring-JSF/CZU-PEF-DataModelling/ejb-backend/src/main/resources).

              Note: I'm still working on it but the persistence itself is working quite fine...Have fun.
              Thank you rstibrn. I have already managed to deploy my JPA2 + EJB 2 + spring 3.0 project to JBoss 6.0.0 Final and I finally can have a good holiday. I wish everyone a happy new year too.

              Comment

              Working...
              X