6

I met the problem of persisting element to database using EntityManager. Based on the answers I found, I tried those 4 ways in my DaoJpa to do such thing but still failed. Here I attached the four ways I tried:

Code in Controller part:

   @Transactional 
   SmartProduct smartProduct = new SmartProduct();
            smartProduct.setName("Dove Soap");
            smartProductDao.persist(smartProduct);

1. DaoJpa:

 @Transactional
 public void persist(SmartProduct smartProduct) {
            entityManager.persist(smartProduct);

Doesn't work!

2.

@Transactional
public void persist(SmartProduct smartProduct) {
entityManager.persist(smartProduct);
entityManager.flush();

Exception I got: no transaction is in progress

3.

@Transactional
public void persist(SmartProduct smartProduct) {
EntityTransaction emTransaction = entityManager.getTransaction();
        emTransaction.begin();  
        entityManager.persist(smartProduct);
        emTransaction.commit();
        entityManager.close();

Exception I got: Not allowed to create transaction on shared EntityManager - use Spring transactions or EJB CMT instead

4.

@Transactional
public void persist(SmartProduct smartProduct) {
                    EntityManagerFactory emf = Persistence.createEntityManagerFactory("persistenceUnit");
                EntityManager em = emf.createEntityManager();
                EntityTransaction etx = em.getTransaction();
                etx.begin();
                em.persist(smartProduct);
                etx.commit();
                em.close();
                emf.close();

Exception I got: The application must supply JDBC connections

Could someone help me figure out the problem please? Many thanks in advance!

Many thanks JustinKSU's help. I add the annotation in Spring context and then it solved! Here is the previous version of my Spring context:

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

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

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

After added the

<tx:annotation-driven />

it works:

<tx:annotation-driven />
    <bean class="org.springframework.orm.jpa.JpaTransactionManager" id="transactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory" />
    </bean>

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

    <bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory">
        <property name="persistenceUnitName" value="persistenceUnit" />
        <property name="dataSource" ref="dataSource" />
    </bean>
Emil Laine
  • 41,598
  • 9
  • 101
  • 157
Qingshan Zhang
  • 245
  • 1
  • 3
  • 12
  • 1
    Have you tried using @Transactional on the persist method? – JustinKSU Oct 17 '12 at 15:07
  • Sorry I forgot to mention it in the post. Yes I added @Transactional before the method in all the four ways. Also I tried to add (readOnly = true)/(readOnly = false)after Transactional annotation, and even added (propagation = Propagation.REQUIRED) as well, but seems no difference. – Qingshan Zhang Oct 17 '12 at 15:11
  • Are you using @PersistenceContext to inject the entityManager? – JustinKSU Oct 17 '12 at 15:13
  • Yes I added it at the beginning of the controller: @PersistenceContext private EntityManager entityManager; – Qingshan Zhang Oct 17 '12 at 15:14
  • If you are using annotations do you have this in your Spring context along with defining a transactionManager injecting the entity manager? – JustinKSU Oct 17 '12 at 15:15
  • I checked the beans in Spring Elements, and under the section of Transactional there is "context:component-scan smartProductDaoJpa" which is the Jpa I use entityManager to persist things. but not sure whether is this the context you mentioned – Qingshan Zhang Oct 17 '12 at 15:19

2 Answers2

9

To enable @Transactional in your Spring context you should have the following:

Appropriate for your version of Spring:

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    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/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

Enable the annotations:

<tx:annotation-driven />

Declare your transaction manager injecting your entity manager:

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
JustinKSU
  • 4,875
  • 2
  • 29
  • 51
  • I found that the annotation in my spring context is like this: should I modified any in this? – Qingshan Zhang Oct 17 '12 at 15:29
  • 3
    Try removing the mode parameter in going with the default mode="proxy" – JustinKSU Oct 17 '12 at 15:40
  • Wow Thank you so much @JustinKSU I solve the problem now! It's exactly the problem of annotations! Maybe I should attached the content of my spring context below to help others who might also meet similar problem. Anyway, many many thanks for your kindly help! – Qingshan Zhang Oct 17 '12 at 15:54
  • @JustinKSU I tried as per your answer Please see http://pastie.org/9977330 and when I run it then I get error like it http://pastie.org/9977329 – SpringLearner Feb 24 '15 at 06:30
  • @SpringLearner I suggest you ask your own question and the community may be able to help you. Comments is not meant for things like this. In your question you can link this answer if you feel it is relevant. Off the top of my head, a common issue is having a mix of Spring versions. – JustinKSU Feb 24 '15 at 16:44
  • @JustinKSU I have already posted a question http://stackoverflow.com/questions/28667550/how-to-rollback-in-entitymanager-createnativemethod Hope you can help there – SpringLearner Feb 25 '15 at 04:44
1

If you still have this problem and all the configurations are ok, please make sure that the @Transaction annotated method is public, not protected in order to be identified/managed by the transaction manager.

Criss
  • 11
  • 1
  • 2
  • As per the code snippets in OP's post all methods are `public`. Also it states that when added `` solves the problem. I don't see your answer adding anything to the discussion. – bhantol Sep 16 '14 at 20:34
  • 2
    Maybe this answer could help other developers ?! – Criss Apr 01 '15 at 17:45