30

My entityManager persist() gets id from sequence and puts it to my Image object but the Image object itself is not showing up in the database. EntityManager.flush() gives an error so I can't commit this way. Here is my code.

@Repository
public class ImageDaoImpl extends BaseDao implements ImageDao {

@PersistenceContext
protected EntityManager entityManager;

@Override
@Transactional
public void create(Image image) {       
    JpaTemplate jpaTemplate = getJpaTemplate(entityManager);
    jpaTemplate.persist(image);
}

 

@Repository
public class BaseDao {

private JpaTemplate jpaTemplate;


public JpaTemplate getJpaTemplate(EntityManager entityManager){
    if(jpaTemplate == null)
        jpaTemplate = new JpaTemplate(entityManager);
    return jpaTemplate;
}

 

<bean id="entityManagerFactory"
       class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
       p:dataSource-ref="dataSource">
       <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <property name="showSql" value="true" />
                <property name="generateDdl" value="true" />
                <property name="databasePlatform" value="org.hibernate.dialect.PostgreSQLDialect" />
            </bean>
        </property>
        <property name="persistenceUnitName" value="sample"></property>
    </bean>



    <!-- DataSource Setup -->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="org.postgresql.Driver" />
        <property name="url" value="jdbc:postgresql://localhost:5432/imageCapture" />
        <property name="username" value="myusername" />
        <property name="password" value="mypassword" />
    </bean>


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

    <tx:annotation-driven transaction-manager="transactionManager" />
ivar
  • 819
  • 4
  • 12
  • 19

6 Answers6

32

This generally happens when Transaction in not applied.. I doubt @Transactional interceptor is not intercepting properly.

Premraj
  • 7,802
  • 8
  • 45
  • 66
  • 7
    One more thing to check: Be sure, `@Transactional` annotation is from package `org.springframework.transaction.annotation`, not `javax.transaction` - the second one wasn't working in my case. – Gondy Dec 15 '16 at 13:55
  • 2
    @Gondy you sir, have just put an end to my 2 hour long misery. Thank you very much ! – Sikorski Nov 15 '18 at 10:41
  • @Gondy Spring also added support for javax.transaction.Transactional, now one could use that too in Spring applications. Just don't mix the two and be consistent about your choice! – Balu Mar 24 '21 at 16:01
30

persist() means "add object to list of managed entries". To save object to data base you must call flush() method. But remember you must call in inside the transaction.

//Edit: Example save method.

public void save(T t){
    // begin transaction 
    em.getTransaction().begin();
    if (!em.contains(t)) {
        // persist object - add to entity manager
        em.persist(t);
        // flush em - save to DB
        em.flush();
    }
    // commit transaction at all
    em.getTransaction().commit();
}

This is not the best that you can make, but good enough.

Michu93
  • 5,058
  • 7
  • 47
  • 80
Koziołek
  • 2,791
  • 1
  • 28
  • 48
2

Check your server logs. Are you creating new EntityManger? and have not begun the transaction. I think, Where you have begun that is another EntityManager object.

Atul Jain
  • 1,035
  • 2
  • 16
  • 24
2

Check EntityManager object is not getting created twice. In my case I was initialize EntityManager object in one method and mistakenly calling that method twice during opening transaction and persisting data.

Incorrect code:

EntityTrasaction transaction = getEntityManager().getTransaction().begin();
getEntityManager().persist(customer); // This line is calling another object of EntityManager
transaction.commit();

Correct code:

EntityManager em = getEntityManager();
EntityTransaction transaction = em.getTransaction();
transaction.begin();
em.persist(customer);
transaction.commit();

public EntityManager getEntityManager(){
    EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("punit");
    return entityManagerFactory.createEntityManager();
}
Shredator
  • 940
  • 3
  • 17
  • 32
Rahul
  • 21
  • 3
0

Check your mvc-dispatcher-servlet.xml . Here in <context:component-scan base-package="pass"/> pass should equal to package where your controllers are

zafezo
  • 1
  • 1
0

I faced this problem in when running test cases with SpringJUnit4ClassRunner

I solved it by wrapping the test function with

@Autowired
private PlatformTransactionManager transactionManager;

// in your test funciton 
// Declare a transaction programmatically to be able to rollback.
DefaultTransactionDefinition transactionDefinition = new DefaultTransactionDefinition();
transactionDefinition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
TransactionStatus transaction = transactionManager.getTransaction(transactionDefinition);

try {
    // here test of Dao goes
} finally {
    transactionManager.rollback(transaction);
}

hope this helps you

Basheer AL-MOMANI
  • 14,473
  • 9
  • 96
  • 92