title: Entities Not Persisting - Spring + Hibernate + JPA
body: <p>I'm using Spring + Hibernate + JPA and I have a situation where I can't get my entities to persist to the database. I've set up a service class that is annotated with @Transactional. It uses a DAO that contains an injected EntityManager. When I call the function on the service object I see a bunch of selects for the reads the DAO is doing, but no updates/deletes as a result of merges and removes issued by my DAO. Surely there's something wrong with my setup, but I can't see it.</p>
  
  <p>persistence.xml</p>
  
  <pre><code>&lt;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_1_0.xsd"
      version="1.0"&gt;
      &lt;persistence-unit name="pu"&gt;
          &lt;properties&gt;
              &lt;property name="hibernate.dialect" value="org.hibernate.dialect.InformixDialect" /&gt;
              &lt;property name="hibernate.cache.provider_class" value="org.hibernate.cache.NoCacheProvider" /&gt;
              &lt;property name="hibernate.showsql" value="true" /&gt;
              &lt;property name="hibernate.cache.use_second_level_cache"
                  value="false" /&gt;
          &lt;/properties&gt;
      &lt;/persistence-unit&gt;
  </code></pre>
  
  <p>config.xml</p>
  
  <pre><code>&lt;beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:security="http://www.springframework.org/schema/security"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      xmlns:tx="http://www.springframework.org/schema/tx"
      xmlns:p="http://www.springframework.org/schema/p"
      xmlns:context="http://www.springframework.org/schema/context"
      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/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
                  http://www.springframework.org/schema/security
                  http://www.springframework.org/schema/security/spring-security-3.0.3.xsd
                  http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"&gt;
  
      &lt;bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
          destroy-method="close"&gt;
          &lt;property name="driverClassName" value="org.postgresql.Driver" /&gt;
          &lt;property name="url" value="jdbc:postgresql://localhost:5432/testdb" /&gt;  
          &lt;property name="username" value="username" /&gt;
          &lt;property name="password" value="password" /&gt;
      &lt;/bean&gt;
  
      &lt;bean id="entityManagerFactory"
          class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"&gt;
          &lt;property name="persistenceUnitName" value="pu" /&gt;
          &lt;property name="dataSource" ref="dataSource" /&gt;
          &lt;property name="jpaVendorAdapter"&gt;
              &lt;bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"&gt;
                  &lt;property name="showSql" value="true" /&gt;
                  &lt;property name="databasePlatform" value="org.hibernate.dialect.PostgreSQLDialect" /&gt;
              &lt;/bean&gt;
          &lt;/property&gt;
          &lt;property name="loadTimeWeaver"&gt;
              &lt;bean
                  class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver"/&gt;
          &lt;/property&gt;
      &lt;/bean&gt;
  
      &lt;bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"
          p:entityManagerFactory-ref="entityManagerFactory" /&gt;
  
      &lt;bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/&gt;
  
      &lt;tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/&gt;
  
      &lt;context:annotation-config/&gt;
      &lt;/beans&gt;
  </code></pre>
  
  <p>AccountService.java</p>
  
  <pre><code>@Service("accountService")
  @Transactional(propagation=Propagation.REQUIRED)
  public class AccountService {
  
      private static final Logger log = Logger.getLogger(AccountService.class);
  
      @Autowired
      private UserDAO userDAO;
  
      public void activateUser(String username, String activationCode) {
          PendingActivation pendingActivation = userDAO.getPendingActivation(
                  username, activationCode);
  
              Client client = pendingActivation.getClient();
  
              if (!userDAO.removePendingActivation(pendingActivation)) {
                  log.warn("Unable to remove pending activation");
              }
  
              if (!userDAO.enableUser(client)) {
                  log.error("Unable to enable client");
                  return;
              }
  
              return;
          }
      }
  </code></pre>
  
  <p>UserDAOImpl.java</p>
  
  <pre><code>@Repository("userDAO")
  public class UserDAOImpl implements UserDAO, Serializable {
  
      private static final long serialVersionUID = 1L;
  
      private static Logger log = Logger.getLogger(UserDAOImpl.class);
  
      @PersistenceContext
      EntityManager em;
  
      @Override 
      public PendingActivation getPendingActivation(String username, String activationCode) {
          Query q = em.createNamedQuery("getActivationCode")
              .setParameter("activationCode", activationCode);
  
          PendingActivation pendingActivation = null;
          try {
              pendingActivation = (PendingActivation)q.getSingleResult();
              return pendingActivation;
          }
          catch (Exception e) {
              log.warn("Could not retrieve activation code " + activationCode + " for user " + username, e);
              return null;
          }
      }
  
      @Override
      public boolean enableUser(Client client) {
  
          try {
              client.setEnabled(true);
              client = em.merge(client);   // this never generates an update
          }
          catch(Exception e) {
              log.error("Unable to enable client: " + client.getUsername(), e);
              return false;
          }
  
          return true;
      }
  
      @Override
      public boolean removePendingActivation(PendingActivation pendingActivation) {
          try {
              pendingActivation = (PendingActivation)em.getReference(PendingActivation.class, pendingActivation.getPendingActivationId());
              em.remove(pendingActivation);  // this never generates a delete
          }
          catch(Exception e) {
              log.warn("Unable to remove activation: " + pendingActivation.getActivationCode(), e);
              return false;
          }
  
          return true;
      }
  }
  </code></pre>
  
  <p>AccountActivationController.java</p>
  
  <pre><code>@Controller
  public class AccountActivationController {
  
      @Autowired
      @Qualifier("accountService")
      AccountService accountService;
  
      @RequestMapping("activate.do")
      public String doActivate(
              @RequestParam("activationCode") String activationCode,
              @RequestParam("username") String username,
              ModelMap model) {
  
          UnitCriteria unitCriteria = accountService.activateUser(username, activationCode);
  
          if (unitCriteria == null) {
              return "account/activationError";
          }
  
          model.addAttribute("fromActivation", true);
          return "forward:search.do?" + unitCriteria.toUrlParams(true);
      }
  
  }
  </code></pre>